]> gcc.gnu.org Git - gcc.git/blame - libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
[multiple changes]
[gcc.git] / libjava / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkWindowPeer.c
CommitLineData
5aac1dac 1/* gtkwindowpeer.c -- Native implementation of GtkWindowPeer
2c20a171 2 Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
5aac1dac
TT
3
4This file is part of GNU Classpath.
5
6GNU Classpath is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Classpath is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Classpath; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1902111-1307 USA.
20
21Linking this library statically or dynamically with other modules is
22making a combined work based on this library. Thus, the terms and
23conditions of the GNU General Public License cover the whole
24combination.
25
26As a special exception, the copyright holders of this library give you
27permission to link this library with independent modules to produce an
28executable, regardless of the license terms of these independent
29modules, and to copy and distribute the resulting executable under
30terms of your choice, provided that you also meet, for each linked
31independent module, the terms and conditions of the license of that
32module. An independent module is a module which is not derived from
33or based on this library. If you modify this library, you may extend
34this exception to your version of the library, but you are not
35obligated to do so. If you do not wish to do so, delete this
36exception statement from your version. */
37
38
39#include "gtkpeer.h"
834b1209 40#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
5aac1dac
TT
41#include "gnu_java_awt_peer_gtk_GtkWindowPeer.h"
42#include "gnu_java_awt_peer_gtk_GtkFramePeer.h"
43#include <gdk/gdkprivate.h>
44#include <gdk/gdkx.h>
f2d0e05d
TF
45#include <X11/Xatom.h>
46
86881a7b
GH
47static int filter_added = 0;
48
49static GdkFilterReturn window_wm_protocols_filter (GdkXEvent *xev,
50 GdkEvent *event,
51 gpointer data);
52
db19e39b
TF
53static void window_get_frame_extents (GtkWidget *window,
54 int *top, int *left,
55 int *bottom, int *right);
56
57static void request_frame_extents (GtkWidget *window);
58
59static int property_notify_predicate (Display *xdisplay,
60 XEvent *event,
61 XPointer window_id);
62
f2d0e05d
TF
63static void window_delete_cb (GtkWidget *widget, GdkEvent *event,
64 jobject peer);
65static void window_destroy_cb (GtkWidget *widget, GdkEvent *event,
66 jobject peer);
67static void window_show_cb (GtkWidget *widget, jobject peer);
86881a7b
GH
68static void window_focus_or_active_state_change_cb (GtkWidget *widget,
69 GParamSpec *pspec,
70 jobject peer);
f2d0e05d
TF
71static gboolean window_window_state_cb (GtkWidget *widget,
72 GdkEvent *event,
73 jobject peer);
74static jint window_get_new_state (GtkWidget *widget);
db19e39b
TF
75static gboolean window_property_changed_cb (GtkWidget *widget,
76 GdkEventProperty *event,
77 jobject peer);
5aac1dac 78
5aac1dac 79/*
b59b5081 80 * Make a new window.
5aac1dac
TT
81 */
82
83JNIEXPORT void JNICALL
84Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
b59b5081 85 (JNIEnv *env, jobject obj, jint type, jboolean decorated,
db19e39b 86 jint width, jint height, jobject parent, jintArray jinsets)
5aac1dac 87{
b59b5081
TF
88 GtkWidget *window_widget;
89 GtkWindow *window;
90 void *window_parent;
db19e39b
TF
91 GtkWidget *vbox;
92 GtkWidget *layout;
93 int top = 0;
94 int left = 0;
95 int bottom = 0;
96 int right = 0;
97 jint *insets;
98
99 insets = (*env)->GetIntArrayElements (env, jinsets, 0);
100 insets[0] = insets[1] = insets[2] = insets[3] = 0;
5aac1dac 101
7ecd4576
FN
102 /* Create global reference and save it for future use */
103 NSA_SET_GLOBAL_REF (env, obj);
104
5aac1dac 105 gdk_threads_enter ();
7ecd4576 106
b59b5081
TF
107 window_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
108 window = GTK_WINDOW (window_widget);
5aac1dac 109
b59b5081
TF
110 /* Keep this window in front of its parent, if it has one. */
111 if (parent)
112 {
113 window_parent = NSA_GET_PTR (env, parent);
114 gtk_window_set_transient_for (window, GTK_WINDOW(window_parent));
115 }
116
117 gtk_window_set_decorated (window, decorated);
118
119 gtk_window_set_type_hint (window, type);
120
23a555b0
TF
121 gtk_window_group_add_window (global_gtk_window_group, window);
122
5aac1dac
TT
123 vbox = gtk_vbox_new (0, 0);
124 layout = gtk_layout_new (NULL, NULL);
125 gtk_box_pack_end (GTK_BOX (vbox), layout, 1, 1, 0);
b59b5081 126 gtk_container_add (GTK_CONTAINER (window_widget), vbox);
5aac1dac
TT
127
128 gtk_widget_show (layout);
129 gtk_widget_show (vbox);
db19e39b
TF
130 gtk_widget_realize (window_widget);
131
132 if (decorated)
133 window_get_frame_extents (window_widget, &top, &left, &bottom, &right);
134
135 gtk_window_set_default_size (window,
136 MAX (1, width - left - right),
137 MAX (1, height - top - bottom));
138
139 /* We must set this window's size requisition. Otherwise when a
140 resize is queued (when gtk_widget_queue_resize is called) the
141 window will snap to its default requisition of 0x0. If we omit
142 this call, Frames and Dialogs shrink to degenerate 1x1 windows
143 when their resizable property changes. */
144 gtk_widget_set_size_request (window_widget,
145 MAX (1, width - left - right),
146 MAX (1, height - top - bottom));
147
148 insets[0] = top;
149 insets[1] = left;
150 insets[2] = bottom;
151 insets[3] = right;
5aac1dac 152
86881a7b
GH
153 /* We must filter out WM_TAKE_FOCUS messages. Otherwise we get two
154 focus in events when a window becomes active and two focus out
155 events when a window becomes inactive. */
156 if (!filter_added)
157 {
158 GdkAtom wm_protocols_atom =
159 gdk_x11_xatom_to_atom (gdk_x11_get_xatom_by_name ("WM_PROTOCOLS"));
160
161 gdk_add_client_message_filter (wm_protocols_atom,
162 window_wm_protocols_filter,
163 NULL);
164 filter_added = 1;
165 }
166
5aac1dac
TT
167 gdk_threads_leave ();
168
db19e39b
TF
169 (*env)->ReleaseIntArrayElements (env, jinsets, insets, 0);
170
b59b5081 171 NSA_SET_PTR (env, obj, window_widget);
5aac1dac
TT
172}
173
834b1209
FN
174JNIEXPORT void JNICALL
175Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible
5aac1dac
TT
176 (JNIEnv *env, jobject obj, jboolean visible)
177{
178 void *ptr;
179
180 ptr = NSA_GET_PTR (env, obj);
181
182 gdk_threads_enter ();
183
184 if (visible)
185 gtk_widget_show (GTK_WIDGET (ptr));
186 else
187 gtk_widget_hide (GTK_WIDGET (ptr));
188
189 XFlush (GDK_DISPLAY ());
5ec47f60 190
5aac1dac
TT
191 gdk_threads_leave ();
192}
193
834b1209
FN
194JNIEXPORT void JNICALL
195Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectJObject
5aac1dac
TT
196 (JNIEnv *env, jobject obj)
197{
198 void *ptr;
48c2d88a 199 GtkWidget* vbox, *layout;
29e531ff 200 GList* children;
48c2d88a 201
5aac1dac
TT
202 ptr = NSA_GET_PTR (env, obj);
203
204 gdk_threads_enter ();
29e531ff 205
5ec47f60
TF
206 children = gtk_container_get_children(GTK_CONTAINER(ptr));
207 vbox = children->data;
9deab0b7 208 g_assert (GTK_IS_VBOX(vbox));
48c2d88a 209
5ec47f60 210 children = gtk_container_get_children(GTK_CONTAINER(vbox));
a2708c12
KH
211 do
212 {
213 layout = children->data;
214 children = children->next;
215 }
216 while (!GTK_IS_LAYOUT (layout) && children != NULL);
9deab0b7 217 g_assert (GTK_IS_LAYOUT(layout));
29e531ff 218
5aac1dac 219 gtk_widget_realize (layout);
29e531ff 220
5aac1dac 221 connect_awt_hook (env, obj, 1, GTK_LAYOUT (layout)->bin_window);
eb2a5f91
TF
222
223 gtk_widget_realize (ptr);
29e531ff 224
5aac1dac 225 connect_awt_hook (env, obj, 1, GTK_WIDGET (ptr)->window);
eb2a5f91 226
834b1209
FN
227 gdk_threads_leave ();
228}
229
230JNIEXPORT void JNICALL
231Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals
232 (JNIEnv *env, jobject obj)
233{
7ecd4576
FN
234 void *ptr = NSA_GET_PTR (env, obj);
235 jobject *gref = NSA_GET_GLOBAL_REF (env, obj);
ca3bb0c2
GH
236 GtkWidget* vbox, *layout;
237 GList* children;
7ecd4576 238 g_assert (gref);
834b1209
FN
239
240 gdk_threads_enter ();
241
242 gtk_widget_realize (ptr);
243
ca3bb0c2
GH
244 /* Receive events from the GtkLayout too */
245 children = gtk_container_get_children(GTK_CONTAINER(ptr));
246 vbox = children->data;
9deab0b7
TF
247 g_assert (GTK_IS_VBOX (vbox));
248
ca3bb0c2 249 children = gtk_container_get_children(GTK_CONTAINER(vbox));
9deab0b7
TF
250 do
251 {
252 layout = children->data;
253 children = children->next;
254 }
255 while (!GTK_IS_LAYOUT (layout) && children != NULL);
256 g_assert (GTK_IS_LAYOUT (layout));
ca3bb0c2
GH
257
258 g_signal_connect (GTK_OBJECT (layout), "event",
259 G_CALLBACK (pre_event_handler), *gref);
260
f2d0e05d
TF
261 /* Connect signals for window event support. */
262 g_signal_connect (G_OBJECT (ptr), "delete-event",
7ecd4576 263 G_CALLBACK (window_delete_cb), *gref);
f2d0e05d
TF
264
265 g_signal_connect (G_OBJECT (ptr), "destroy-event",
7ecd4576 266 G_CALLBACK (window_destroy_cb), *gref);
f2d0e05d
TF
267
268 g_signal_connect (G_OBJECT (ptr), "show",
7ecd4576 269 G_CALLBACK (window_show_cb), *gref);
f2d0e05d 270
86881a7b
GH
271 g_signal_connect (G_OBJECT (ptr), "notify",
272 G_CALLBACK (window_focus_or_active_state_change_cb), *gref);
f2d0e05d
TF
273
274 g_signal_connect (G_OBJECT (ptr), "window-state-event",
7ecd4576 275 G_CALLBACK (window_window_state_cb), *gref);
f2d0e05d 276
9deab0b7
TF
277 g_signal_connect (G_OBJECT (ptr), "property-notify-event",
278 G_CALLBACK (window_property_changed_cb), *gref);
279
5aac1dac 280 gdk_threads_leave ();
834b1209
FN
281
282 /* Connect the superclass signals. */
283 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals (env, obj);
5aac1dac
TT
284}
285
5aac1dac
TT
286/*
287 * Lower the z-level of a window.
288 */
289
290JNIEXPORT void JNICALL
291Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv *env,
292 jobject obj)
293{
294 void *ptr;
295 ptr = NSA_GET_PTR (env, obj);
296
297 gdk_threads_enter ();
298 gdk_window_lower (GTK_WIDGET (ptr)->window);
299
300 XFlush (GDK_DISPLAY ());
301 gdk_threads_leave ();
302}
303
304/*
305 * Raise the z-level of a window.
306 */
307
308JNIEXPORT void JNICALL
309Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env,
310 jobject obj)
311{
312 void *ptr;
313 ptr = NSA_GET_PTR (env, obj);
314
315 gdk_threads_enter ();
316 gdk_window_raise (GTK_WIDGET (ptr)->window);
317
318 XFlush (GDK_DISPLAY ());
319 gdk_threads_leave ();
320}
321
b59b5081
TF
322JNIEXPORT void JNICALL
323Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBoundsCallback
ce7a72c8
TF
324 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
325 jobject window, jint x, jint y, jint width, jint height)
5aac1dac 326{
b59b5081
TF
327 /* Circumvent package-private access to call Window's
328 setBoundsCallback method. */
329 (*gdk_env)->CallVoidMethod (gdk_env, window, setBoundsCallbackID,
330 x, y, width, height);
331}
5aac1dac 332
b59b5081
TF
333JNIEXPORT void JNICALL
334Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize
335 (JNIEnv *env, jobject obj, jint width, jint height)
336{
337 void *ptr = NSA_GET_PTR (env, obj);
5aac1dac 338
db19e39b 339 /* Avoid GTK runtime assertion failures. */
23a555b0
TF
340 width = (width < 1) ? 1 : width;
341 height = (height < 1) ? 1 : height;
342
5aac1dac 343 gdk_threads_enter ();
b59b5081
TF
344 gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
345 gdk_threads_leave ();
346}
5aac1dac 347
b59b5081
TF
348JNIEXPORT void JNICALL
349Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds
350 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
351{
352 void *ptr = NSA_GET_PTR (env, obj);
5aac1dac 353
db19e39b 354 /* Avoid GTK runtime assertion failures. */
23a555b0
TF
355 width = (width < 1) ? 1 : width;
356 height = (height < 1) ? 1 : height;
357
b59b5081
TF
358 gdk_threads_enter ();
359 gtk_window_move (GTK_WINDOW(ptr), x, y);
c5d2de6b
GH
360 /* The call to gdk_window_move is needed in addition to the call to
361 gtk_window_move. If gdk_window_move isn't called, then the
362 following set of operations doesn't give the expected results:
363
364 1. show a window
365 2. manually move it to another position on the screen
366 3. hide the window
367 4. reposition the window with Component.setLocation
368 5. show the window
369
370 Instead of being at the position set by setLocation, the window
371 is reshown at the position to which it was moved manually. */
372 gdk_window_move (GTK_WIDGET (ptr)->window, x, y);
373
b59b5081
TF
374 /* Need to change the widget's request size. */
375 gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
376 /* Also need to call gtk_window_resize. If the resize is requested
377 by the program and the window's "resizable" property is true then
378 the size request will not be honoured. */
379 gtk_window_resize (GTK_WINDOW (ptr), width, height);
5aac1dac
TT
380 gdk_threads_leave ();
381}
382
383JNIEXPORT void JNICALL
2c20a171 384Java_gnu_java_awt_peer_gtk_GtkFramePeer_removeMenuBarPeer
e300e74f 385 (JNIEnv *env, jobject obj)
5aac1dac 386{
2c20a171
KH
387 void *wptr;
388 GtkWidget *box;
389 GtkWidget *mptr;
e300e74f 390 GList* children;
5aac1dac 391
2c20a171 392 wptr = NSA_GET_PTR (env, obj);
2c20a171
KH
393
394 gdk_threads_enter ();
5aac1dac 395
2c20a171 396 box = GTK_BIN (wptr)->child;
e300e74f
KH
397
398 children = gtk_container_get_children (GTK_CONTAINER (box));
399
400 while (children != NULL && !GTK_IS_MENU_SHELL (children->data))
401 {
402 children = children->next;
403 }
404
405 /* If there isn't a MenuBar in this Frame's list of children
406 then we can just return. */
407 if (!GTK_IS_MENU_SHELL (children->data))
408 return;
409 else
410 mptr = children->data;
411
412 /* This will actually destroy the MenuBar. By removing it from
413 its parent, the reference count for the MenuBar widget will
414 decrement to 0. The widget will be automatically destroyed
415 by Gtk. */
2c20a171
KH
416 gtk_container_remove (GTK_CONTAINER (box), GTK_WIDGET (mptr));
417
418 gdk_threads_leave();
419}
420
421JNIEXPORT void JNICALL
422Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarPeer
423 (JNIEnv *env, jobject obj, jobject menubar)
424{
425 void *wptr;
426 GtkWidget *mptr;
427 GtkWidget *box;
ecf67f46 428
5aac1dac
TT
429 wptr = NSA_GET_PTR (env, obj);
430 mptr = NSA_GET_PTR (env, menubar);
2c20a171
KH
431
432 gdk_threads_enter ();
5aac1dac 433
2c20a171
KH
434 box = GTK_BIN (wptr)->child;
435 gtk_box_pack_start (GTK_BOX (box), mptr, 0, 0, 0);
436
437 gtk_widget_show (mptr);
5aac1dac 438
2c20a171 439
5aac1dac
TT
440 gdk_threads_leave ();
441}
442
443JNIEXPORT jint JNICALL
444Java_gnu_java_awt_peer_gtk_GtkFramePeer_getMenuBarHeight
2bd408db 445 (JNIEnv *env, jobject obj __attribute__((unused)), jobject menubar)
5aac1dac 446{
2c20a171
KH
447 GtkWidget *ptr;
448 jint height;
ecf67f46 449 GtkRequisition gtkreq;
2c20a171
KH
450
451 ptr = NSA_GET_PTR (env, menubar);
5aac1dac
TT
452
453 gdk_threads_enter ();
ecf67f46
KH
454 gtk_widget_size_request (ptr, &gtkreq);
455
456 height = gtkreq.height;
5aac1dac 457 gdk_threads_leave ();
5aac1dac
TT
458 return height;
459}
f2d0e05d 460
57e13917
KH
461JNIEXPORT void JNICALL
462Java_gnu_java_awt_peer_gtk_GtkFramePeer_moveLayout
463 (JNIEnv *env, jobject obj, jint offset)
464{
465 void* ptr;
466 GList* children;
467 GtkBox* vbox;
468 GtkLayout* layout;
469 GtkWidget* widget;
470
471 ptr = NSA_GET_PTR (env, obj);
472
473 gdk_threads_enter ();
474
475 children = gtk_container_get_children (GTK_CONTAINER (ptr));
476 vbox = children->data;
477 g_assert (GTK_IS_VBOX (vbox));
478
479 children = gtk_container_get_children (GTK_CONTAINER (vbox));
480 do
481 {
482 layout = children->data;
483 children = children->next;
484 }
485 while (!GTK_IS_LAYOUT (layout) && children != NULL);
486 g_assert (GTK_IS_LAYOUT (layout));
487 children = gtk_container_get_children (GTK_CONTAINER (layout));
488
489 while (children != NULL)
490 {
491 widget = children->data;
492 gtk_layout_move (layout, widget, widget->allocation.x,
493 widget->allocation.y+offset);
494 children = children->next;
495 }
496
497 gdk_threads_leave ();
498}
499
5efa7640
KH
500JNIEXPORT void JNICALL
501Java_gnu_java_awt_peer_gtk_GtkFramePeer_gtkLayoutSetVisible
502 (JNIEnv *env, jobject obj, jboolean vis)
503{
504 void* ptr;
505 GList* children;
506 GtkBox* vbox;
507 GtkLayout* layout;
508
509 ptr = NSA_GET_PTR (env, obj);
510
511 gdk_threads_enter ();
512
513 children = gtk_container_get_children (GTK_CONTAINER (ptr));
514 vbox = children->data;
515 g_assert (GTK_IS_VBOX (vbox));
57e13917 516
5efa7640
KH
517 children = gtk_container_get_children (GTK_CONTAINER (vbox));
518 do
519 {
520 layout = children->data;
521 children = children->next;
522 }
523 while (!GTK_IS_LAYOUT (layout) && children != NULL);
524 g_assert (GTK_IS_LAYOUT (layout));
525
526 if (vis)
527 gtk_widget_show (GTK_WIDGET (layout));
528 else
529 gtk_widget_hide (GTK_WIDGET (layout));
530 gdk_threads_leave ();
531}
db19e39b
TF
532static void
533window_get_frame_extents (GtkWidget *window,
534 int *top, int *left, int *bottom, int *right)
535{
536 unsigned long *extents = NULL;
537
538 /* Guess frame extents in case _NET_FRAME_EXTENTS is not
539 supported. */
540 *top = 23;
541 *left = 6;
542 *bottom = 6;
543 *right = 6;
544
545 /* Request that the window manager set window's
546 _NET_FRAME_EXTENTS property. */
547 request_frame_extents (window);
548
549 /* Attempt to retrieve window's frame extents. */
550 if (gdk_property_get (window->window,
551 gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
552 gdk_atom_intern ("CARDINAL", FALSE),
553 0,
554 sizeof (unsigned long) * 4,
555 FALSE,
556 NULL,
557 NULL,
558 NULL,
559 (guchar **)&extents))
560 {
561 *left = extents [0];
562 *right = extents [1];
563 *top = extents [2];
564 *bottom = extents [3];
565 }
566}
567
568static Atom extents_atom = 0;
569
570/* Requests that the window manager set window's
571 _NET_FRAME_EXTENTS property. */
572static void
573request_frame_extents (GtkWidget *window)
574{
575 const char *request_str = "_NET_REQUEST_FRAME_EXTENTS";
576 GdkAtom request_extents = gdk_atom_intern (request_str, FALSE);
577
578 /* Check if the current window manager supports
579 _NET_REQUEST_FRAME_EXTENTS. */
580 if (gdk_net_wm_supports (request_extents))
581 {
582 GdkDisplay *display = gtk_widget_get_display (window);
583 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
584
585 GdkWindow *root_window = gdk_get_default_root_window ();
586 Window xroot_window = GDK_WINDOW_XID (root_window);
587
588 Atom extents_request_atom =
589 gdk_x11_get_xatom_by_name_for_display (display, request_str);
590
591 XEvent xevent;
592 XEvent notify_xevent;
593
594 unsigned long window_id = GDK_WINDOW_XID (GDK_DRAWABLE(window->window));
595
596 if (!extents_atom)
597 {
598 const char *extents_str = "_NET_FRAME_EXTENTS";
599 extents_atom =
600 gdk_x11_get_xatom_by_name_for_display (display, extents_str);
601 }
602
603 xevent.xclient.type = ClientMessage;
604 xevent.xclient.message_type = extents_request_atom;
605 xevent.xclient.display = xdisplay;
606 xevent.xclient.window = window_id;
607 xevent.xclient.format = 32;
608 xevent.xclient.data.l[0] = 0;
609 xevent.xclient.data.l[1] = 0;
610 xevent.xclient.data.l[2] = 0;
611 xevent.xclient.data.l[3] = 0;
612 xevent.xclient.data.l[4] = 0;
613
614 XSendEvent (xdisplay, xroot_window, False,
615 (SubstructureRedirectMask | SubstructureNotifyMask),
616 &xevent);
617
618 XIfEvent(xdisplay, &notify_xevent,
619 property_notify_predicate, (XPointer) &window_id);
620 }
621}
622
623static int
624property_notify_predicate (Display *xdisplay __attribute__((unused)),
625 XEvent *event,
626 XPointer window_id)
627{
628 unsigned long *window = (unsigned long *) window_id;
629
630 if (event->xany.type == PropertyNotify
631 && event->xany.window == *window
632 && event->xproperty.atom == extents_atom)
633 return True;
634
635 return False;
636}
637
f2d0e05d
TF
638static void
639window_delete_cb (GtkWidget *widget __attribute__((unused)),
640 GdkEvent *event __attribute__((unused)),
641 jobject peer)
642{
643 (*gdk_env)->CallVoidMethod (gdk_env, peer,
644 postWindowEventID,
645 (jint) AWT_WINDOW_CLOSING,
646 (jobject) NULL, (jint) 0);
647}
648
649static void
650window_destroy_cb (GtkWidget *widget __attribute__((unused)),
651 GdkEvent *event __attribute__((unused)),
652 jobject peer)
653{
654 (*gdk_env)->CallVoidMethod (gdk_env, peer,
655 postWindowEventID,
656 (jint) AWT_WINDOW_CLOSED,
657 (jobject) NULL, (jint) 0);
658}
659
660static void
661window_show_cb (GtkWidget *widget __attribute__((unused)),
662 jobject peer)
663{
664 (*gdk_env)->CallVoidMethod (gdk_env, peer,
665 postWindowEventID,
666 (jint) AWT_WINDOW_OPENED,
667 (jobject) NULL, (jint) 0);
668}
669
86881a7b
GH
670static void
671window_focus_or_active_state_change_cb (GtkWidget *widget,
672 GParamSpec *pspec,
673 jobject peer)
f2d0e05d 674{
86881a7b
GH
675 if (!strcmp (g_param_spec_get_name (pspec), "is-active"))
676 {
677 if (GTK_WINDOW (widget)->is_active)
678 (*gdk_env)->CallVoidMethod (gdk_env, peer,
679 postWindowEventID,
680 (jint) AWT_WINDOW_GAINED_FOCUS,
681 (jobject) NULL, (jint) 0);
682 else
683 (*gdk_env)->CallVoidMethod (gdk_env, peer,
684 postWindowEventID,
685 (jint) AWT_WINDOW_DEACTIVATED,
686 (jobject) NULL, (jint) 0);
687 }
688 else if (!strcmp (g_param_spec_get_name (pspec), "has-toplevel-focus"))
689 {
690 if (GTK_WINDOW (widget)->has_toplevel_focus)
691 (*gdk_env)->CallVoidMethod (gdk_env, peer,
692 postWindowEventID,
693 (jint) AWT_WINDOW_ACTIVATED,
694 (jobject) NULL, (jint) 0);
695 else
696 (*gdk_env)->CallVoidMethod (gdk_env, peer,
697 postWindowEventID,
698 (jint) AWT_WINDOW_LOST_FOCUS,
699 (jobject) NULL, (jint) 0);
700 }
f2d0e05d
TF
701}
702
703static gboolean
704window_window_state_cb (GtkWidget *widget,
705 GdkEvent *event,
706 jobject peer)
707{
708 jint new_state;
709
710 /* Handle WINDOW_ICONIFIED and WINDOW_DEICONIFIED events. */
711 if (event->window_state.changed_mask & GDK_WINDOW_STATE_ICONIFIED)
712 {
713 /* We've either been iconified or deiconified. */
714 if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
715 {
716 /* We've been iconified. */
717 (*gdk_env)->CallVoidMethod (gdk_env, peer,
718 postWindowEventID,
719 (jint) AWT_WINDOW_ICONIFIED,
720 (jobject) NULL, (jint) 0);
721 }
722 else
723 {
724 /* We've been deiconified. */
725 (*gdk_env)->CallVoidMethod (gdk_env, peer,
726 postWindowEventID,
727 (jint) AWT_WINDOW_DEICONIFIED,
728 (jobject) NULL, (jint) 0);
729 }
730 }
731
732 /* Post a WINDOW_STATE_CHANGED event, passing the new frame state to
733 GtkWindowPeer. */
734 new_state = AWT_FRAME_STATE_NORMAL;
735
736 if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
737 new_state |= AWT_FRAME_STATE_ICONIFIED;
738
739 new_state |= window_get_new_state (widget);
740
741 (*gdk_env)->CallVoidMethod (gdk_env, peer,
742 postWindowEventID,
743 (jint) AWT_WINDOW_STATE_CHANGED,
744 (jobject) NULL, new_state);
745 return TRUE;
746}
747
748static jint
749window_get_new_state (GtkWidget *widget)
750{
751 GdkDisplay *display = gtk_widget_get_display(widget);
752 jint new_state = AWT_FRAME_STATE_NORMAL;
753 Atom type;
754 gint format;
755 gulong atom_count;
756 gulong bytes_after;
757 Atom *atom_list = NULL;
758 gulong i;
759
760 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window),
761 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
762 0, G_MAXLONG, False, XA_ATOM, &type, &format, &atom_count,
763 &bytes_after, (guchar **)&atom_list);
764
765 if (type != None)
766 {
767 Atom maxvert = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
768 Atom maxhorz = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
769
770 i = 0;
771 while (i < atom_count)
772 {
773 if (atom_list[i] == maxhorz)
774 new_state |= AWT_FRAME_STATE_MAXIMIZED_HORIZ;
775 else if (atom_list[i] == maxvert)
776 new_state |= AWT_FRAME_STATE_MAXIMIZED_VERT;
777
778 ++i;
779 }
780
781 XFree (atom_list);
782 }
783 return new_state;
784}
db19e39b
TF
785
786static gboolean
787window_property_changed_cb (GtkWidget *widget __attribute__((unused)),
788 GdkEventProperty *event,
789 jobject peer)
790{
791 unsigned long *extents;
792
793 static int id_set = 0;
794 static jmethodID postInsetsChangedEventID;
795
796 if (!id_set)
797 {
798 jclass gtkwindowpeer = (*gdk_env)->FindClass (gdk_env,
799 "gnu/java/awt/peer/gtk/GtkWindowPeer");
800 postInsetsChangedEventID = (*gdk_env)->GetMethodID (gdk_env,
801 gtkwindowpeer,
802 "postInsetsChangedEvent",
803 "(IIII)V");
eae433e9 804 id_set = 1;
db19e39b
TF
805 }
806
807 if (gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE) == event->atom
808 && gdk_property_get (event->window,
809 gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
810 gdk_atom_intern ("CARDINAL", FALSE),
811 0,
812 sizeof (unsigned long) * 4,
813 FALSE,
814 NULL,
815 NULL,
816 NULL,
817 (guchar **)&extents))
818 (*gdk_env)->CallVoidMethod (gdk_env, peer,
819 postInsetsChangedEventID,
820 (jint) extents[2], /* top */
821 (jint) extents[0], /* left */
822 (jint) extents[3], /* bottom */
823 (jint) extents[1]); /* right */
824
825 return FALSE;
826}
86881a7b
GH
827
828static GdkFilterReturn
829window_wm_protocols_filter (GdkXEvent *xev,
830 GdkEvent *event __attribute__((unused)),
831 gpointer data __attribute__((unused)))
832{
833 XEvent *xevent = (XEvent *)xev;
834
835 if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name ("WM_TAKE_FOCUS"))
836 return GDK_FILTER_REMOVE;
837
838 return GDK_FILTER_CONTINUE;
839}
This page took 0.273481 seconds and 5 git commands to generate.