From e27d6202c07dbc70172733fcf6e79cb2ffe9a56c Mon Sep 17 00:00:00 2001
From: Scott Gilbertson <scottg@mantatest.com>
Date: Fri, 15 Jul 2005 16:07:18 +0000
Subject: [PATCH] XCanvasPeer.java (attributes): New field.

2005-07-15  Scott Gilbertson  <scottg@mantatest.com>

	* gnu/awt/xlib/XCanvasPeer.java (attributes): New field.
	(eventMask): New field.
	(XCanvasPeer(Component)): Use attributes field.
	(setBackground): Implemented.
	(setEventMask): Process mask only if changed.
	* gnu/awt/xlib/XEventLoop.java (class): Iplement Runnable.
	(eventLoopThread): New field.
	(XEventLoop(Display,EventQueue)): Start eventLoopThread.
	(interrupt): Removed.
	(run): New method.
	* gnu/awt/xlib/XEventQueue.java (getNextEvent): Process Container
	and Component events.
	* gnu/awt/xlib/XFramePeer.java (processingConfigureNotify): New
	field.
	(configureNotify): Set and clear processingConfigureNotify.
	(setBounds): Process only if processingConfigureNotify is false.
	(toBack): Implemented.
	(toFront): Implemented.
	* gnu/awt/xlib/XGraphics.java (setColor): Ignore null color.
	* gnu/awt/xlib/XGraphicsConfiguration.java (getPixel): Ignore null
	color.
	* gnu/awt/xlib/XToolkit.java (nativeQueueEmpty): Always return true.
	(wakeNativeQueue): Do nothing.
	(iterateNativeQueue): Do queue.wait if blocking.
	* gnu/gcj/xlib/Font.java (loadFont): New method.
	(loadFontImpl): Renamed native method, was loadFont.
	* gnu/gcj/xlib/Window.java (toFront): New method.
	(toBack): New method.
	* gnu/gcj/xlib/natFont.cc (loadFontImpl): Renamed method, was
	loadFont.
	* gnu/gcj/xlib/natWindow.cc (toBack): New method.
	(toFront): New method.
	* gnu/gcj/xlib/natXAnyEvent.cc (loadNext): Removed timeout.

From-SVN: r102057
---
 libjava/ChangeLog                             | 36 +++++++++
 libjava/gnu/awt/xlib/XCanvasPeer.java         | 46 ++++++++----
 libjava/gnu/awt/xlib/XEventLoop.java          | 17 +++--
 libjava/gnu/awt/xlib/XEventQueue.java         | 73 ++++++++++++++++++-
 libjava/gnu/awt/xlib/XFramePeer.java          | 33 ++++-----
 libjava/gnu/awt/xlib/XGraphics.java           |  3 +-
 .../gnu/awt/xlib/XGraphicsConfiguration.java  | 21 +++---
 libjava/gnu/awt/xlib/XToolkit.java            | 25 +++++--
 libjava/gnu/gcj/xlib/Font.java                | 16 +++-
 libjava/gnu/gcj/xlib/Window.java              |  2 +
 libjava/gnu/gcj/xlib/natFont.cc               |  2 +-
 libjava/gnu/gcj/xlib/natWindow.cc             | 14 ++++
 libjava/gnu/gcj/xlib/natXAnyEvent.cc          |  5 +-
 13 files changed, 229 insertions(+), 64 deletions(-)

diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 3f224052321b..4fae8576c865 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,39 @@
+2005-07-15  Scott Gilbertson  <scottg@mantatest.com>
+
+	* gnu/awt/xlib/XCanvasPeer.java (attributes): New field.
+	(eventMask): New field.
+	(XCanvasPeer(Component)): Use attributes field.
+	(setBackground): Implemented.
+	(setEventMask): Process mask only if changed.
+	* gnu/awt/xlib/XEventLoop.java (class): Iplement Runnable.
+	(eventLoopThread): New field.
+	(XEventLoop(Display,EventQueue)): Start eventLoopThread.
+	(interrupt): Removed.
+	(run): New method.
+	* gnu/awt/xlib/XEventQueue.java (getNextEvent): Process Container
+	and Component events.
+	* gnu/awt/xlib/XFramePeer.java (processingConfigureNotify): New
+	field.
+	(configureNotify): Set and clear processingConfigureNotify.
+	(setBounds): Process only if processingConfigureNotify is false.
+	(toBack): Implemented.
+	(toFront): Implemented.
+	* gnu/awt/xlib/XGraphics.java (setColor): Ignore null color.
+	* gnu/awt/xlib/XGraphicsConfiguration.java (getPixel): Ignore null
+	color.
+	* gnu/awt/xlib/XToolkit.java (nativeQueueEmpty): Always return true.
+	(wakeNativeQueue): Do nothing.
+	(iterateNativeQueue): Do queue.wait if blocking.
+	* gnu/gcj/xlib/Font.java (loadFont): New method.
+	(loadFontImpl): Renamed native method, was loadFont. 
+	* gnu/gcj/xlib/Window.java (toFront): New method.
+	(toBack): New method.
+	* gnu/gcj/xlib/natFont.cc (loadFontImpl): Renamed method, was 
+	loadFont.
+	* gnu/gcj/xlib/natWindow.cc (toBack): New method.
+	(toFront): New method. 
+	* gnu/gcj/xlib/natXAnyEvent.cc (loadNext): Removed timeout.
+
 2005-07-14  Andrew Haley  <aph@redhat.com>
 
         * gnu/java/net/protocol/file/Connection.java (unquote): New
diff --git a/libjava/gnu/awt/xlib/XCanvasPeer.java b/libjava/gnu/awt/xlib/XCanvasPeer.java
index 83646b1f3385..39a3f9331f4e 100644
--- a/libjava/gnu/awt/xlib/XCanvasPeer.java
+++ b/libjava/gnu/awt/xlib/XCanvasPeer.java
@@ -55,6 +55,8 @@ public class XCanvasPeer implements CanvasPeer
 
   Component component;
   XGraphicsConfiguration config;
+  private WindowAttributes attributes = new WindowAttributes();
+  private long eventMask;
   
   public XCanvasPeer(Component component)
   {
@@ -92,7 +94,6 @@ public class XCanvasPeer implements CanvasPeer
        object. */
     component.setBounds(bounds);
 	    
-    WindowAttributes attributes = new WindowAttributes();
 
     /* Set background color */
     Color bg = component.getBackground();
@@ -349,8 +350,21 @@ public class XCanvasPeer implements CanvasPeer
 
   public void setBackground(Color color)
   {
-    /* default canvas peer does not keep track of background, since it won't
-     * paint anything. */
+    if (color != null)
+    {
+      int[] components =
+      {
+        color.getRed (),
+        color.getGreen (),
+        color.getBlue (),
+        0xff
+      };
+      
+      ColorModel cm = config.getColorModel ();
+      long pixel = cm.getDataElement (components, 0);
+      attributes.setBackground (pixel);
+      window.setAttributes (attributes);
+    }
   }
 
   public void setBounds(int x, int y, int width, int height)
@@ -388,20 +402,22 @@ public class XCanvasPeer implements CanvasPeer
 
   public void setEventMask(long eventMask)
   {
-    WindowAttributes attributes = new WindowAttributes();
-
-    long xEventMask = getBasicEventMask();
-	
-    if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0)
+    if (this.eventMask != eventMask)
+    {
+      this.eventMask = eventMask;
+      long xEventMask = getBasicEventMask ();
+      
+      if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0)
       {
-	xEventMask |=
-	  WindowAttributes.MASK_BUTTON_PRESS |
-	  WindowAttributes.MASK_BUTTON_RELEASE;
+        xEventMask |=
+          WindowAttributes.MASK_BUTTON_PRESS |
+          WindowAttributes.MASK_BUTTON_RELEASE;
       }
-	    
-    attributes.setEventMask(xEventMask);
-    window.setAttributes(attributes);
-    ensureFlush();
+      
+      attributes.setEventMask (xEventMask);
+      window.setAttributes (attributes);
+      ensureFlush ();
+    }
   }
 
   public void setFont(Font font)
