OSDN Git Service

2005-04-25 Thomas Fitzsimmons <fitzsim@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkWindowPeer.c
index 8c6fc1f..184ca56 100644 (file)
@@ -37,34 +37,42 @@ exception statement from your version. */
 
 
 #include "gtkpeer.h"
-#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
 #include "gnu_java_awt_peer_gtk_GtkWindowPeer.h"
-#include "gnu_java_awt_peer_gtk_GtkFramePeer.h"
 #include <gdk/gdkprivate.h>
 #include <gdk/gdkx.h>
 #include <X11/Xatom.h>
 
+/* FIXME: we're currently seeing the double-activation that occurs
+   with metacity and GTK.  See
+   http://bugzilla.gnome.org/show_bug.cgi?id=140977 for details. */
+
 static void window_get_frame_extents (GtkWidget *window,
                                       int *top, int *left,
                                       int *bottom, int *right);
 
 static void request_frame_extents (GtkWidget *window);
 
-static int property_notify_predicate (Display *xdisplay,
-                                      XEvent  *event,
-                                      XPointer window_id);
+static Bool property_notify_predicate (Display *display,
+                                       XEvent  *xevent,
+                                       XPointer arg);
 
 static void window_delete_cb (GtkWidget *widget, GdkEvent *event,
                              jobject peer);
 static void window_destroy_cb (GtkWidget *widget, GdkEvent *event,
                               jobject peer);
 static void window_show_cb (GtkWidget *widget, jobject peer);
+static void window_active_state_change_cb (GtkWidget *widget,
+                                           GParamSpec *pspec,
+                                           jobject peer);
+static void window_focus_state_change_cb (GtkWidget *widget,
+                                          GParamSpec *pspec,
+                                          jobject peer);
 static gboolean window_focus_in_cb (GtkWidget * widget,
-                                   GdkEventFocus *event,
-                                   jobject peer);
+                                    GdkEventFocus *event,
+                                    jobject peer);
 static gboolean window_focus_out_cb (GtkWidget * widget,
-                                    GdkEventFocus *event,
-                                    jobject peer);
+                                     GdkEventFocus *event,
+                                     jobject peer);
 static gboolean window_window_state_cb (GtkWidget *widget,
                                        GdkEvent *event,
                                        jobject peer);
@@ -72,31 +80,30 @@ static jint window_get_new_state (GtkWidget *widget);
 static gboolean window_property_changed_cb (GtkWidget *widget,
                                            GdkEventProperty *event,
                                            jobject peer);
+static void realize_cb (GtkWidget *widget, jobject peer);
 
-/*
- * Make a new window.
- */
+/* Union used for type punning. */
+union extents_union
+{
+  guchar **gu_extents;
+  unsigned long **extents;
+};
 
-JNIEXPORT void JNICALL 
-Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create 
-  (JNIEnv *env, jobject obj, jint type, jboolean decorated,
-   jint width, jint height, jobject parent, jintArray jinsets)
+union atom_list_union
+{
+  guchar **gu_extents;
+  Atom **atom_list;
+};
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
+  (JNIEnv *env, jobject obj, jint type, jboolean decorated, jobject parent)
 {
   GtkWidget *window_widget;
   GtkWindow *window;
   void *window_parent;
-  GtkWidget *vbox;
-  GtkWidget *layout;
-  int top = 0;
-  int left = 0;
-  int bottom = 0;
-  int right = 0;
-  jint *insets;
-
-  insets = (*env)->GetIntArrayElements (env, jinsets, 0);
-  insets[0] = insets[1] = insets[2] = insets[3] = 0;
-
-  /* Create global reference and save it for future use */
+  GtkWidget *fixed;
+
   NSA_SET_GLOBAL_REF (env, obj);
 
   gdk_threads_enter ();
@@ -117,46 +124,39 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
 
   gtk_window_group_add_window (global_gtk_window_group, window);
 
-  vbox = gtk_vbox_new (0, 0);
-  layout = gtk_layout_new (NULL, NULL);
-  gtk_box_pack_end (GTK_BOX (vbox), layout, 1, 1, 0);
-  gtk_container_add (GTK_CONTAINER (window_widget), vbox);
+  fixed = gtk_fixed_new ();
+  gtk_container_add (GTK_CONTAINER (window_widget), fixed);
 
-  gtk_widget_show (layout);
-  gtk_widget_show (vbox);
-  gtk_widget_realize (window_widget);
+  gtk_widget_show (fixed);
 
-  if (decorated)
-    window_get_frame_extents (window_widget, &top, &left, &bottom, &right);
+  gdk_threads_leave ();
 
-  gtk_window_set_default_size (window,
-                              MAX (1, width - left - right),
-                              MAX (1, height - top - bottom));
+  NSA_SET_PTR (env, obj, window_widget);
+}
 
