Hello,

Tom F. and I worked on changing how we handle Container lightweights and
Component lightweights. This bug showed up in MegaMek and several test
cases. It appeared that Containers should be handled differently.

When a Container was placed in a Window, and contained Heavyweight
components, the location of the components were always being set at
(0,0), relative to the Window. This is because the components were not
aware of the bounds of the Container. Now, GtkLightweightPeer is similar
to a GtkPanelPeer.

GtkLightweightPeer extends GtkContainerPeer. This fixes the problem. We
discovered that we could not completely get rid of GLightweightPeer
because Components still depended on its constructor.

I tested this with the swing demo and MegaMek. The painting seems to
work fine still... 

Feel free to give me feedback before I commit this. 

2006-02-21  Lillian Angel  <[EMAIL PROTECTED]>

        * gnu/java/awt/peer/gtk/GtkLightweightPeer.java:
        New class to handle Container Lightweights.
        * gnu/java/awt/peer/gtk/GtkPanelPeer.java:
        Removed unneeded import.
        * gnu/java/awt/peer/gtk/GtkToolkit.java
        (createComponent): New method to override Toolkit's
        createComponent. Returns an instance of GtkLightweightPeer
        if the target is a container, and a GLightweightPeer if the
        target is a Component.
        * include/Makefile.am:
        Added gnu_java_awt_peer_gtk_GtkLightweightPeer.h.
        * include/gnu_java_awt_peer_gtk_GtkLightweightPeer.h:
        New header file.
        * java/awt/Toolkit.java
        (createComponent): Changed to return null. This method
        should be overridden. Added comment explaining why.
        * native/jni/gtk-peer/Makefile.am:
        Added gnu_java_awt_peer_gtk_GtkLightweightPeer.c.
        * native/jni/gtk-peer/gnu_java_awt_peer_gtk_
        GtkLightweightPeer.c: New class.

Index: gnu/java/awt/peer/gtk/GtkComponentPeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java,v
retrieving revision 1.105
diff -u -r1.105 GtkComponentPeer.java
--- gnu/java/awt/peer/gtk/GtkComponentPeer.java	17 Feb 2006 19:53:06 -0000	1.105
+++ gnu/java/awt/peer/gtk/GtkComponentPeer.java	21 Feb 2006 15:11:38 -0000
@@ -166,19 +166,16 @@
     setVisibleAndEnabled ();
   }
 
-  void setParent ()
+  void setParent()
   {
     ComponentPeer p;
     Component component = awtComponent;
-    do
-      {
-        component = component.getParent ();
-        p = component.getPeer ();
-      }
-    while (p instanceof java.awt.peer.LightweightPeer);
+
+    component = component.getParent();
+    p = component.getPeer();
 
     if (p != null)
-      gtkWidgetSetParent (p);
+      gtkWidgetSetParent(p);
   }
 
   void beginNativeRepaint ()
@@ -443,38 +440,11 @@
   {
     int new_x = x;
     int new_y = y;
-
-    Component parent = awtComponent.getParent ();
-    Component next_parent;
-
-    // Heavyweight components that are children of one or more
-    // lightweight containers have to be handled specially.  Because
-    // calls to GLightweightPeer.setBounds do nothing, GTK has no
-    // knowledge of the lightweight containers' positions.  So we have
-    // to add the offsets manually when placing a heavyweight
-    // component within a lightweight container.  The lightweight
-    // container may itself be in a lightweight container and so on,
-    // so we need to continue adding offsets until we reach a
-    // container whose position GTK knows -- that is, the first
-    // non-lightweight.
-    boolean lightweightChild = false;
-    Insets i;
-    while (parent.isLightweight())
-      {
-        lightweightChild = true;
-
-        next_parent = parent.getParent();
-
-        i = ((Container) parent).getInsets();
-        new_x += parent.getX() + i.left;
-        new_y += parent.getY() + i.top;
-
-        parent = next_parent;
-      }
+    Component parent = awtComponent.getParent();
 
     // We only need to convert from Java to GTK coordinates if we're
     // placing a heavyweight component in a Window.
-    if (parent instanceof Window && !lightweightChild)
+    if (parent instanceof Window)
       {
         GtkWindowPeer peer = (GtkWindowPeer) parent.getPeer ();
         // important: we want the window peer's insets here, not the
@@ -490,7 +460,7 @@
         new_x = x - insets.left;
         new_y = y - insets.top + menuBarHeight;
       }
-
+    
     setNativeBounds (new_x, new_y, width, height);
   }
 