diff --git a/libjava/gnu/awt/xlib/XEventLoop.java b/libjava/gnu/awt/xlib/XEventLoop.java
index 149ee736d7c1..d0c46a804d56 100644
--- a/libjava/gnu/awt/xlib/XEventLoop.java
+++ b/libjava/gnu/awt/xlib/XEventLoop.java
@@ -21,12 +21,13 @@ import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
 import java.util.Vector;
 
-public class XEventLoop
+public class XEventLoop implements Runnable
 {
   Display display;
   EventQueue queue;
   XAnyEvent anyEvent;
-
+  private Thread eventLoopThread;
+  
   LightweightRedirector lightweightRedirector = new LightweightRedirector();
     
   public XEventLoop(Display display, EventQueue queue)
@@ -35,13 +36,17 @@ public class XEventLoop
     this.queue = queue;
     
     anyEvent = new XAnyEvent(display);
+    eventLoopThread = new Thread(this, "AWT thread for XEventLoop");
+    eventLoopThread.start();
   }
 
-  void interrupt()
+  public void run ()
   {
-    anyEvent.interrupt();
+    // FIXME: do we need an interrupt mechanism for window shutdown?
+    while (true)
+      postNextEvent (true);
   }
-
+  
   /** If there's an event available, post it.
    * @return true if an event was posted
    */
@@ -65,7 +70,7 @@ public class XEventLoop
     AWTEvent event = null;
     if (loadNextEvent(block))
       {
-        event = createEvent();        
+        event = createEvent(); 
         event = lightweightRedirector.redirect(event);
       }
     return event;
diff --git a/libjava/gnu/awt/xlib/XEventQueue.java b/libjava/gnu/awt/xlib/XEventQueue.java
index ea2ad1860605..b068daf1b52f 100644
--- a/libjava/gnu/awt/xlib/XEventQueue.java
+++ b/libjava/gnu/awt/xlib/XEventQueue.java
@@ -8,12 +8,16 @@ details.  */
 
 package gnu.awt.xlib;
 
-import java.awt.*;
-
 import gnu.gcj.xlib.Display;
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.EventQueue;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ContainerEvent;
 
 /**
- * The only difference here from a standard EventQueue is that the X
+ * The main difference here from a standard EventQueue is that the X
  * display connection is flushed before waiting for more events.
  */
 public class XEventQueue extends EventQueue
@@ -29,6 +33,67 @@ public class XEventQueue extends EventQueue
   {
     if ((peekEvent() == null) && (display != null))
       display.flush();
-    return super.getNextEvent();
+    AWTEvent event = super.getNextEvent();
+    if (event != null)
+    {
+      switch (event.getID ())
+      {
+        case ContainerEvent.COMPONENT_ADDED:
+        {
+          /* If a component has been added to a container, it needs to be
+           * invalidated, to ensure that it ultimately gets an addNotify.
+           * If it's not invalidated, the component will never display in 
+           * an already-showing container (probably applies only to CardLayout).
+           * Perhaps this code should be in java.awt, but the problem only seems 
+           * to happen with xlib peers (not with gtk peers) so it's here instead.
+           */
+          ContainerEvent ce = (ContainerEvent)event;
+          ce.getChild ().invalidate ();
+          ce.getContainer ().validate ();
+        }
+        break;
+
+        case ComponentEvent.COMPONENT_RESIZED:
+        {
+          ComponentEvent ce = (ComponentEvent)event;
+          // FIXME: there may be opportunities to coalesce resize events
+          ce.getComponent ().validate ();
+        }
+        break;
+
+        case ComponentEvent.COMPONENT_SHOWN:
+        {
+          ComponentEvent ce = (ComponentEvent)event;
+          Component comp = ce.getComponent ();
+          if (!comp.isValid ())
+          {
+            /* Try to validate, going up the tree to the highest-level invalid
+             * Container.  The idea is to ensure that addNotify gets called for
+             * any non-top-level component being shown, to make it create a peer.
+             */
+            Container parent = comp.getParent ();
+            while (parent != null)
+            {
+              Container next = parent.getParent ();
+              if (next == null || next.isValid ())
+              {
+                parent.validate ();
+                break;
+              }
+              else
+                parent = next;
+            }
+            if (comp instanceof Container)
+              comp.validate ();
+          }
+          comp.repaint ();
+        }
+        break;
+        
+        default:
+          break;
+      }
+    }
+    return event;
   }
 }