-  /* We must set this window's size requisition.  Otherwise when a
-     resize is queued (when gtk_widget_queue_resize is called) the
-     window will snap to its default requisition of 0x0.  If we omit
-     this call, Frames and Dialogs shrink to degenerate 1x1 windows
-     when their resizable property changes. */
-  gtk_widget_set_size_request (window_widget,
-                              MAX (1, width - left - right),
-                              MAX (1, height - top - bottom));
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetTitle
+  (JNIEnv *env, jobject obj, jstring title)
+{
+  const char *c_title;
+  void *ptr;
 
-  insets[0] = top;
-  insets[1] = left;
-  insets[2] = bottom;
-  insets[3] = right;
+  ptr = NSA_GET_PTR (env, obj);
 
-  gdk_threads_leave ();
+  c_title = (*env)->GetStringUTFChars (env, title, NULL);
+
+  gdk_threads_enter ();
 
-  (*env)->ReleaseIntArrayElements (env, jinsets, insets, 0);
+  gtk_window_set_title (GTK_WINDOW (ptr), c_title);
 
-  NSA_SET_PTR (env, obj, window_widget);
+  gdk_threads_leave ();
+
+  (*env)->ReleaseStringUTFChars (env, title, c_title);
 }
 
 JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible
-  (JNIEnv *env, jobject obj, jboolean visible)
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetResizable
+  (JNIEnv *env, jobject obj, jboolean resizable)
 {
   void *ptr;
 
@@ -164,53 +164,42 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible
 
   gdk_threads_enter ();
 
-  if (visible)
-    gtk_widget_show (GTK_WIDGET (ptr));
-  else
-    gtk_widget_hide (GTK_WIDGET (ptr));
-
-  XFlush (GDK_DISPLAY ());
+  gtk_window_set_policy (GTK_WINDOW (ptr), resizable, resizable, FALSE);
 
   gdk_threads_leave ();
 }
 
 JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectJObject
-  (JNIEnv *env, jobject obj)
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal
+  (JNIEnv *env, jobject obj, jboolean modal)
 {
   void *ptr;
-  GtkWidget* vbox, *layout;
-  GList* children;
 
   ptr = NSA_GET_PTR (env, obj);
 
   gdk_threads_enter ();
 
-  children = gtk_container_get_children(GTK_CONTAINER(ptr));
-  vbox = children->data;
-
-  if(!GTK_IS_VBOX(vbox))
-    {
-      printf("*** this is not a vbox\n");
-    }
-  children = gtk_container_get_children(GTK_CONTAINER(vbox));
-  layout = children->data;
+  gtk_window_set_modal (GTK_WINDOW (ptr), modal);
 
-  if(!GTK_IS_LAYOUT(layout))
-    {
-      printf("*** widget is not a layout ***");
-    }
+  gdk_threads_leave ();
+}
 
-  gtk_widget_realize (layout);
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible
+  (JNIEnv *env, jobject obj, jboolean visible)
+{
+  void *ptr;
 
-  connect_awt_hook (env, obj, 1, GTK_LAYOUT (layout)->bin_window);
+  ptr = NSA_GET_PTR (env, obj);
 
-  gtk_widget_realize (ptr);
+  gdk_threads_enter ();
 
-  connect_awt_hook (env, obj, 1, GTK_WIDGET (ptr)->window);
+  if (visible)
+    gtk_widget_show (GTK_WIDGET (ptr));
+  else
+    gtk_widget_hide (GTK_WIDGET (ptr));
 
-  g_signal_connect (G_OBJECT (ptr), "property-notify-event",
-                   G_CALLBACK (window_property_changed_cb), obj);
+  XFlush (GDK_DISPLAY ());
 
   gdk_threads_leave ();
 }
