This fixes a long outstanding AWT issue:
- Frame.set[Extended]State() is now fully supported (save for the
MAXIMIZE_VERT and MAXIMIZE_HORIZ settings, which isn't supported in GTK
yet). This means that an application can now request the AWT to
iconify/maximize a Frame.
- The window state events are now reported correctly and include the
extended states.

2006-10-18  Roman Kennke  <[EMAIL PROTECTED]>

        PR 27091
        * gnu/java/awt/peer/gtk/GtkFramePeer.java
        (maximize): New native method.
        (unmaximize): New native method.
        (iconify): New native method.
        (deiconify): New native method.
        (getState): Implemented.
        (setState): Implemented.
        * gnu/java/awt/peer/gtk/GtkWindowPeer.java
        (oldState): Rename to windowState and made protected, so that
        the FramePeer can access it.
        (postWindowEvent): Handle state change events more gently and
        correctly.
        * java/awt/Frame.java
        (getState): Fetch state from getExtendedState().
        (setExtendedState): Update the peer. Check if the state change
        is actually supported.
        (getExtendedState): Update the state from the peer.
        * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c
        (maximize): New method.
        (unmaximize): New method.
        (iconify): New method.
        (deiconify): New method.
        * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
        (AWT_FRAME_NORMAL): New macro.
        (AWT_FRAME_ICONIFIED): New macro.
        (AWT_FRAME_MAXIMIZED_BOTH): New macro.
        (window_window_state_cb): Rewritten to handle window state changes
        more gently (mostly on the java side of the world).
        * include/gnu_java_awt_peer_gtk_GtkFramePeer.h: Regenerated.

/Roman