Index: gnu/java/awt/peer/gtk/GtkContainerPeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java,v
retrieving revision 1.33
diff -u -r1.33 GtkContainerPeer.java
--- gnu/java/awt/peer/gtk/GtkContainerPeer.java	19 Feb 2006 22:32:45 -0000	1.33
+++ gnu/java/awt/peer/gtk/GtkContainerPeer.java	21 Feb 2006 15:11:38 -0000
@@ -81,8 +81,7 @@
         for (int i = 0; i < ncomponents; i++)
           {
             ComponentPeer peer = components[i].getPeer ();
-
-            // Skip lightweight peers.
+            
             if (peer instanceof GtkComponentPeer)
               ((GtkComponentPeer) peer).setParentAndBounds ();
           }
Index: gnu/java/awt/peer/gtk/GtkLightweightPeer.java
===================================================================
RCS file: gnu/java/awt/peer/gtk/GtkLightweightPeer.java
diff -N gnu/java/awt/peer/gtk/GtkLightweightPeer.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/peer/gtk/GtkLightweightPeer.java	21 Feb 2006 15:11:38 -0000
@@ -0,0 +1,80 @@
+/* GtkLightweightPeer.java -- 
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Container;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.peer.LightweightPeer;
+
+public class GtkLightweightPeer
+  extends GtkContainerPeer
+    implements LightweightPeer
+{
+  
+  private Container cont;
+  
+  native void create();
+  native void connectSignals();
+  
+  public GtkLightweightPeer (Container c)
+  {
+    super(c);
+    cont = c;
+  }
+  
+  public Point getLocationOnScreen()
+  {
+    Point parentLocation = cont.getParent().getLocationOnScreen();
+    return new Point (parentLocation.x + cont.getX(),
+                      parentLocation.y + cont.getY());
+  }
+
+  public FontMetrics getFontMetrics(Font f)
+  {
+    return cont.getToolkit().getFontMetrics(f);
+  }
+
+  public Graphics getGraphics()
+  {
+    return null;
+  }
+}
Index: gnu/java/awt/peer/gtk/GtkPanelPeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java,v
retrieving revision 1.22
diff -u -r1.22 GtkPanelPeer.java
--- gnu/java/awt/peer/gtk/GtkPanelPeer.java	13 Feb 2006 14:32:53 -0000	1.22
+++ gnu/java/awt/peer/gtk/GtkPanelPeer.java	21 Feb 2006 15:11:38 -0000
@@ -41,7 +41,6 @@
 import java.awt.AWTEvent;
 import java.awt.Graphics;
 import java.awt.Panel;
-import java.awt.event.ComponentEvent;
 import java.awt.event.MouseEvent;
 import java.awt.event.PaintEvent;
 import java.awt.peer.PanelPeer;
Index: gnu/java/awt/peer/gtk/GtkToolkit.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java,v
retrieving revision 1.81
diff -u -r1.81 GtkToolkit.java
--- gnu/java/awt/peer/gtk/GtkToolkit.java	14 Feb 2006 22:49:18 -0000	1.81
+++ gnu/java/awt/peer/gtk/GtkToolkit.java	21 Feb 2006 15:11:38 -0000
@@ -44,6 +44,7 @@
 import gnu.java.awt.peer.ClasspathFontPeer;
 import gnu.java.awt.peer.ClasspathTextLayoutPeer;
 import gnu.java.awt.peer.EmbeddedWindowPeer;
+import gnu.java.awt.peer.GLightweightPeer;
 
 import java.awt.*;
 import java.awt.datatransfer.Clipboard;
@@ -51,10 +52,8 @@
 import java.awt.dnd.peer.DragSourceContextPeer;
 import java.awt.font.FontRenderContext;
 import java.awt.im.InputMethodHighlight;
-import java.awt.image.BufferedImage;
 import java.awt.image.ColorModel;
 import java.awt.image.DirectColorModel;
-import java.awt.image.ImageConsumer;
 import java.awt.image.ImageObserver;
 import java.awt.image.ImageProducer;
 import java.awt.peer.*;
@@ -62,9 +61,7 @@
 import java.net.URL;
 import java.text.AttributedString;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Properties;
@@ -610,6 +607,23 @@
   {
     GdkPixbufDecoder.registerSpis(reg);
   }
-
+  
+  /**
+   * Creates a peer object for the specified <code>Component</code>.  The
+   * peer returned by this method is not a native windowing system peer
+   * with its own native window.  Instead, this method allows the component
+   * to draw on its parent window as a "lightweight" widget.
+   *
+   * @param target The <code>Component</code> to create the peer for.
+   *
+   * @return The peer for the specified <code>Component</code> object.
+   */
+  protected LightweightPeer createComponent(Component target)
+  {
+    if (target instanceof Container)
+      return new GtkLightweightPeer((Container) target);
+    return new GLightweightPeer(target);
+  }
+  
   public static native void gtkMain();
 } // class GtkToolkit
