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