This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Patch: Window and Dialog fixes


On Wed, 2003-09-10 at 13:08, Tom Tromey wrote:
> >>>>> "Tom" == Thomas Fitzsimmons <fitzsim@redhat.com> writes:
> 
> More comments...
> 
> Tom> +    parent = owner;
> Tom> +    owner.ownedWindows.add(new WeakReference(this));
> 
> Synchronization is needed here, when changing owner.ownedWindows, as
> the other users of ownedWindows also synchronize.
> 
> Should we synchronize on the tree lock instead of on the Window?
> 
> Tom> +  public synchronized Window[] getOwnedWindows()
> 
> This method needs to be implemented a different way.  The problem is
> that a WeakReference can be cleared between the two loops.
> 
> Maybe the only way to do this is to allocate a possibly-too-large
> array, fill it, and then create a new, smaller array if need be.
> 

OK, thanks for the comments.

I reworked this patch a little.  I realized that null weak references
weren't being removed from ownedWindows.  With this iteration of the
patch, I remove them as I discover them.

Accesses to ownedWindows are now synchronized on ownedWindows itself
instead of on the window.

And I fixed the problem Tom noted with getOwnedWindows.

OK to commit?

Thanks,
Tom

2003-09-19  Thomas Fitzsimmons  <fitzsim@redhat.com>

	* gnu/java/awt/peer/gtk/GtkDialogPeer.java (create()): Create a
	top-level GTK window.
	(getArgs): Add "title" property.
	* gnu/java/awt/peer/gtk/GtkWindowPeer.java (setResizable): Use
	"allow_shrink" and "allow_grow" properties.
	* java/awt/Dialog.java: Initialize resizable to true and change
	comments accordingly.  Initialize visible to false in
	constructors.
	* java/awt/Frame.java (dispose): Remove method.
	* java/awt/Window.java (ownedWindows): New field.
	(Window(Window,GraphicsConfiguration)): Add a weak reference to
	owner's ownedWindows vector.
	(finalize): Remove method.
	(hide): Hide owned windows.
	(dispose): Dispose of owned windows.
	(getOwnedWindows): Implement.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c: Remove
	unused GtkArg code.
	(set(String,boolean)): Clamp gboolean parameter to g_object_set
	to TRUE or FALSE.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
	(create): Set window's size requisition.
	(connectHooks): Fix indentation.
	(setResizable): Remove function.
	(static setBounds): Likewise.
	(setBounds): Replace call to setBounds with GTK size requisition
	and resize calls.

Index: gnu/java/awt/peer/gtk/GtkDialogPeer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java,v
retrieving revision 1.4
diff -u -r1.4 GtkDialogPeer.java
--- gnu/java/awt/peer/gtk/GtkDialogPeer.java	2 Sep 2003 23:04:05 -0000	1.4
+++ gnu/java/awt/peer/gtk/GtkDialogPeer.java	19 Sep 2003 18:51:23 -0000
@@ -53,7 +53,7 @@
 
   void create ()
   {
-    create (GTK_WINDOW_POPUP,
+    create (GTK_WINDOW_TOPLEVEL,
 	    awtComponent.getWidth(),
 	    awtComponent.getHeight());
   }
@@ -64,6 +64,7 @@
 
     Dialog dialog = (Dialog) component;
 
+    args.add ("title", dialog.getTitle ());
     args.add ("modal", dialog.isModal ());
     args.add ("allow_shrink", dialog.isResizable ());
     args.add ("allow_grow", dialog.isResizable ());
Index: gnu/java/awt/peer/gtk/GtkFramePeer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkFramePeer.java,v
retrieving revision 1.3
diff -u -r1.3 GtkFramePeer.java
--- gnu/java/awt/peer/gtk/GtkFramePeer.java	13 Jul 2003 15:09:20 -0000	1.3
+++ gnu/java/awt/peer/gtk/GtkFramePeer.java	19 Sep 2003 18:51:23 -0000
@@ -84,6 +84,7 @@
     args.add ("allow_shrink", frame.isResizable ());
     args.add ("allow_grow", frame.isResizable ());
   }