@@ -219,15 +208,17 @@ JNIEXPORT void JNICALL
 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals
   (JNIEnv *env, jobject obj)
 {
-  void *ptr = NSA_GET_PTR (env, obj);
-  jobject *gref = NSA_GET_GLOBAL_REF (env, obj);
-  g_assert (gref);
+  void *ptr;
+  jobject *gref;
+
+  ptr = NSA_GET_PTR (env, obj);
+  gref = NSA_GET_GLOBAL_REF (env, obj);
 
   gdk_threads_enter ();
 
-  gtk_widget_realize (ptr);
+  g_signal_connect (G_OBJECT (ptr), "event",
+                    G_CALLBACK (pre_event_handler), *gref);
 
-  /* Connect signals for window event support. */
   g_signal_connect (G_OBJECT (ptr), "delete-event",
                    G_CALLBACK (window_delete_cb), *gref);
 
@@ -237,47 +228,40 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals
   g_signal_connect (G_OBJECT (ptr), "show",
                    G_CALLBACK (window_show_cb), *gref);
 
+  g_signal_connect (G_OBJECT (ptr), "notify::is-active",
+                   G_CALLBACK (window_active_state_change_cb), *gref);
+
+  g_signal_connect (G_OBJECT (ptr), "notify::has-toplevel-focus",
+                   G_CALLBACK (window_focus_state_change_cb), *gref);
+
   g_signal_connect (G_OBJECT (ptr), "focus-in-event",
-                   G_CALLBACK (window_focus_in_cb), *gref);
+                    G_CALLBACK (window_focus_in_cb), *gref);
 
   g_signal_connect (G_OBJECT (ptr), "focus-out-event",
-                   G_CALLBACK (window_focus_out_cb), *gref);
+                    G_CALLBACK (window_focus_out_cb), *gref);
 
   g_signal_connect (G_OBJECT (ptr), "window-state-event",
                    G_CALLBACK (window_window_state_cb), *gref);
 
-  gdk_threads_leave ();
+  g_signal_connect (G_OBJECT (ptr), "property-notify-event",
+                   G_CALLBACK (window_property_changed_cb), *gref);
 
-  /* Connect the superclass signals.  */
-  Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals (env, obj);
-}
+  g_signal_connect_after (G_OBJECT (ptr), "realize",
+                          G_CALLBACK (realize_cb), *gref);
 
-/*
- * Set a frame's title
- */
+  g_signal_connect_after (G_OBJECT (ptr), "realize",
+                          G_CALLBACK (connect_awt_hook_cb), *gref);
 
-JNIEXPORT void JNICALL 
-Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setTitle
-  (JNIEnv *env, jobject obj, jstring title)
-{
-  void *ptr;
-  const char *str;
 
-  ptr = NSA_GET_PTR (env, obj);
-  
-  str = (*env)->GetStringUTFChars (env, title, NULL);
-  
-  gdk_threads_enter ();
-  gtk_window_set_title (GTK_WINDOW (ptr), str);
+  /* Realize the window here so that its frame extents are known now.
+     That way Window.pack can operate with the accurate insets
+     returned by the window manager rather than the default
+     estimates. */
+  gtk_widget_realize (GTK_WIDGET (ptr));
+
   gdk_threads_leave ();
-  
-  (*env)->ReleaseStringUTFChars (env, title, str);
 }
 
-/*
- * Lower the z-level of a window. 
- */
-
 JNIEXPORT void JNICALL 
 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv *env, 
     jobject obj)
@@ -286,16 +270,13 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv *env,
   ptr = NSA_GET_PTR (env, obj);
     
   gdk_threads_enter ();
+
   gdk_window_lower (GTK_WIDGET (ptr)->window);