Index: include/Makefile.am
===================================================================
RCS file: /sources/classpath/classpath/include/Makefile.am,v
retrieving revision 1.53
diff -u -r1.53 Makefile.am
--- include/Makefile.am	13 Feb 2006 16:12:53 -0000	1.53
+++ include/Makefile.am	21 Feb 2006 15:11:39 -0000
@@ -59,6 +59,7 @@
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkImage.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkLabelPeer.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkListPeer.h \
+$(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkLightweightPeer.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkMenuBarPeer.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkMenuComponentPeer.h \
 $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkMenuItemPeer.h \
Index: include/gnu_java_awt_peer_gtk_GtkLightweightPeer.h
===================================================================
RCS file: include/gnu_java_awt_peer_gtk_GtkLightweightPeer.h
diff -N include/gnu_java_awt_peer_gtk_GtkLightweightPeer.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ include/gnu_java_awt_peer_gtk_GtkLightweightPeer.h	21 Feb 2006 15:11:39 -0000
@@ -0,0 +1,20 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+
+#ifndef __gnu_java_awt_peer_gtk_GtkLightweightPeer__
+#define __gnu_java_awt_peer_gtk_GtkLightweightPeer__
+
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkLightweightPeer_create (JNIEnv *env, jobject);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkLightweightPeer_connectSignals (JNIEnv *env, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gnu_java_awt_peer_gtk_GtkLightweightPeer__ */
Index: java/awt/Toolkit.java
===================================================================
RCS file: /sources/classpath/classpath/java/awt/Toolkit.java,v
retrieving revision 1.31
diff -u -r1.31 Toolkit.java
--- java/awt/Toolkit.java	2 Aug 2005 15:29:25 -0000	1.31
+++ java/awt/Toolkit.java	21 Feb 2006 15:11:39 -0000
@@ -349,7 +349,16 @@
    */
   protected LightweightPeer createComponent(Component target)
   {
-    return new gnu.java.awt.peer.GLightweightPeer (target);
+    // This should be overridden by default Toolkit (eg. GtkToolkit).
+    // If target is an instance of Container, then a GtkLightweightPeer
+    // should be returned. Otherwise, an instance of GLightweightPeer is
+    // returned for Components. This is because, all the properties of a
+    // Container should be accessible (bounds, location etc).
+    // A lightweight Component should _just_ be drawn on its parent window,
+    // but we should be able to reshape a Container. Therefore, Component
+    // and Container lightweights should be treated differently.
+    
+    return null;
   }
 
   /**
Index: native/jni/gtk-peer/Makefile.am
===================================================================
RCS file: /sources/classpath/classpath/native/jni/gtk-peer/Makefile.am,v
retrieving revision 1.34
diff -u -r1.34 Makefile.am
--- native/jni/gtk-peer/Makefile.am	25 Jan 2006 10:40:12 -0000	1.34
+++ native/jni/gtk-peer/Makefile.am	21 Feb 2006 15:11:39 -0000
@@ -31,6 +31,7 @@
 			gnu_java_awt_peer_gtk_GtkImage.c \
 			gnu_java_awt_peer_gtk_GtkLabelPeer.c \
 			gnu_java_awt_peer_gtk_GtkListPeer.c \
+			gnu_java_awt_peer_gtk_GtkLightweightPeer.c \
 			gnu_java_awt_peer_gtk_GtkMenuBarPeer.c \
 			gnu_java_awt_peer_gtk_GtkMenuComponentPeer.c \
 			gnu_java_awt_peer_gtk_GtkMenuItemPeer.c \
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLightweightPeer.c
===================================================================
RCS file: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLightweightPeer.c
diff -N native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLightweightPeer.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLightweightPeer.c	21 Feb 2006 15:11:40 -0000
@@ -0,0 +1,110 @@
+/* GtkLightweightPeer.c -- Native implementation of GtkLightweightPeer
+   Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+#include "gtkpeer.h"
+#include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
+#include "gnu_java_awt_peer_gtk_GtkLightweightPeer.h"
+
+static gboolean panel_focus_in_cb (GtkWidget * widget,
+                                   GdkEventFocus *event,
+                                   jobject peer);
+static gboolean panel_focus_out_cb (GtkWidget * widget,
+                                    GdkEventFocus *event,
+                                    jobject peer);
+
+JNIEXPORT void JNICALL 
+Java_gnu_java_awt_peer_gtk_GtkLightweightPeer_create
+  (JNIEnv *env, jobject obj)
+{
+  GtkWidget *widget;
+
+  gdk_threads_enter ();
+
+  NSA_SET_GLOBAL_REF (env, obj);
+
+  widget = gtk_fixed_new ();
+
+  gtk_fixed_set_has_window (GTK_FIXED (widget), FALSE);
+
+  NSA_SET_PTR (env, obj, widget);
+
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkLightweightPeer_connectSignals
+  (JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  jobject *gref;
+
+  gdk_threads_enter ();
+
+  ptr = NSA_GET_PTR (env, obj);
+  gref = NSA_GET_GLOBAL_REF (env, obj);
+
+  /* Panel signals.  These callbacks prevent expose events being
+     delivered to the panel when it is focused. */
+  g_signal_connect (G_OBJECT (ptr), "focus-in-event",
+                    G_CALLBACK (panel_focus_in_cb), *gref);
+
+  g_signal_connect (G_OBJECT (ptr), "focus-out-event",
+                    G_CALLBACK (panel_focus_out_cb), *gref);
+
+  /* Component signals.  Exclude focus signals. */
+  cp_gtk_component_connect_expose_signals (ptr, gref);
+  cp_gtk_component_connect_mouse_signals (ptr, gref);
+
+  gdk_threads_leave ();
+}
+
+static gboolean
+panel_focus_in_cb (GtkWidget * widget  __attribute__((unused)),
+		    GdkEventFocus *event  __attribute__((unused)),
+		    jobject peer __attribute__((unused)))
+{
+  return TRUE;
+}
+
+static gboolean
+panel_focus_out_cb (GtkWidget * widget __attribute__((unused)),
+		     GdkEventFocus *event __attribute__((unused)),
+		     jobject peer __attribute__((unused)))
+{
+  return TRUE;
+}

Reply via email to