OSDN Git Service

2004-01-19 Kim Ho <kho@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkWindowPeer.c
1 /* gtkwindowpeer.c -- Native implementation of GtkWindowPeer
2    Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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.
10
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.
15
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
19 02111-1307 USA.
20
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.
25
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. */
37
38
39 #include "gtkpeer.h"
40 #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
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>
45 #include <X11/Xatom.h>
46
47 static void window_get_frame_extents (GtkWidget *window,
48                                       int *top, int *left,
49                                       int *bottom, int *right);
50
51 static void request_frame_extents (GtkWidget *window);
52
53 static int property_notify_predicate (Display *xdisplay,
54                                       XEvent  *event,
55                                       XPointer window_id);
56
57 static void window_delete_cb (GtkWidget *widget, GdkEvent *event,
58                               jobject peer);
59 static void window_destroy_cb (GtkWidget *widget, GdkEvent *event,
60                                jobject peer);
61 static void window_show_cb (GtkWidget *widget, jobject peer);
62 static gboolean window_focus_in_cb (GtkWidget * widget,
63                                     GdkEventFocus *event,
64                                     jobject peer);
65 static gboolean window_focus_out_cb (GtkWidget * widget,
66                                      GdkEventFocus *event,
67                                      jobject peer);
68 static gboolean window_window_state_cb (GtkWidget *widget,
69                                         GdkEvent *event,
70                                         jobject peer);
71 static jint window_get_new_state (GtkWidget *widget);
72 static gboolean window_property_changed_cb (GtkWidget *widget,
73                                             GdkEventProperty *event,
74                                             jobject peer);
75 static void menubar_resize_cb (GtkWidget *widget, GtkAllocation *alloc, 
76                                jobject peer);                                       
77
78 /*
79  * Make a new window.
80  */
81
82 JNIEXPORT void JNICALL 
83 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create 
84   (JNIEnv *env, jobject obj, jint type, jboolean decorated,
85    jint width, jint height, jobject parent, jintArray jinsets)
86 {
87   GtkWidget *window_widget;
88   GtkWindow *window;
89   void *window_parent;
90   GtkWidget *vbox;
91   GtkWidget *layout;
92   int top = 0;
93   int left = 0;
94   int bottom = 0;
95   int right = 0;
96   jint *insets;
97
98   insets = (*env)->GetIntArrayElements (env, jinsets, 0);
99   insets[0] = insets[1] = insets[2] = insets[3] = 0;
100
101   /* Create global reference and save it for future use */
102   NSA_SET_GLOBAL_REF (env, obj);
103
104   gdk_threads_enter ();
105   
106   window_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
107   window = GTK_WINDOW (window_widget);
108
109   /* Keep this window in front of its parent, if it has one. */
110   if (parent)
111     {
112       window_parent = NSA_GET_PTR (env, parent);
113       gtk_window_set_transient_for (window, GTK_WINDOW(window_parent));
114     }
115
116   gtk_window_set_decorated (window, decorated);
117
118   gtk_window_set_type_hint (window, type);
119
120   gtk_window_group_add_window (global_gtk_window_group, window);
121
122   vbox = gtk_vbox_new (0, 0);
123   layout = gtk_layout_new (NULL, NULL);
124   gtk_box_pack_end (GTK_BOX (vbox), layout, 1, 1, 0);
125   gtk_container_add (GTK_CONTAINER (window_widget), vbox);
126
127   gtk_widget_show (layout);
128   gtk_widget_show (vbox);
129   gtk_widget_realize (window_widget);
130
131   if (decorated)
132     window_get_frame_extents (window_widget, &top, &left, &bottom, &right);
133
134   gtk_window_set_default_size (window,
135                                MAX (1, width - left - right),
136                                MAX (1, height - top - bottom));
137
138   /* We must set this window's size requisition.  Otherwise when a
139      resize is queued (when gtk_widget_queue_resize is called) the
140      window will snap to its default requisition of 0x0.  If we omit
141      this call, Frames and Dialogs shrink to degenerate 1x1 windows
142      when their resizable property changes. */
143   gtk_widget_set_size_request (window_widget,
144                                MAX (1, width - left - right),
145                                MAX (1, height - top - bottom));
146
147   insets[0] = top;
148   insets[1] = left;
149   insets[2] = bottom;
150   insets[3] = right;
151
152   gdk_threads_leave ();
153
154   (*env)->ReleaseIntArrayElements (env, jinsets, insets, 0);
155
156   NSA_SET_PTR (env, obj, window_widget);
157 }
158
159 JNIEXPORT void JNICALL
160 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible
161   (JNIEnv *env, jobject obj, jboolean visible)
162 {
163   void *ptr;
164
165   ptr = NSA_GET_PTR (env, obj);
166
167   gdk_threads_enter ();
168
169   if (visible)
170     gtk_widget_show (GTK_WIDGET (ptr));
171   else
172     gtk_widget_hide (GTK_WIDGET (ptr));
173
174   XFlush (GDK_DISPLAY ());
175
176   gdk_threads_leave ();
177 }
178
179 JNIEXPORT void JNICALL
180 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectJObject
181   (JNIEnv *env, jobject obj)
182 {
183   void *ptr;
184   GtkWidget* vbox, *layout;
185   GList* children;
186
187   ptr = NSA_GET_PTR (env, obj);
188
189   gdk_threads_enter ();
190
191   children = gtk_container_get_children(GTK_CONTAINER(ptr));
192   vbox = children->data;
193
194   if(!GTK_IS_VBOX(vbox))
195     {
196       printf("*** this is not a vbox\n");
197     }
198   children = gtk_container_get_children(GTK_CONTAINER(vbox));
199   do
200   {
201     layout = children->data;
202     children = children->next;
203   }
204   while (!GTK_IS_LAYOUT (layout) && children != NULL);
205
206   if(!GTK_IS_LAYOUT(layout))
207     {
208       printf("*** widget is not a layout ***");
209     }
210
211   gtk_widget_realize (layout);
212
213   connect_awt_hook (env, obj, 1, GTK_LAYOUT (layout)->bin_window);
214
215   gtk_widget_realize (ptr);
216
217   connect_awt_hook (env, obj, 1, GTK_WIDGET (ptr)->window);
218
219   g_signal_connect (G_OBJECT (ptr), "property-notify-event",
220                     G_CALLBACK (window_property_changed_cb), obj);
221
222   gdk_threads_leave ();
223 }
224
225 JNIEXPORT void JNICALL
226 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals
227   (JNIEnv *env, jobject obj)
228 {
229   void *ptr = NSA_GET_PTR (env, obj);
230   jobject *gref = NSA_GET_GLOBAL_REF (env, obj);
231   g_assert (gref);
232
233   gdk_threads_enter ();
234
235   gtk_widget_realize (ptr);
236
237   /* Connect signals for window event support. */
238   g_signal_connect (G_OBJECT (ptr), "delete-event",
239                     G_CALLBACK (window_delete_cb), *gref);
240
241   g_signal_connect (G_OBJECT (ptr), "destroy-event",
242                     G_CALLBACK (window_destroy_cb), *gref);
243
244   g_signal_connect (G_OBJECT (ptr), "show",
245                     G_CALLBACK (window_show_cb), *gref);
246
247   g_signal_connect (G_OBJECT (ptr), "focus-in-event",
248                     G_CALLBACK (window_focus_in_cb), *gref);
249
250   g_signal_connect (G_OBJECT (ptr), "focus-out-event",
251                     G_CALLBACK (window_focus_out_cb), *gref);
252
253   g_signal_connect (G_OBJECT (ptr), "window-state-event",
254                     G_CALLBACK (window_window_state_cb), *gref);
255
256   gdk_threads_leave ();
257
258   /* Connect the superclass signals.  */
259   Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals (env, obj);
260 }
261
262 /*
263  * Set a frame's title
264  */
265
266 JNIEXPORT void JNICALL 
267 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setTitle
268   (JNIEnv *env, jobject obj, jstring title)
269 {
270   void *ptr;
271   const char *str;
272
273   ptr = NSA_GET_PTR (env, obj);
274   
275   str = (*env)->GetStringUTFChars (env, title, NULL);
276   
277   gdk_threads_enter ();
278   gtk_window_set_title (GTK_WINDOW (ptr), str);
279   gdk_threads_leave ();
280   
281   (*env)->ReleaseStringUTFChars (env, title, str);
282 }
283
284 /*
285  * Lower the z-level of a window. 
286  */
287
288 JNIEXPORT void JNICALL 
289 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv *env, 
290     jobject obj)
291 {
292   void *ptr;
293   ptr = NSA_GET_PTR (env, obj);
294     
295   gdk_threads_enter ();
296   gdk_window_lower (GTK_WIDGET (ptr)->window);
297
298   XFlush (GDK_DISPLAY ());
299   gdk_threads_leave ();
300 }
301
302 /*
303  * Raise the z-level of a window.
304  */
305
306 JNIEXPORT void JNICALL 
307 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env, 
308     jobject obj)
309 {
310   void *ptr;
311   ptr = NSA_GET_PTR (env, obj);
312     
313   gdk_threads_enter ();
314   gdk_window_raise (GTK_WIDGET (ptr)->window);
315
316   XFlush (GDK_DISPLAY ());
317   gdk_threads_leave ();
318 }
319
320 JNIEXPORT void JNICALL
321 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBoundsCallback
322   (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
323    jobject window, jint x, jint y, jint width, jint height)
324 {
325   /* Circumvent package-private access to call Window's
326      setBoundsCallback method. */
327   (*gdk_env)->CallVoidMethod (gdk_env, window, setBoundsCallbackID,
328                               x, y, width, height);
329 }
330
331 JNIEXPORT void JNICALL
332 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize
333   (JNIEnv *env, jobject obj, jint width, jint height)
334 {
335   void *ptr = NSA_GET_PTR (env, obj);
336
337   /* Avoid GTK runtime assertion failures. */
338   width = (width < 1) ? 1 : width;
339   height = (height < 1) ? 1 : height;
340
341   gdk_threads_enter ();
342   gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
343   gdk_threads_leave ();
344 }
345
346 JNIEXPORT void JNICALL
347 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds
348   (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
349 {
350   void *ptr = NSA_GET_PTR (env, obj);
351
352   /* Avoid GTK runtime assertion failures. */
353   width = (width < 1) ? 1 : width;
354   height = (height < 1) ? 1 : height;
355
356   gdk_threads_enter ();
357   gtk_window_move (GTK_WINDOW(ptr), x, y);
358   /* Need to change the widget's request size. */
359   gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
360   /* Also need to call gtk_window_resize.  If the resize is requested
361      by the program and the window's "resizable" property is true then
362      the size request will not be honoured. */
363   gtk_window_resize (GTK_WINDOW (ptr), width, height);
364   gdk_threads_leave ();
365 }
366
367 JNIEXPORT void JNICALL
368 Java_gnu_java_awt_peer_gtk_GtkFramePeer_removeMenuBarPeer
369   (JNIEnv *env, jobject obj, jobject menubar)
370 {
371   void *wptr;
372   GtkWidget *box;
373   GtkWidget *mptr;
374
375   wptr = NSA_GET_PTR (env, obj);
376   mptr = NSA_GET_PTR (env, menubar);
377   
378   gdk_threads_enter ();
379
380   box = GTK_BIN (wptr)->child;
381   gtk_container_remove (GTK_CONTAINER (box), GTK_WIDGET (mptr));  
382   
383   gdk_threads_leave();
384 }  
385   
386 JNIEXPORT void JNICALL
387 Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarPeer
388   (JNIEnv *env, jobject obj, jobject menubar)
389 {
390   void *wptr;
391   GtkWidget *mptr;
392   GtkWidget *box;
393   jobject *gref = NSA_GET_GLOBAL_REF (env, obj);
394   
395   wptr = NSA_GET_PTR (env, obj);
396   mptr = NSA_GET_PTR (env, menubar);
397   
398   gdk_threads_enter ();
399
400   g_signal_connect (G_OBJECT (mptr), "size-allocate", 
401                     G_CALLBACK (menubar_resize_cb), *gref);    
402   box = GTK_BIN (wptr)->child;              
403   gtk_box_pack_start (GTK_BOX (box), mptr, 0, 0, 0);
404  
405   gtk_widget_show (mptr);
406
407  
408   gdk_threads_leave ();
409 }
410
411 JNIEXPORT jint JNICALL
412 Java_gnu_java_awt_peer_gtk_GtkFramePeer_getMenuBarHeight
413   (JNIEnv *env, jobject obj, jobject menubar)
414 {
415   GtkWidget *ptr;
416   jint height;
417   
418   ptr = NSA_GET_PTR (env, menubar);
419
420   gdk_threads_enter ();
421   height = ptr->allocation.height;
422   gdk_threads_leave ();
423   return height;
424 }
425
426 static void
427 window_get_frame_extents (GtkWidget *window,
428                           int *top, int *left, int *bottom, int *right)
429 {
430   unsigned long *extents = NULL;
431
432   /* Guess frame extents in case _NET_FRAME_EXTENTS is not
433      supported. */
434   *top = 23;
435   *left = 6;
436   *bottom = 6;
437   *right = 6;
438
439   /* Request that the window manager set window's
440      _NET_FRAME_EXTENTS property. */
441   request_frame_extents (window);
442
443   /* Attempt to retrieve window's frame extents. */
444   if (gdk_property_get (window->window,
445                         gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
446                         gdk_atom_intern ("CARDINAL", FALSE),
447                         0,
448                         sizeof (unsigned long) * 4,
449                         FALSE,
450                         NULL,
451                         NULL,
452                         NULL,
453                         (guchar **)&extents))
454     {
455       *left = extents [0];
456       *right = extents [1];
457       *top = extents [2];
458       *bottom = extents [3];
459     }
460 }
461
462 static Atom extents_atom = 0;
463
464 /* Requests that the window manager set window's
465    _NET_FRAME_EXTENTS property. */
466 static void
467 request_frame_extents (GtkWidget *window)
468 {
469   const char *request_str = "_NET_REQUEST_FRAME_EXTENTS";
470   GdkAtom request_extents = gdk_atom_intern (request_str, FALSE);
471
472   /* Check if the current window manager supports
473      _NET_REQUEST_FRAME_EXTENTS. */
474   if (gdk_net_wm_supports (request_extents))
475     {
476       GdkDisplay *display = gtk_widget_get_display (window);
477       Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
478
479       GdkWindow *root_window = gdk_get_default_root_window ();
480       Window xroot_window = GDK_WINDOW_XID (root_window);
481
482       Atom extents_request_atom =
483         gdk_x11_get_xatom_by_name_for_display (display, request_str);
484
485       XEvent xevent;
486       XEvent notify_xevent;
487
488       unsigned long window_id = GDK_WINDOW_XID (GDK_DRAWABLE(window->window));
489
490       if (!extents_atom)
491         {
492           const char *extents_str = "_NET_FRAME_EXTENTS";
493           extents_atom =
494             gdk_x11_get_xatom_by_name_for_display (display, extents_str);
495         }
496
497       xevent.xclient.type = ClientMessage;
498       xevent.xclient.message_type = extents_request_atom;
499       xevent.xclient.display = xdisplay;
500       xevent.xclient.window = window_id;
501       xevent.xclient.format = 32;
502       xevent.xclient.data.l[0] = 0;
503       xevent.xclient.data.l[1] = 0;
504       xevent.xclient.data.l[2] = 0;
505       xevent.xclient.data.l[3] = 0;
506       xevent.xclient.data.l[4] = 0;
507
508       XSendEvent (xdisplay, xroot_window, False,
509                   (SubstructureRedirectMask | SubstructureNotifyMask),
510                   &xevent);
511
512       XIfEvent(xdisplay, &notify_xevent,
513                property_notify_predicate, (XPointer) &window_id);
514     }
515 }
516
517 static int
518 property_notify_predicate (Display *xdisplay __attribute__((unused)),
519                            XEvent  *event,
520                            XPointer window_id)
521 {
522   unsigned long *window = (unsigned long *) window_id;
523
524   if (event->xany.type == PropertyNotify
525       && event->xany.window == *window
526       && event->xproperty.atom == extents_atom)
527         return True;
528
529   return False;
530 }
531
532 static void
533 window_delete_cb (GtkWidget *widget __attribute__((unused)),
534                   GdkEvent *event __attribute__((unused)),
535                   jobject peer)
536 {
537   (*gdk_env)->CallVoidMethod (gdk_env, peer,
538                               postWindowEventID,
539                               (jint) AWT_WINDOW_CLOSING,
540                               (jobject) NULL, (jint) 0);
541 }
542
543 static void
544 window_destroy_cb (GtkWidget *widget __attribute__((unused)),
545                    GdkEvent *event __attribute__((unused)),
546                    jobject peer)
547 {
548   (*gdk_env)->CallVoidMethod (gdk_env, peer,
549                               postWindowEventID,
550                               (jint) AWT_WINDOW_CLOSED,
551                               (jobject) NULL, (jint) 0);
552 }
553
554 static void
555 window_show_cb (GtkWidget *widget __attribute__((unused)),
556                 jobject peer)
557 {
558   (*gdk_env)->CallVoidMethod (gdk_env, peer,
559                               postWindowEventID,
560                               (jint) AWT_WINDOW_OPENED,
561                               (jobject) NULL, (jint) 0);
562 }
563
564 static gboolean
565 window_focus_in_cb (GtkWidget * widget __attribute__((unused)),
566                     GdkEventFocus *event __attribute__((unused)),
567                     jobject peer)
568 {
569   /* FIXME: when hiding then showing, we get two sets of
570      (LOST_FOCUS/DEACTIVATED, ACTIVATED/GAINED_FOCUS) events. */
571   (*gdk_env)->CallVoidMethod (gdk_env, peer,
572                               postWindowEventID,
573                               (jint) AWT_WINDOW_ACTIVATED,
574                               (jobject) NULL, (jint) 0);
575
576   (*gdk_env)->CallVoidMethod (gdk_env, peer,
577                               postWindowEventID,
578                               (jint) AWT_WINDOW_GAINED_FOCUS,
579                               (jobject) NULL, (jint) 0);
580   return TRUE;
581 }
582
583 static gboolean
584 window_focus_out_cb (GtkWidget * widget __attribute__((unused)),
585                      GdkEventFocus *event __attribute__((unused)),
586                      jobject peer)
587 {
588   (*gdk_env)->CallVoidMethod (gdk_env, peer,
589                               postWindowEventID,
590                               (jint) AWT_WINDOW_LOST_FOCUS,
591                               (jobject) NULL, (jint) 0);
592
593   (*gdk_env)->CallVoidMethod (gdk_env, peer,
594                               postWindowEventID,
595                               (jint) AWT_WINDOW_DEACTIVATED,
596                               (jobject) NULL, (jint) 0);
597   return TRUE;
598 }
599
600 static gboolean
601 window_window_state_cb (GtkWidget *widget,
602                         GdkEvent *event,
603                         jobject peer)
604 {
605   jint new_state;
606
607   /* Handle WINDOW_ICONIFIED and WINDOW_DEICONIFIED events. */
608   if (event->window_state.changed_mask & GDK_WINDOW_STATE_ICONIFIED)
609     {
610       /* We've either been iconified or deiconified. */
611       if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
612         {
613           /* We've been iconified. */
614           (*gdk_env)->CallVoidMethod (gdk_env, peer,
615                                       postWindowEventID,
616                                       (jint) AWT_WINDOW_ICONIFIED,
617                                       (jobject) NULL, (jint) 0);
618         }
619       else
620         {
621           /* We've been deiconified. */
622           (*gdk_env)->CallVoidMethod (gdk_env, peer,
623                                       postWindowEventID,
624                                       (jint) AWT_WINDOW_DEICONIFIED,
625                                       (jobject) NULL, (jint) 0);
626         }
627     }
628
629   /* Post a WINDOW_STATE_CHANGED event, passing the new frame state to
630      GtkWindowPeer. */
631   new_state = AWT_FRAME_STATE_NORMAL;
632
633   if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
634     new_state |= AWT_FRAME_STATE_ICONIFIED;
635
636   new_state |= window_get_new_state (widget);
637
638   (*gdk_env)->CallVoidMethod (gdk_env, peer,
639                               postWindowEventID,
640                               (jint) AWT_WINDOW_STATE_CHANGED,
641                               (jobject) NULL, new_state);
642   return TRUE;
643 }
644
645 static jint
646 window_get_new_state (GtkWidget *widget)
647 {
648   GdkDisplay *display = gtk_widget_get_display(widget);
649   jint new_state = AWT_FRAME_STATE_NORMAL;
650   Atom type;
651   gint format;
652   gulong atom_count;
653   gulong bytes_after;
654   Atom *atom_list = NULL;
655   gulong i;
656
657   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window),
658                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
659                       0, G_MAXLONG, False, XA_ATOM, &type, &format, &atom_count,
660                       &bytes_after, (guchar **)&atom_list);
661
662   if (type != None)
663     {
664       Atom maxvert = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
665       Atom maxhorz      = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
666
667       i = 0;
668       while (i < atom_count)
669         {
670           if (atom_list[i] == maxhorz)
671             new_state |= AWT_FRAME_STATE_MAXIMIZED_HORIZ;
672           else if (atom_list[i] == maxvert)
673             new_state |= AWT_FRAME_STATE_MAXIMIZED_VERT;
674
675           ++i;
676         }
677
678       XFree (atom_list);
679     }
680   return new_state;
681 }
682
683 static gboolean
684 window_property_changed_cb (GtkWidget *widget __attribute__((unused)),
685                             GdkEventProperty *event,
686                             jobject peer)
687 {
688   unsigned long *extents;
689
690   static int id_set = 0;
691   static jmethodID postInsetsChangedEventID;
692
693   if (!id_set)
694     {
695       jclass gtkwindowpeer = (*gdk_env)->FindClass (gdk_env,
696                                  "gnu/java/awt/peer/gtk/GtkWindowPeer");
697       postInsetsChangedEventID = (*gdk_env)->GetMethodID (gdk_env,
698                                                       gtkwindowpeer,
699                                                       "postInsetsChangedEvent",
700                                                       "(IIII)V");
701       id_set = 1;
702     }
703
704   if (gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE) == event->atom
705       && gdk_property_get (event->window,
706                            gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
707                            gdk_atom_intern ("CARDINAL", FALSE),
708                            0,
709                            sizeof (unsigned long) * 4,
710                            FALSE,
711                            NULL,
712                            NULL,
713                            NULL,
714                            (guchar **)&extents))
715     (*gdk_env)->CallVoidMethod (gdk_env, peer,
716                                 postInsetsChangedEventID,
717                                 (jint) extents[2],  /* top */
718                                 (jint) extents[0],  /* left */
719                                 (jint) extents[3],  /* bottom */
720                                 (jint) extents[1]); /* right */
721
722   return FALSE;
723 }
724
725 static void menubar_resize_cb (GtkWidget *widget, GtkAllocation *alloc, 
726                                jobject peer)
727 {
728   static int id_set = 0;
729   static jmethodID postSizeAllocateEventID;
730   
731   if (!id_set)
732     {
733       jclass gtkframepeer = (*gdk_env)->FindClass (gdk_env,
734                                 "gnu/java/awt/peer/gtk/GtkFramePeer");
735       postSizeAllocateEventID = (*gdk_env)->GetMethodID (gdk_env,
736                                                      gtkframepeer,
737                                                      "postSizeAllocateEvent",
738                                                      "()V");
739       id_set = 1;
740     }
741   gdk_threads_leave();
742   (*gdk_env)->CallVoidMethod (gdk_env, peer,
743                               postSizeAllocateEventID);
744   gdk_threads_enter();
745 }