+  gdk_flush ();
 
-  XFlush (GDK_DISPLAY ());
   gdk_threads_leave ();
 }
 
-/*
- * Raise the z-level of a window.
- */
-
 JNIEXPORT void JNICALL 
 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env, 
     jobject obj)
@@ -304,9 +285,10 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env,
   ptr = NSA_GET_PTR (env, obj);
     
   gdk_threads_enter ();
+
   gdk_window_raise (GTK_WIDGET (ptr)->window);
+  gdk_flush ();
 
-  XFlush (GDK_DISPLAY ());
   gdk_threads_leave ();
 }
 
@@ -317,7 +299,7 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBoundsCallback
 {
   /* Circumvent package-private access to call Window's
      setBoundsCallback method. */
-  (*gdk_env)->CallVoidMethod (gdk_env, window, setBoundsCallbackID,
+  (*gdk_env())->CallVoidMethod (gdk_env(), window, setBoundsCallbackID,
                              x, y, width, height);
 }
 
@@ -332,7 +314,9 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize
   height = (height < 1) ? 1 : height;
 
   gdk_threads_enter ();
+
   gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
+
   gdk_threads_leave ();
 }
 
@@ -347,7 +331,23 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds
   height = (height < 1) ? 1 : height;
 
   gdk_threads_enter ();
+
   gtk_window_move (GTK_WINDOW(ptr), x, y);