diff --git a/libjava/gnu/awt/xlib/XFramePeer.java b/libjava/gnu/awt/xlib/XFramePeer.java
index f3c655ecf80f..79f1e88cf282 100644
--- a/libjava/gnu/awt/xlib/XFramePeer.java
+++ b/libjava/gnu/awt/xlib/XFramePeer.java
@@ -22,7 +22,8 @@ import gnu.gcj.xlib.XConfigureEvent;
 
 public class XFramePeer extends XCanvasPeer implements FramePeer
 {
-
+  private boolean processingConfigureNotify = false;
+  
   public XFramePeer(Frame frame)
   {
     super(frame);
@@ -62,28 +63,24 @@ public class XFramePeer extends XCanvasPeer implements FramePeer
 
   void configureNotify(XConfigureEvent configEvent)
   {
+    processingConfigureNotify = true; // to avoid setBounds flood
     component.setBounds(configEvent.getBounds());
-    
-    /* FIXME: Validation should probably not be done here.  The best
-       strategy is probably to validate on the AWT thread in response
-       to an ComponentEvent.  This will make it possible to coalesce
-       resize validations. */
-    component.validate();
+    processingConfigureNotify = false;
   }
 
   /* Overridden to ignore request to set bounds if the request occurs
-     on the X event loop thread.  It is assumed that all requests that
-     occur on the X event loop thread are results of XConfigureNotify
-     events, in which case the X window already has the desired
-     bounds.  */
+     while processing an XConfigureNotify event, in which case the X
+     window already has the desired bounds.
+     That's what java.awt.Window.setBoundsCallback is for, but it's
+     package-private, and using our own flag eliminates the need to
+     circumvent java security.
+  */
   public void setBounds(int x, int y, int width, int height)
   {
-    if (EventQueue.isDispatchThread())
-      return;
-    
-    super.setBounds(x, y, width, height);
+    if (!processingConfigureNotify)
+      super.setBounds(x, y, width, height);
   }
- 
+  
   // Implementing ContainerPeer:
 
   static final Insets INSETS_0_PROTOTYPE = new Insets(0, 0, 0, 0);
@@ -114,12 +111,12 @@ public class XFramePeer extends XCanvasPeer implements FramePeer
 
   public void toBack()
   {
-    throw new UnsupportedOperationException("not implemented yet");	
+    window.toBack ();	
   }
   
   public void toFront()
   {
-    throw new UnsupportedOperationException("not implemented yet");	
+    window.toFront ();
   }
 
 
diff --git a/libjava/gnu/awt/xlib/XGraphics.java b/libjava/gnu/awt/xlib/XGraphics.java
index 60abc87b5408..215c04dc197b 100644
--- a/libjava/gnu/awt/xlib/XGraphics.java
+++ b/libjava/gnu/awt/xlib/XGraphics.java
@@ -83,7 +83,8 @@ public class XGraphics implements Cloneable, DirectRasterGraphics
   
   public void setColor(Color color)
   {
-    context.setForeground(config.getPixel(color));
+    if (color != null)
+      context.setForeground(config.getPixel(color));
   }
 
   public void setPaintMode()
diff --git a/libjava/gnu/awt/xlib/XGraphicsConfiguration.java b/libjava/gnu/awt/xlib/XGraphicsConfiguration.java
index bdbf3e18a74d..d1202b837912 100644
--- a/libjava/gnu/awt/xlib/XGraphicsConfiguration.java
+++ b/libjava/gnu/awt/xlib/XGraphicsConfiguration.java
@@ -522,17 +522,20 @@ public class XGraphicsConfiguration extends GraphicsConfiguration
     };
      */
     
-    float[] normalizedComponents =
-    {
-      ((float)color.getRed ()) / 255F,
-      ((float)color.getGreen ()) / 255F,
-      ((float)color.getBlue ()) / 255F,
-      1
-    };
     int[] unnormalizedComponents = { 0, 0, 0, 0xff };
     ColorModel cm = getColorModel ();
-    cm.getUnnormalizedComponents(normalizedComponents, 0,
-				 unnormalizedComponents, 0);
+    if (color != null)
+    {
+      float[] normalizedComponents =
+      {
+        ((float)color.getRed ()) / 255F,
+        ((float)color.getGreen ()) / 255F,
+        ((float)color.getBlue ()) / 255F,
+        1
+      };
+      cm.getUnnormalizedComponents(normalizedComponents, 0,
+           unnormalizedComponents, 0);
+    }
     return cm.getDataElement (unnormalizedComponents, 0);
   }
 }