+
   public void setIconImage (Image image) 
   {
       /* TODO: Waiting on Toolkit Image routines */
Index: gnu/java/awt/peer/gtk/GtkWindowPeer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkWindowPeer.java,v
retrieving revision 1.4
diff -u -r1.4 GtkWindowPeer.java
--- gnu/java/awt/peer/gtk/GtkWindowPeer.java	2 Sep 2003 23:04:05 -0000	1.4
+++ gnu/java/awt/peer/gtk/GtkWindowPeer.java	19 Sep 2003 18:51:23 -0000
@@ -53,7 +53,9 @@
 
   void create (int type)
   {
-    create (type, awtComponent.getWidth(), awtComponent.getHeight());
+    create (type,
+	    awtComponent.getWidth(),
+	    awtComponent.getHeight());
   }
 
   void create ()
@@ -75,7 +77,7 @@
     args.add ("visible", component.isVisible ());
     args.add ("sensitive", component.isEnabled ());
   }
-  
+
   native public void toBack ();
   native public void toFront ();
 
@@ -86,7 +88,11 @@
     set ("title", title);
   }
 
-  native public void setResizable (boolean r);
+  public void setResizable (boolean resizable)
+  {
+    set ("allow_shrink", resizable);
+    set ("allow_grow", resizable);
+  }
 
   protected void postConfigureEvent (int x, int y, int width, int height,
 				     int top, int left, int bottom, int right)
Index: java/awt/Dialog.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/Dialog.java,v
retrieving revision 1.9
diff -u -r1.9 Dialog.java
--- java/awt/Dialog.java	5 Jun 2003 19:58:39 -0000	1.9
+++ java/awt/Dialog.java	19 Sep 2003 18:51:23 -0000
@@ -70,7 +70,7 @@
 /**
   * @serial Indicates whether or not this dialog box is resizable.
   */
-private boolean resizable;
+private boolean resizable = true;
 
 /**
   * @serial The title string for this dialog box, which can be
@@ -91,7 +91,7 @@
 
 /**
   * Initializes a new instance of <code>Dialog</code> with the specified
-  * parent, that is not resizable and not modal, and which has no title.
+  * parent, that is resizable and not modal, and which has no title.
   *
   * @param parent The parent frame of this dialog box.
   *
@@ -109,7 +109,7 @@
 
 /**
   * Initializes a new instance of <code>Dialog</code> with the specified
-  * parent and modality, that is not resizable and which has no title.
+  * parent and modality, that is resizable and which has no title.
   *
   * @param parent The parent frame of this dialog box.
   * @param modal <true> if this dialog box is modal, <code>false</code>
@@ -129,7 +129,7 @@
 
 /**
   * Initializes a new instance of <code>Dialog</code> with the specified
-  * parent, that is not resizable and not modal, and which has the specified
+  * parent, that is resizable and not modal, and which has the specified
   * title.
   *
   * @param parent The parent frame of this dialog box.
@@ -149,7 +149,7 @@
 
 /**
   * Initializes a new instance of <code>Dialog</code> with the specified,
-  * parent, title, and modality, that is not resizable.
+  * parent, title, and modality, that is resizable.
   *
   * @param parent The parent frame of this dialog box.
   * @param title The title string for this dialog box.
@@ -168,7 +168,7 @@
 /**
  * Initializes a new instance of <code>Dialog</code> with the specified,
  * parent, title, modality and <code>GraphicsConfiguration</code>,
- * that is not resizable.
+ * that is resizable.
  *
  * @param parent The parent frame of this dialog box.
  * @param title The title string for this dialog box.
@@ -189,14 +189,14 @@
 
   this.title = title;
   this.modal = modal;
-  resizable = false;
+  visible = false;
 
   setLayout(new BorderLayout());
 }
 
 /**
  * Initializes a new instance of <code>Dialog</code> with the specified,
- * parent, that is not resizable.
+ * parent, that is resizable.
  *
  * @exception IllegalArgumentException If parent is null. This exception is
  * always thrown when GraphicsEnvironment.isHeadless() returns true.
@@ -211,7 +211,7 @@
 
 /**
  * Initializes a new instance of <code>Dialog</code> with the specified,
- * parent and title, that is not resizable.
+ * parent and title, that is resizable.
  *
  * @exception IllegalArgumentException If parent is null. This exception is
  * always thrown when GraphicsEnvironment.isHeadless() returns true.
@@ -226,7 +226,7 @@
 
 /**
  * Initializes a new instance of <code>Dialog</code> with the specified,
- * parent, title and modality, that is not resizable.
+ * parent, title and modality, that is resizable.
  *
  * @exception IllegalArgumentException If parent is null. This exception is
  * always thrown when GraphicsEnvironment.isHeadless() returns true.
@@ -242,7 +242,7 @@
 /**
  * Initializes a new instance of <code>Dialog</code> with the specified,
  * parent, title, modality and <code>GraphicsConfiguration</code>,
- * that is not resizable.
+ * that is resizable.
  *
  * @exception IllegalArgumentException If parent is null, the
  * GraphicsConfiguration is not a screen device or
@@ -255,10 +255,10 @@
 {
   super (parent, parent.getGraphicsConfiguration ());
   
-  this.modal = modal;
   this.title = title;
-  resizable = false;
-  
+  this.modal = modal;
+  visible = false;
+
   setLayout (new BorderLayout ());
 }
 
Index: java/awt/Frame.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/Frame.java,v
retrieving revision 1.17
diff -u -r1.17 Frame.java
--- java/awt/Frame.java	2 Sep 2003 23:04:05 -0000	1.17
+++ java/awt/Frame.java	19 Sep 2003 18:51:23 -0000
@@ -438,25 +438,6 @@
 /*************************************************************************/
 
 /**
-  * Destroys any resources associated with this frame.  This includes
-  * all components in the frame and all owned toplevel windows.
-  */
-public void
-dispose()
-{
-  Enumeration e = ownedWindows.elements();
-  while(e.hasMoreElements())
-    {
-      Window w = (Window)e.nextElement();
-      w.dispose();
-    }
-
-  super.dispose();
-}
-
-/*************************************************************************/
-
-/**
   * Returns a debugging string describing this window.
   *
   * @return A debugging string describing this window.
@@ -472,8 +453,6 @@
 {
   //Frame[] array = new Frames[frames.size()];
   //return frames.toArray(array);
-    
-    // see finalize() comment
   String msg = "FIXME: can't be implemented without weak references";
   throw new UnsupportedOperationException(msg);
 }
Index: java/awt/Window.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/Window.java,v
retrieving revision 1.28
diff -u -r1.28 Window.java
--- java/awt/Window.java	27 Jul 2003 19:38:00 -0000	1.28
+++ java/awt/Window.java	19 Sep 2003 18:51:23 -0000
@@ -43,9 +43,13 @@
 import java.awt.event.WindowListener;
 import java.awt.event.WindowStateListener;
 import java.awt.peer.WindowPeer;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.Iterator;
 import java.util.EventListener;
 import java.util.Locale;
 import java.util.ResourceBundle;
+import java.util.Vector;
 import javax.accessibility.Accessible;
 import javax.accessibility.AccessibleContext;
 
@@ -69,6 +73,9 @@
   /** @since 1.4 */
   private boolean focusableWindowState = true;
 