Index: include/gnu_java_awt_peer_gtk_GtkFramePeer.h
===================================================================
RCS file: /cvsroot/classpath/classpath/include/gnu_java_awt_peer_gtk_GtkFramePeer.h,v
retrieving revision 1.13
diff -u -1 -5 -r1.13 gnu_java_awt_peer_gtk_GtkFramePeer.h
--- include/gnu_java_awt_peer_gtk_GtkFramePeer.h	30 Apr 2006 10:37:36 -0000	1.13
+++ include/gnu_java_awt_peer_gtk_GtkFramePeer.h	18 Oct 2006 22:08:07 -0000
@@ -4,22 +4,26 @@
 #define __gnu_java_awt_peer_gtk_GtkFramePeer__
 
 #include <jni.h>
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
 JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_getMenuBarHeight (JNIEnv *env, jobject, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarWidthUnlocked (JNIEnv *env, jobject, jobject, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarWidth (JNIEnv *env, jobject, jobject, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_setMenuBarPeer (JNIEnv *env, jobject, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_removeMenuBarPeer (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_gtkFixedSetVisible (JNIEnv *env, jobject, jboolean);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_maximize (JNIEnv *env, jobject);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_unmaximize (JNIEnv *env, jobject);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_iconify (JNIEnv *env, jobject);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_deiconify (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImage (JNIEnv *env, jobject, jobject);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* __gnu_java_awt_peer_gtk_GtkFramePeer__ */
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c,v
retrieving revision 1.11
diff -u -1 -5 -r1.11 gnu_java_awt_peer_gtk_GtkFramePeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c	29 May 2006 16:14:59 -0000	1.11
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c	18 Oct 2006 22:08:07 -0000
@@ -176,15 +176,59 @@
 {
   void *ptr;
   GdkPixbuf *pixbuf = NULL;
 
   gdk_threads_enter ();
 
   pixbuf = cp_gtk_image_get_pixbuf (env, gtkimage);
   g_assert (pixbuf != NULL);
 
   ptr = NSA_GET_PTR (env, obj);
 
   gtk_window_set_icon (GTK_WINDOW (ptr), pixbuf);
 
   gdk_threads_leave ();
 }
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkFramePeer_maximize
+(JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  gdk_threads_enter ();
+  ptr = NSA_GET_PTR (env, obj);
+  gtk_window_maximize (GTK_WINDOW (ptr));
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkFramePeer_unmaximize
+(JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  gdk_threads_enter ();
+  ptr = NSA_GET_PTR (env, obj);
+  gtk_window_unmaximize (GTK_WINDOW (ptr));
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkFramePeer_iconify
+(JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  gdk_threads_enter ();
+  ptr = NSA_GET_PTR (env, obj);
+  gtk_window_iconify (GTK_WINDOW (ptr));
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkFramePeer_deiconify
+(JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  gdk_threads_enter ();
+  ptr = NSA_GET_PTR (env, obj);
+  gtk_window_deiconify (GTK_WINDOW (ptr));
+  gdk_threads_leave ();
+}
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c,v
retrieving revision 1.70
diff -u -1 -5 -r1.70 gnu_java_awt_peer_gtk_GtkWindowPeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c	18 Oct 2006 19:26:20 -0000	1.70
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c	18 Oct 2006 22:08:08 -0000
@@ -42,30 +42,34 @@
 #include <gdk/gdkprivate.h>
 #include <gdk/gdkx.h>
 #include <X11/Xatom.h>
 #include <gdk/gdkkeysyms.h>
 
 #define AWT_WINDOW_CLOSING 201
 #define AWT_WINDOW_CLOSED 202
 #define AWT_WINDOW_ICONIFIED 203
 #define AWT_WINDOW_DEICONIFIED 204
 #define AWT_WINDOW_ACTIVATED 205
 #define AWT_WINDOW_DEACTIVATED 206
 #define AWT_WINDOW_GAINED_FOCUS 207
 #define AWT_WINDOW_LOST_FOCUS 208
 #define AWT_WINDOW_STATE_CHANGED 209
 
+#define AWT_FRAME_NORMAL 0
+#define AWT_FRAME_ICONIFIED 1
+#define AWT_FRAME_MAXIMIZED_BOTH 6
+
 /* Virtual Keys */
 /* This list should be kept in the same order as the VK_ field
    declarations in KeyEvent.java. */
 #define VK_ENTER '\n'
 #define VK_BACK_SPACE '\b'
 #define VK_TAB '\t'
 #define VK_CANCEL 3
 #define VK_CLEAR 12
 #define VK_SHIFT 16
 #define VK_CONTROL 17
 #define VK_ALT 18
 #define VK_PAUSE 19
 #define VK_CAPS_LOCK 20
 #define VK_ESCAPE 27
 #define VK_SPACE ' '
@@ -1691,65 +1695,48 @@
 		     jobject peer)
 {
   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
                               postWindowEventID,
                               (jint) AWT_WINDOW_LOST_FOCUS,
                               (jobject) NULL, (jint) 0);
 
   return FALSE;
 }
 
 static gboolean
 window_window_state_cb (GtkWidget *widget __attribute__((unused)),
 			GdkEvent *event,
 			jobject peer)
 {
-  jint new_state;
-
-  /* Handle WINDOW_ICONIFIED and WINDOW_DEICONIFIED events. */
-  if (event->window_state.changed_mask & GDK_WINDOW_STATE_ICONIFIED)
-    {
-      /* We've either been iconified or deiconified. */
-      if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
-	{
-	  /* We've been iconified. */
-	  (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
-				      postWindowEventID,
-				      (jint) AWT_WINDOW_ICONIFIED,
-				      (jobject) NULL, (jint) 0);
-	}
-      else
-	{
-	  /* We've been deiconified. */
-	  (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
-				      postWindowEventID,
-				      (jint) AWT_WINDOW_DEICONIFIED,
-				      (jobject) NULL, (jint) 0);
-	}
-    }
-
-  /* Post a WINDOW_STATE_CHANGED event, passing the new frame state to
-     GtkWindowPeer. */
-  new_state = AWT_FRAME_STATE_NORMAL;
-
-  if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED)
-    new_state |= AWT_FRAME_STATE_ICONIFIED;
+  jint new_java_state = 0;
+  /* Put together the new state and let the java side figure out what
+   * to post */
+  GdkWindowState new_state = event->window_state.new_window_state;
+  /* The window can be either iconfified, maximized, iconified + maximized
+   * or normal. */
+  if ((new_state & GDK_WINDOW_STATE_ICONIFIED) != 0)
+    new_java_state |= AWT_FRAME_ICONIFIED;
+  if ((new_state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
+    new_java_state |= AWT_FRAME_MAXIMIZED_BOTH;
+  if ((new_state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_ICONIFIED))
+      == 0)
+    new_java_state = AWT_FRAME_NORMAL;
 
   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
 			      postWindowEventID,
 			      (jint) AWT_WINDOW_STATE_CHANGED,
-			      (jobject) NULL, new_state);
+			      (jobject) NULL, new_java_state);
 
   return TRUE;
 }
 
 static gboolean
 window_property_changed_cb (GtkWidget *widget __attribute__((unused)),
                             GdkEventProperty *event,
                             jobject peer)
 {
   unsigned long *extents;
   union extents_union gu_ex;
 
   gu_ex.extents = &extents;
   if (gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE) == event->atom
       && gdk_property_get (event->window,
Index: gnu/java/awt/peer/gtk/GtkFramePeer.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java,v
retrieving revision 1.48
diff -u -1 -5 -r1.48 GtkFramePeer.java
--- gnu/java/awt/peer/gtk/GtkFramePeer.java	17 Jul 2006 22:41:03 -0000	1.48
+++ gnu/java/awt/peer/gtk/GtkFramePeer.java	18 Oct 2006 22:08:09 -0000
@@ -45,30 +45,35 @@
 import java.awt.peer.FramePeer;
 import java.awt.peer.MenuBarPeer;
 
 public class GtkFramePeer extends GtkWindowPeer
     implements FramePeer
 {
   private int menuBarHeight;
   private MenuBarPeer menuBar;
   native int getMenuBarHeight (MenuBarPeer bar);
   native void setMenuBarWidthUnlocked (MenuBarPeer bar, int width);
   native void setMenuBarWidth (MenuBarPeer bar, int width);
   native void setMenuBarPeer (MenuBarPeer bar);
   native void removeMenuBarPeer ();
   native void gtkFixedSetVisible (boolean visible);
 
+  private native void maximize();
+  private native void unmaximize();
+  private native void iconify();
+  private native void deiconify();
+
   int getMenuBarHeight ()
   {
     return menuBar == null ? 0 : getMenuBarHeight (menuBar);
   }
 
   public void setMenuBar (MenuBar bar)
   {
     if (bar == null && menuBar != null)
       {
         // We're removing the menubar.
         gtkFixedSetVisible (false);
         menuBar = null;
         removeMenuBarPeer ();
         insets.top -= menuBarHeight;
         menuBarHeight = 0;
@@ -187,36 +192,49 @@
 
     // Since insets.top already includes the MenuBar's height, we need
     // to subtract the MenuBar's height from the top inset.
     int frame_height = height - menuBarHeight;
 
     // Likewise, since insets.top includes the MenuBar height, we need
     // to add back the MenuBar height to the frame's y position.  If
     // no MenuBar exists in this frame, the MenuBar height will be 0.
     int frame_y = y + menuBarHeight;
 
     super.postConfigureEvent(x, frame_y, width, frame_height);
   }
 
   public int getState ()
   {
-    return 0;
+    return windowState;
   }
 
   public void setState (int state)
   {
-
+    switch (state)
+      {
+        case Frame.NORMAL:
+          if ((windowState & Frame.ICONIFIED) != 0)
+            deiconify();
+          if ((windowState & Frame.MAXIMIZED_BOTH) != 0)
+            unmaximize();
+          break;
+        case Frame.ICONIFIED:
+          iconify();
+          break;
+        case Frame.MAXIMIZED_BOTH:
+          maximize();
+      }
   }
 
   public void setMaximizedBounds (Rectangle r)
   {
 
   }
   public void setBoundsPrivate(int x, int y, int width, int height)
   {
     // TODO Auto-generated method stub
     
   }
 
   public boolean requestWindowFocus()
   {
     // TODO Auto-generated method stub
Index: gnu/java/awt/peer/gtk/GtkToolkit.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java,v
retrieving revision 1.93
diff -u -1 -5 -r1.93 GtkToolkit.java
--- gnu/java/awt/peer/gtk/GtkToolkit.java	8 Aug 2006 22:23:36 -0000	1.93
+++ gnu/java/awt/peer/gtk/GtkToolkit.java	18 Oct 2006 22:08:09 -0000
@@ -652,18 +652,26 @@
   public RobotPeer createRobot (GraphicsDevice screen) throws AWTException
   {
     return new GdkRobotPeer (screen);
   }
 
   public void registerImageIOSpis(IIORegistry reg)
   {
     GdkPixbufDecoder.registerSpis(reg);
   }
 
   protected MouseInfoPeer getMouseInfoPeer()
   {
     return new GtkMouseInfoPeer();
   }
 
+  public boolean isFrameStateSupported(int state)
+  {
+    // GTK supports ICONFIED, NORMAL and MAXIMIZE_BOTH, but
+    // not (yet?) MAXIMIZE_VERT and MAXIMIZE_HORIZ.
+    return state == Frame.NORMAL || state == Frame.ICONIFIED
+           || state == Frame.MAXIMIZED_BOTH;
+  }
+
   public native int getMouseNumberOfButtons();
 
 } // class GtkToolkit
Index: gnu/java/awt/peer/gtk/GtkWindowPeer.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java,v
retrieving revision 1.56
diff -u -1 -5 -r1.56 GtkWindowPeer.java
--- gnu/java/awt/peer/gtk/GtkWindowPeer.java	18 Oct 2006 19:26:20 -0000	1.56
+++ gnu/java/awt/peer/gtk/GtkWindowPeer.java	18 Oct 2006 22:08:10 -0000
@@ -52,31 +52,31 @@
 import java.awt.event.WindowEvent;
 import java.awt.peer.WindowPeer;
 
 public class GtkWindowPeer extends GtkContainerPeer
   implements WindowPeer
 {
   protected static final int GDK_WINDOW_TYPE_HINT_NORMAL = 0;
   protected static final int GDK_WINDOW_TYPE_HINT_DIALOG = 1;
   protected static final int GDK_WINDOW_TYPE_HINT_MENU = 2;
   protected static final int GDK_WINDOW_TYPE_HINT_TOOLBAR = 3;
   protected static final int GDK_WINDOW_TYPE_HINT_SPLASHSCREEN = 4;
   protected static final int GDK_WINDOW_TYPE_HINT_UTILITY = 5;
   protected static final int GDK_WINDOW_TYPE_HINT_DOCK = 6;
   protected static final int GDK_WINDOW_TYPE_HINT_DESKTOP = 7;
 
-  private int oldState = Frame.NORMAL;
+  protected int windowState = Frame.NORMAL;
 
   // Cached awt window component location, width and height.
   private int x, y, width, height;
 
   native void gtkWindowSetTitle (String title);
   native void gtkWindowSetResizable (boolean resizable);
   native void gtkWindowSetModal (boolean modal);
   native void gtkWindowSetAlwaysOnTop ( boolean alwaysOnTop );
   native boolean gtkWindowHasFocus();
   native void realize ();
 
   public void dispose()
   {
     super.dispose();
     GtkMainThread.destroyWindow();
@@ -272,35 +272,48 @@
 
   public void show ()
   {
     x = awtComponent.getX();
     y = awtComponent.getY();
     width = awtComponent.getWidth();
     height = awtComponent.getHeight();
     setLocation(x, y);
     setVisible (true);
   }
 
   void postWindowEvent (int id, Window opposite, int newState)
   {
     if (id == WindowEvent.WINDOW_STATE_CHANGED)
       {
-	if (oldState != newState)
+	if (windowState != newState)
 	  {
-	    q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite,
-					  oldState, newState));
-	    oldState = newState;
+            // Post old styleWindowEvent with WINDOW_ICONIFIED or
+            // WINDOW_DEICONIFIED if appropriate.
+            if ((windowState & Frame.ICONIFIED) != 0
+                && (newState & Frame.ICONIFIED) == 0)
+              q().postEvent(new WindowEvent((Window) awtComponent,
+                                            WindowEvent.WINDOW_DEICONIFIED,
+                                            opposite, 0, 0));
+            else if ((windowState & Frame.ICONIFIED) == 0
+                && (newState & Frame.ICONIFIED) != 0)
+              q().postEvent(new WindowEvent((Window) awtComponent,
+                                            WindowEvent.WINDOW_ICONIFIED,
+                                            opposite, 0, 0));
+            // Post new-style WindowStateEvent.
+	    q().postEvent (new WindowEvent ((Window) awtComponent, id,
+                                            opposite, windowState, newState));
+	    windowState = newState;
 	  }
       }
     else
       q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite));
   }
 
   /**
    * Update the always-on-top status of the native window.
    */
   public void updateAlwaysOnTop()
   {
     gtkWindowSetAlwaysOnTop( ((Window)awtComponent).isAlwaysOnTop() );
   }
 
   protected void postExposeEvent (int x, int y, int width, int height)
Index: java/awt/Frame.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Frame.java,v
retrieving revision 1.39
diff -u -1 -5 -r1.39 Frame.java
--- java/awt/Frame.java	20 Sep 2006 09:12:25 -0000	1.39
+++ java/awt/Frame.java	18 Oct 2006 22:08:10 -0000
@@ -524,47 +524,55 @@
   public void setState(int state)
   {
     int current_state = getExtendedState ();
 
     if (state == NORMAL
         && (current_state & ICONIFIED) != 0)
       setExtendedState(current_state | ICONIFIED);
     
     if (state == ICONIFIED
         && (current_state & ~ICONIFIED) == 0)
       setExtendedState(current_state & ~ICONIFIED);
   }
 
   public int getState()
   {
-    // FIXME: State might have changed in the peer... Must check.
-    return (state & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
+    return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
   }
 
   /**
    * @since 1.4
    */
   public void setExtendedState(int state)
   {
-    this.state = state;
+    if (getToolkit().isFrameStateSupported(state))
+      {
+        this.state = state;
+        FramePeer p = (FramePeer) peer;
+        if (p != null)
+          p.setState(state);
+      }
   }
 
   /**
    * @since 1.4
    */
   public int getExtendedState()
   {
+    FramePeer p = (FramePeer) peer;
+    if (p != null)
+      state = p.getState();
     return state;
   }
 
   /**
    * @since 1.4
    */
   public void setMaximizedBounds(Rectangle maximizedBounds)
   {
     this.maximizedBounds = maximizedBounds;
   }
 
   /**
    * Returns the maximized bounds of this frame.
    *
    * @return the maximized rectangle, may be null

Reply via email to