diff --git a/libjava/gnu/awt/xlib/XToolkit.java b/libjava/gnu/awt/xlib/XToolkit.java
index c6e140eb3e16..87acec3e3496 100644
--- a/libjava/gnu/awt/xlib/XToolkit.java
+++ b/libjava/gnu/awt/xlib/XToolkit.java
@@ -445,13 +445,16 @@ public class XToolkit extends ClasspathToolkit
   }
 
   public boolean nativeQueueEmpty() 
-  { 
-    return eventLoop.isIdle(); 
+  {
+    // Tell EventQueue the native queue is empty, because XEventLoop
+    // separately ensures that native events are posted to AWT.
+    return true;
   }
 
   public void wakeNativeQueue() 
   {
-    eventLoop.interrupt();
+    // Not implemented, because the native queue is always awake.
+    // (i.e. it's polled in a thread separate from the AWT dispatch thread)
   }
 
   /** Checks the native event queue for events.  If blocking, waits until an
@@ -464,6 +467,18 @@ public class XToolkit extends ClasspathToolkit
    */
   public void iterateNativeQueue(java.awt.EventQueue locked, boolean block) 
   {
-    eventLoop.postNextEvent(block);
-  }
+    // There is nothing to do here except block, because XEventLoop 
+    // iterates the queue in a dedicated thread.
+    if (block)
+    {
+      try
+      {
+        queue.wait ();
+      }
+      catch (InterruptedException ie)
+      {
+        // InterruptedException intentionally ignored
+      }
+    }
+  }; 
 }
diff --git a/libjava/gnu/gcj/xlib/Font.java b/libjava/gnu/gcj/xlib/Font.java
index cd2fff9630d8..74985b9388e0 100644
--- a/libjava/gnu/gcj/xlib/Font.java
+++ b/libjava/gnu/gcj/xlib/Font.java
@@ -34,7 +34,21 @@ public final class Font extends XID
     structure = struct;
   }
 
-  static native RawData loadFont(Display display, String lfdNamePattern);
+  static RawData loadFont(Display display, String lfdNamePattern)
+  {
+    RawData returnValue = null;
+    try
+    {
+      returnValue = loadFontImpl (display,lfdNamePattern);
+    }
+    catch (XException e)
+    {
+      // Throw a descriptive exception, including the font pattern
+      throw new XException ("Font not found: " + lfdNamePattern);
+    }
+    return returnValue;
+  }
+  static native RawData loadFontImpl(Display display, String lfdNamePattern);
 
   static native int getXIDFromStruct(RawData structure);
 