+  // A list of other top-level windows owned by this window.
+  private transient Vector ownedWindows = new Vector();
+
   private transient WindowListener windowListener;
   private transient WindowFocusListener windowFocusListener;
   private transient WindowStateListener windowStateListener;
@@ -139,11 +146,13 @@
     if (owner == null)
       throw new IllegalArgumentException ("owner must not be null");
 
-    this.parent = owner;
-    
-    // FIXME: add to owner's "owned window" list
-    //owner.owned.add(this); // this should be a weak reference
-    
+    parent = owner;
+
+    synchronized (owner.ownedWindows)
+      {
+        owner.ownedWindows.add(new WeakReference(this));
+      }
+
     // FIXME: make this text visible in the window.
     SecurityManager s = System.getSecurityManager();
     if (s != null && ! s.checkTopLevelWindow(this))
@@ -171,18 +180,6 @@
   }
 
   /**
-   * Disposes of the input methods and context, and removes the WeakReference
-   * which formerly pointed to this Window from the parent's owned Window list.
-   *
-   * @exception Throwable The Exception raised by this method.
-   */
-  protected void finalize() throws Throwable
-  {
-    // FIXME: remove from owner's "owned window" list (Weak References)
-    super.finalize();
-  }
-
-  /**
    * Creates the native peer for this window.
    */
   public void addNotify()
@@ -227,7 +224,23 @@
 
   public void hide()
   {
-    // FIXME: call hide() on any "owned" children here.
+    synchronized (ownedWindows)
+      {
+	Iterator e = ownedWindows.iterator();
+	while(e.hasNext())
+	  {
+	    Window w = (Window)(((Reference) e.next()).get());
+	    if (w != null)
+	      w.hide();
+     	    else
+	      // Remove null weak reference from ownedWindows.
+	      // Unfortunately this can't be done in the Window's
+	      // finalize method because there is no way to guarantee
+	      // synchronous access to ownedWindows there.
+	      e.remove();
+	  }
+      }
+
     super.hide();
   }
 