+  /* The call to gdk_window_move is needed in addition to the call to
+     gtk_window_move.  If gdk_window_move isn't called, then the
+     following set of operations doesn't give the expected results:
+
+     1. show a window
+     2. manually move it to another position on the screen
+     3. hide the window
+     4. reposition the window with Component.setLocation
+     5. show the window
+
+     Instead of being at the position set by setLocation, the window
+     is reshown at the position to which it was moved manually. */
+  if (GTK_WIDGET (ptr)->window != NULL)
+    gdk_window_move (GTK_WIDGET (ptr)->window, x, y);
+
   /* Need to change the widget's request size. */
   gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
   /* Also need to call gtk_window_resize.  If the resize is requested
@@ -357,81 +357,12 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds
   gdk_threads_leave ();
 }
 
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarPeer
-  (JNIEnv *env, jobject obj, jobject menubar)
-{
-  void *wptr, *mptr;
-  GtkBox *box;
-
-  if (!menubar) return;
-
-  wptr = NSA_GET_PTR (env, obj);
-  mptr = NSA_GET_PTR (env, menubar);
-
-  if (!mptr) return; /* this case should remove a menu */
-
-  gdk_threads_enter ();
-  box = GTK_BOX (GTK_BIN (wptr)->child);
-  gtk_box_pack_start (box, GTK_WIDGET (mptr), 0, 0, 0);
-  gdk_threads_leave ();
-}
-
-JNIEXPORT jint JNICALL
-Java_gnu_java_awt_peer_gtk_GtkFramePeer_getMenuBarHeight
-  (JNIEnv *env, jobject obj)
-{
-  void *ptr;
-  GList *children;
-  jint height = 0;
-
-  ptr = NSA_GET_PTR (env, obj);
-
-  gdk_threads_enter ();
-  children = gtk_container_children (GTK_CONTAINER (GTK_BIN (ptr)->child));
-  if (g_list_length (children) == 2)
-    {
-      GtkWidget *menubar = GTK_WIDGET (children->data);
-      height = menubar->allocation.height;
-
-    }
-  gdk_threads_leave ();
-
-  return height;
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_gtkWidgetGetDimensions
-  (JNIEnv *env, jobject obj, jintArray jdims)
-{
-  void *ptr;
-  jint *dims;
-  int top, left, bottom, right;
-  GtkRequisition req;
-  
-  ptr = NSA_GET_PTR (env, obj);
-  dims = (*env)->GetIntArrayElements (env, jdims, 0);
-  dims[0] = dims[1] = 0;
-  
-  gdk_threads_enter ();
-  
-  gtk_widget_size_request (GTK_WIDGET (ptr), &req);
-  
-  window_get_frame_extents (GTK_WIDGET (ptr), &top, &left, &bottom, &right);
-
-  dims[0] = req.width + left + right;
-  dims[1] = req.height + top + bottom;
-  
-  gdk_threads_leave ();
-    
-  (*env)->ReleaseIntArrayElements (env, jdims, dims, 0);
-} 
-
 static void
 window_get_frame_extents (GtkWidget *window,
                           int *top, int *left, int *bottom, int *right)
 {
   unsigned long *extents = NULL;
+  union extents_union gu_ex;
 
   /* Guess frame extents in case _NET_FRAME_EXTENTS is not
      supported. */
@@ -445,6 +376,7 @@ window_get_frame_extents (GtkWidget *window,
   request_frame_extents (window);
 
   /* Attempt to retrieve window's frame extents. */
+  gu_ex.extents = &extents;
   if (gdk_property_get (window->window,
                         gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
                         gdk_atom_intern ("CARDINAL", FALSE),
@@ -454,7 +386,7 @@ window_get_frame_extents (GtkWidget *window,
                         NULL,
                         NULL,
                         NULL,
-                        (guchar **)&extents))
+                        gu_ex.gu_extents))
     {
       *left = extents [0];
       *right = extents [1];
@@ -518,7 +450,7 @@ request_frame_extents (GtkWidget *window)
     }
 }
 
-static int
+static Bool
 property_notify_predicate (Display *xdisplay __attribute__((unused)),
                            XEvent  *event,
                            XPointer window_id)
@@ -528,9 +460,9 @@ property_notify_predicate (Display *xdisplay __attribute__((unused)),
   if (event->xany.type == PropertyNotify
       && event->xany.window == *window
       && event->xproperty.atom == extents_atom)
-        return True;
-
-  return False;
+    return True;
+  else
+    return False;
 }
 
 static void
@@ -538,10 +470,12 @@ window_delete_cb (GtkWidget *widget __attribute__((unused)),
                  GdkEvent *event __attribute__((unused)),
                  jobject peer)
 {
-  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+  gdk_threads_leave ();
+  (*gdk_env())->CallVoidMethod (gdk_env(), peer,
                              postWindowEventID,
                              (jint) AWT_WINDOW_CLOSING,
                              (jobject) NULL, (jint) 0);
+  gdk_threads_enter ();
 }
 
 static void
@@ -549,39 +483,82 @@ window_destroy_cb (GtkWidget *widget __attribute__((unused)),
                   GdkEvent *event __attribute__((unused)),
                   jobject peer)
 {
-  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+  gdk_threads_leave ();
+  (*gdk_env())->CallVoidMethod (gdk_env(), peer,
                              postWindowEventID,
                              (jint) AWT_WINDOW_CLOSED,
                              (jobject) NULL, (jint) 0);
+  gdk_threads_enter ();
 }
 
 static void
 window_show_cb (GtkWidget *widget __attribute__((unused)),
                jobject peer)
 {
-  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+  gdk_threads_leave ();
+  (*gdk_env())->CallVoidMethod (gdk_env(), peer,
                              postWindowEventID,
                              (jint) AWT_WINDOW_OPENED,
                              (jobject) NULL, (jint) 0);
+  gdk_threads_enter ();
+}
+
+static void
+window_active_state_change_cb (GtkWidget *widget __attribute__((unused)),
+                              GParamSpec *pspec __attribute__((unused)),
+                              jobject peer __attribute__((unused)))
+{
+  /* FIXME: not sure if this is needed or not. */
+  /* Remove the unused attributes if you fix the below.  */
+#if 0
+  gdk_threads_leave ();
+  if (GTK_WINDOW (widget)->is_active)
+    (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+                                postWindowEventID,
+                                (jint) AWT_WINDOW_GAINED_FOCUS,
+                                (jobject) NULL, (jint) 0);
+  else
+    (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+                                postWindowEventID,
+                                (jint) AWT_WINDOW_DEACTIVATED,
+                                (jobject) NULL, (jint) 0);
+  gdk_threads_enter ();
+#endif
+}
+
+static void
+window_focus_state_change_cb (GtkWidget *widget,
+                             GParamSpec *pspec __attribute__((unused)),
+                             jobject peer)
+{
+  gdk_threads_leave ();
+  if (GTK_WINDOW (widget)->has_toplevel_focus)
+    (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+                                postWindowEventID,
+                                (jint) AWT_WINDOW_ACTIVATED,
+                                (jobject) NULL, (jint) 0);
+  else
+    (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+                                postWindowEventID,
+                                (jint) AWT_WINDOW_DEACTIVATED,
+                                (jobject) NULL, (jint) 0);
+  gdk_threads_enter ();
 }
 
 static gboolean
-window_focus_in_cb (GtkWidget * widget __attribute__((unused)),
-                   GdkEventFocus *event __attribute__((unused)),
+window_focus_in_cb (GtkWidget * widget  __attribute__((unused)),
+                   GdkEventFocus *event  __attribute__((unused)),
                    jobject peer)
 {
-  /* FIXME: when hiding then showing, we get two sets of
-     (LOST_FOCUS/DEACTIVATED, ACTIVATED/GAINED_FOCUS) events. */
-  (*gdk_env)->CallVoidMethod (gdk_env, peer,
-                             postWindowEventID,
-                             (jint) AWT_WINDOW_ACTIVATED,
-                             (jobject) NULL, (jint) 0);
-
-  (*gdk_env)->CallVoidMethod (gdk_env, peer,
-                             postWindowEventID,
-                             (jint) AWT_WINDOW_GAINED_FOCUS,
-                             (jobject) NULL, (jint) 0);
-  return TRUE;
+  gdk_threads_leave ();
+  (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+                              postWindowEventID,
+                              (jint) AWT_WINDOW_GAINED_FOCUS,
+                              (jobject) NULL, (jint) 0);
+  /* FIXME: somewhere after this is handled, the child window is
+     getting an expose event. */
+  gdk_threads_enter ();
+  return FALSE;
 }
 
 static gboolean
@@ -589,16 +566,15 @@ window_focus_out_cb (GtkWidget * widget __attribute__((unused)),
                     GdkEventFocus *event __attribute__((unused)),
                     jobject peer)
 {
-  (*gdk_env)->CallVoidMethod (gdk_env, peer,
-                             postWindowEventID,
-                             (jint) AWT_WINDOW_LOST_FOCUS,
-                             (jobject) NULL, (jint) 0);
-
-  (*gdk_env)->CallVoidMethod (gdk_env, peer,
-                             postWindowEventID,
-                             (jint) AWT_WINDOW_DEACTIVATED,
-                             (jobject) NULL, (jint) 0);
-  return TRUE;
+  gdk_threads_leave ();
+  (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+                              postWindowEventID,
+                              (jint) AWT_WINDOW_LOST_FOCUS,
+                              (jobject) NULL, (jint) 0);
+  /* FIXME: somewhere after this is handled, the child window is
+     getting an expose event. */
+  gdk_threads_enter ();
+  return FALSE;
 }
 
 static gboolean
@@ -615,18 +591,22 @@ window_window_state_cb (GtkWidget *widget,
       if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
        {
          /* We've been iconified. */
-         (*gdk_env)->CallVoidMethod (gdk_env, peer,
+         gdk_threads_leave ();
+         (*gdk_env())->CallVoidMethod (gdk_env(), peer,
                                      postWindowEventID,
                                      (jint) AWT_WINDOW_ICONIFIED,
                                      (jobject) NULL, (jint) 0);
+         gdk_threads_enter ();
        }
       else
        {
          /* We've been deiconified. */
-         (*gdk_env)->CallVoidMethod (gdk_env, peer,
+         gdk_threads_leave ();
+         (*gdk_env())->CallVoidMethod (gdk_env(), peer,
                                      postWindowEventID,
                                      (jint) AWT_WINDOW_DEICONIFIED,
                                      (jobject) NULL, (jint) 0);
+         gdk_threads_enter ();
        }
     }
 
@@ -639,10 +619,12 @@ window_window_state_cb (GtkWidget *widget,
 
   new_state |= window_get_new_state (widget);
 
-  (*gdk_env)->CallVoidMethod (gdk_env, peer,
+  gdk_threads_leave ();
+  (*gdk_env())->CallVoidMethod (gdk_env(), peer,
                              postWindowEventID,
                              (jint) AWT_WINDOW_STATE_CHANGED,
                              (jobject) NULL, new_state);
+  gdk_threads_enter ();
   return TRUE;
 }
 
@@ -656,12 +638,15 @@ window_get_new_state (GtkWidget *widget)
   gulong atom_count;
   gulong bytes_after;
   Atom *atom_list = NULL;
+  union atom_list_union alu;
   gulong i;
 
-  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window),
+  alu.atom_list = &atom_list;
+  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
+                     GDK_WINDOW_XID (widget->window),
                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
                      0, G_MAXLONG, False, XA_ATOM, &type, &format, &atom_count,
-                     &bytes_after, (guchar **)&atom_list);
+                     &bytes_after, alu.gu_extents);
 
   if (type != None)
     {
@@ -690,20 +675,9 @@ window_property_changed_cb (GtkWidget *widget __attribute__((unused)),
                             jobject peer)
 {
   unsigned long *extents;
+  union extents_union gu_ex;
 
-  static int id_set = 0;
-  static jmethodID postInsetsChangedEventID;
-
-  if (!id_set)
-    {
-      jclass gtkwindowpeer = (*gdk_env)->FindClass (gdk_env,
-                                "gnu/java/awt/peer/gtk/GtkWindowPeer");
-      postInsetsChangedEventID = (*gdk_env)->GetMethodID (gdk_env,
-                                                     gtkwindowpeer,
-                                                     "postInsetsChangedEvent",
-                                                     "(IIII)V");
-    }
-
+  gu_ex.extents = &extents;
   if (gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE) == event->atom
       && gdk_property_get (event->window,
                            gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
@@ -714,13 +688,51 @@ window_property_changed_cb (GtkWidget *widget __attribute__((unused)),
                            NULL,
                            NULL,
                            NULL,
-                           (guchar **)&extents))
-    (*gdk_env)->CallVoidMethod (gdk_env, peer,
-                               postInsetsChangedEventID,
-                               (jint) extents[2],  /* top */
-                               (jint) extents[0],  /* left */
-                               (jint) extents[3],  /* bottom */
-                               (jint) extents[1]); /* right */
+                           gu_ex.gu_extents))
+    {
+      gdk_threads_leave ();
+      (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+                                   postInsetsChangedEventID,
+                                   (jint) extents[2],  /* top */
+                                   (jint) extents[0],  /* left */
+                                   (jint) extents[3],  /* bottom */
+                                   (jint) extents[1]); /* right */
+      gdk_threads_enter ();
+    }
+  
 
   return FALSE;
 }
+
+static void
+realize_cb (GtkWidget *widget, jobject peer)
+{
+  jint top = 0;
+  jint left = 0;
+  jint bottom = 0;
+  jint right = 0;
+  jint width = 0;
+  jint height = 0;
+
+  width = (*gdk_env())->CallIntMethod (gdk_env(), peer, windowGetWidthID);
+  height = (*gdk_env())->CallIntMethod (gdk_env(), peer, windowGetHeightID);
+
+  window_get_frame_extents (widget, &top, &left, &bottom, &right);
+
+  (*gdk_env())->CallVoidMethod (gdk_env(), peer,
+                               postInsetsChangedEventID,
+                               top, left, bottom, right);
+
+  gtk_window_set_default_size (GTK_WINDOW (widget),
+                              MAX (1, width - left - right),
+                              MAX (1, height - top - bottom));
+
+  /* set the size like we do in nativeSetBounds */
+  gtk_widget_set_size_request (widget,
+                              MAX (1, width - left - right),
+                              MAX (1, height - top - bottom));
+
+  gtk_window_resize (GTK_WINDOW (widget),
+                    MAX (1, width - left - right),
+                    MAX (1, height - top - bottom));
+}