diff --git a/libjava/gnu/gcj/xlib/Window.java b/libjava/gnu/gcj/xlib/Window.java
index ae3dbfd688bc..3ff3657c45c9 100644
--- a/libjava/gnu/gcj/xlib/Window.java
+++ b/libjava/gnu/gcj/xlib/Window.java
@@ -73,6 +73,8 @@ public class Window extends Drawable
 
   public native void map();
   public native void unmap();
+  public native void toFront();
+  public native void toBack();
   
   protected boolean owned = false;
 
diff --git a/libjava/gnu/gcj/xlib/natFont.cc b/libjava/gnu/gcj/xlib/natFont.cc
index 54ac655d17b3..cd5d87c7ab69 100644
--- a/libjava/gnu/gcj/xlib/natFont.cc
+++ b/libjava/gnu/gcj/xlib/natFont.cc
@@ -16,7 +16,7 @@ details.  */
 #include <gnu/gcj/xlib/Font.h>
 #include <gnu/gcj/xlib/XException.h>
 
-gnu::gcj::RawData* gnu::gcj::xlib::Font::loadFont(Display* display,
+gnu::gcj::RawData* gnu::gcj::xlib::Font::loadFontImpl(Display* display,
 						  jstring lfdNamePattern)
 {
   ::Display* dpy = (::Display*) display->display;
diff --git a/libjava/gnu/gcj/xlib/natWindow.cc b/libjava/gnu/gcj/xlib/natWindow.cc
index 6600795574f5..62cd086ccb49 100644
--- a/libjava/gnu/gcj/xlib/natWindow.cc
+++ b/libjava/gnu/gcj/xlib/natWindow.cc
@@ -77,6 +77,20 @@ void gnu::gcj::xlib::Window::setAttributes(WindowAttributes* attributes)
   // no fast fail
 }
 
+void gnu::gcj::xlib::Window::toBack()
+{
+  ::Display* dpy = (::Display*) (display->display);
+  ::Window window = xid;
+  XLowerWindow(dpy, window);
+}
+
+void gnu::gcj::xlib::Window::toFront()
+{
+  ::Display* dpy = (::Display*) (display->display);
+  ::Window window = xid;
+  XRaiseWindow(dpy, window);
+}
+
 void gnu::gcj::xlib::Window::map()
 {
   ::Display* dpy = (::Display*) (display->display);
diff --git a/libjava/gnu/gcj/xlib/natXAnyEvent.cc b/libjava/gnu/gcj/xlib/natXAnyEvent.cc
index 26d3b604b04f..0bef563ed2d9 100644
--- a/libjava/gnu/gcj/xlib/natXAnyEvent.cc
+++ b/libjava/gnu/gcj/xlib/natXAnyEvent.cc
@@ -69,14 +69,11 @@ jboolean gnu::gcj::xlib::XAnyEvent::loadNext(jboolean block)
   int xfd = XConnectionNumber(dpy);
   int pipefd = pipe[0];
   int n = (xfd > pipefd ? xfd : pipefd) + 1;
-  struct timeval timeout;
-  timeout.tv_usec = 100000;  // 100ms timeout
-  timeout.tv_sec = 0;
   fd_set rfds;
   FD_ZERO(&rfds);
   FD_SET(xfd, &rfds);
   FD_SET(pipefd, &rfds);  
-  int sel = _Jv_select (n, &rfds, NULL, NULL, &timeout);
+  int sel = _Jv_select (n, &rfds, NULL, NULL, NULL);
   if (sel > 0)
     {
       if (FD_ISSET(xfd, &rfds))
-- 
GitLab