@@ -239,15 +252,26 @@
   }
 
   /**
-   * Called to free any resource associated with this window.
+   * Destroys any resources associated with this window.  This includes
+   * all components in the window and all owned top-level windows.
    */
   public void dispose()
   {
     hide();
 
-    Window[] list = getOwnedWindows();
-    for (int i=0; i<list.length; i++)
-      list[i].dispose();
+    synchronized (ownedWindows)
+      {
+	Iterator e = ownedWindows.iterator();
+	while(e.hasNext())
+	  {
+	    Window w = (Window)(((Reference) e.next()).get());
+	    if (w != null)
+	      w.dispose();
+	    else
+	      // Remove null weak reference from ownedWindows.
+	      e.remove();
+	  }
+      }
 
     for (int i = 0; i < ncomponents; ++i)
       component[i].removeNotify();
@@ -340,9 +364,33 @@
   /** @since 1.2 */
   public Window[] getOwnedWindows()
   {
-    // FIXME: return array containing all the windows this window currently 
-    // owns.
-    return new Window[0];
+    Window [] trimmedList;
+    synchronized (ownedWindows)
+      {
+	// Windows with non-null weak references in ownedWindows.
+	Window [] validList = new Window [ownedWindows.size()];
+
+	Iterator e = ownedWindows.iterator();
+	int numValid = 0;
+	while (e.hasNext())
+	  {
+	    Window w = (Window)(((Reference) e.next()).get());
+	    if (w != null)
+	      validList[numValid++] = w;
+	    else
+	      // Remove null weak reference from ownedWindows.
+	      e.remove();
+	  }
+
+	if (numValid != validList.length)
+	  {
+	    trimmedList = new Window [numValid];
+	    System.arraycopy (validList, 0, trimmedList, 0, numValid);
+	  }
+	else
+	  trimmedList = validList;
+      }
+    return trimmedList;
   }
 
   /**
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c,v
retrieving revision 1.4
diff -u -r1.4 gnu_java_awt_peer_gtk_GtkComponentPeer.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	5 Aug 2003 18:04:09 -0000	1.4
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	19 Sep 2003 18:51:24 -0000
@@ -494,15 +494,11 @@
   const char *name;
   const char *value;
   void *ptr;
-  GtkArg arg;
 
   ptr = NSA_GET_PTR (env, obj);
   name = (*env)->GetStringUTFChars (env, jname, NULL);
   value = (*env)->GetStringUTFChars (env, jvalue, NULL);
 
-  arg.type = GTK_TYPE_STRING;
-  arg.name = (char *) name;
-  GTK_VALUE_STRING (arg) = (char *) value;
   gdk_threads_enter();
   g_object_set(ptr, name, value, NULL);
   gdk_threads_leave();
@@ -512,20 +508,20 @@
 }
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_set__Ljava_lang_String_2Z
-  (JNIEnv *env, jobject obj, jstring jname, jboolean value)
+  (JNIEnv *env, jobject obj, jstring jname, jboolean jvalue)
 {
   const char *name;
+  gboolean value;
   void *ptr;
-  GtkArg arg;
 
   ptr = NSA_GET_PTR (env, obj);
-  name = (*env)->GetStringUTFChars (env, jname, NULL);
 
-  arg.type = GTK_TYPE_BOOL;
-  arg.name = (char *) name;
-  GTK_VALUE_BOOL (arg) = value;
+  name = (*env)->GetStringUTFChars (env, jname, NULL);
+  /* Apparently a jboolean can have a value greater than 1.  gboolean
+     variables may only contain the value TRUE or FALSE. */
+  value = jvalue ? TRUE : FALSE;
 
-  gdk_threads_enter();                          
+  gdk_threads_enter();
   g_object_set(ptr, name, value, NULL);
   gdk_threads_leave();
 
@@ -537,15 +533,10 @@
 {
   const char *name;
   void *ptr;
-  GtkArg arg;
 
   ptr = NSA_GET_PTR (env, obj);
   name = (*env)->GetStringUTFChars (env, jname, NULL);
 
-  arg.type = GTK_TYPE_INT;
-  arg.name = (char *) name;
-  GTK_VALUE_INT (arg) = value;
-  
   gdk_threads_enter();                          
   g_object_set(ptr, name, value, NULL);
   gdk_threads_leave();
@@ -558,15 +549,10 @@
 {
   const char *name;
   void *ptr;
-  GtkArg arg;
 
   ptr = NSA_GET_PTR (env, obj);
   name = (*env)->GetStringUTFChars (env, jname, NULL);
 
-  arg.type = GTK_TYPE_FLOAT;
-  arg.name = (char *) name;
-  GTK_VALUE_FLOAT (arg) = value;
-  
   gdk_threads_enter();                          
   g_object_set(ptr, name, value, NULL);
   gdk_threads_leave();
@@ -580,7 +566,6 @@
 {
   const char *name;
   void *ptr1, *ptr2;
-  GtkArg arg;
 
   ptr1 = NSA_GET_PTR (env, obj1);
   ptr2 = NSA_GET_PTR (env, obj2);
@@ -598,10 +583,6 @@
       return;
     }
 
-  arg.type = GTK_TYPE_OBJECT;
-  arg.name = (char *) name;
-  GTK_VALUE_OBJECT (arg) = GTK_OBJECT (ptr2);
-  
   gdk_threads_enter();                          
   g_object_set(ptr1, name, ptr2, NULL);
   gdk_threads_leave();
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c,v
retrieving revision 1.4
diff -u -r1.4 gnu_java_awt_peer_gtk_GtkWindowPeer.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c	2 Sep 2003 23:04:05 -0000	1.4
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c	19 Sep 2003 18:51:24 -0000
@@ -42,8 +42,6 @@
 #include <gdk/gdkprivate.h>
 #include <gdk/gdkx.h>
 
-static void setBounds (GtkWidget *, jint, jint, jint, jint);
-
 /*
  * Make a new window (any type)
  */
@@ -60,6 +58,13 @@
 
   gtk_window_set_default_size (GTK_WINDOW(window), width, height);
 
+  /* 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, width, height);
+
   vbox = gtk_vbox_new (0, 0);
   layout = gtk_layout_new (NULL, NULL);
   gtk_box_pack_end (GTK_BOX (vbox), layout, 1, 1, 0);
@@ -88,6 +93,7 @@
     gtk_widget_hide (GTK_WIDGET (ptr));
 
   XFlush (GDK_DISPLAY ());
+
   gdk_threads_leave ();
 }
 
@@ -102,20 +108,20 @@
 
   gdk_threads_enter ();
 
-   children = gtk_container_get_children(GTK_CONTAINER(ptr));
-   vbox = children->data;
+  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;
+  if(!GTK_IS_VBOX(vbox))
+    {
+      printf("*** this is not a vbox\n");
+    }
+  children = gtk_container_get_children(GTK_CONTAINER(vbox));
+  layout = children->data;
 
-   if(!GTK_IS_LAYOUT(layout))
-     {
+  if(!GTK_IS_LAYOUT(layout))
+    {
       printf("*** widget is not a layout ***");
-     }
+    }
 
   gtk_widget_realize (layout);
 
@@ -177,24 +183,6 @@
 }
 
 /*
- * Set a window's resizing policy
- */
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setResizable
-  (JNIEnv *env, jobject obj, jboolean resize)
-{
-  void *ptr;
-  
-  ptr = NSA_GET_PTR (env, obj);
-  
-  gdk_threads_enter ();
-  gtk_window_set_policy (GTK_WINDOW (ptr), resize, resize, 0);
-  gdk_threads_leave ();
-}
-
-
-/*
  * Lower the z-level of a window. 
  */
 
@@ -230,12 +218,6 @@
   gdk_threads_leave ();
 }
 
-static void
-setBounds (GtkWidget *widget, jint x, jint y, jint width, jint height)
-{
-  gtk_window_resize (GTK_WINDOW(widget), width, height);
-}
-
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBounds
   (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
 {
@@ -247,7 +229,8 @@
   gdk_threads_enter ();
 
   widget = GTK_WIDGET (ptr);
-  setBounds (widget, x, y, width, height);
+  gtk_widget_set_size_request (widget, width, height);
+  gtk_window_resize (GTK_WINDOW(widget), width, height);
 
   gdk_threads_leave ();
 }
@@ -306,7 +289,7 @@
 			      gint      *depth)
 {
   GdkWindow *private;
-  
+
   g_return_if_fail (window != NULL);
   
   private = (GdkWindow*) window;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]