This fixes Component and related classes to come more close to the new (JDK1.4) style AWT focus system. The Component.requestFocusXXX() methods all use requestFocusImpl() now, which finally ends in ComponentPeer.requestFocus(Component,boolean,boolean,long). The old ComponentPeer.requestFocus() method isn't used anymore. This allows for more flexibility for the peers to handle focus requests. I implemented this for GtkComponentPeer and GtkWindowPeer to work correctly and documented this method in ComponentPeer. The actual meaning of the arguments have been determined by experimenting with the JDK and some kind of dummy toolkit that just does enough to let the requestFocus() calls through...

2006-07-25  Roman Kennke  <[EMAIL PROTECTED]>

        * java/awt/Component.java
        (requestFocus()): Reimplemented to use requestFocusImpl().
        (requestFocus(boolean)): Reimplemented to use requestFocusImpl().
        (requestFocusInWindow()): Reimplemented to use requestFocusImpl().
        (requestFocusInWindow(boolean)): Reimplemented to use
        requestFocusImpl().
        (requestFocusImpl): Reimplemented focus request to use
        new peer method. Also added some obvious additional checks
        for rejecting focus requests early.
        * java/awt/ComponentPeer.java
        (requestFocus(Component,boolean,boolean,long)): Documented
        this method.
        * gnu/java/awt/peer/gtk/GtkComponentPeer.java
        (requestFocus): New field.
        (gtkWidgetHasFocus): New native method.
        (gtkWidgetCanFocus): New native method.
        (requestFocus): Replaced with assert false to prevent
        usage of obsolete method.
        (postFocusEvent(int,boolean,Component)): New overloaded method
        for posting the focus event to a specific target.
        (postFocusEvent(int,boolean)): Post event to requestFocus
        component.
        (requestFocus(Component,boolean,boolean,long)): Implemented.
        (getWindowFor): New helper method.
        (isLightweightDescendant): New helper method.
        * gnu/java/awt/peer/gtk/GtkWindowPeer.java
        (gtkWindowHasFocus): New native method.
        (requestFocus(Component,boolean,boolean,long)): New method.
        Overrides GtkComponentPeer method to specially handly the
        case when a Window receives a focus request for a lightweight
        child.
        * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
        (gtkWidgetHasFocus): New native method.
        (gtkWidgetCanFocus): New native method.
        * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
        (gtkWindowHasFocus): New native method.
        * include/gnu_java_awt_peer_gtk_GtkComponentPeer.h,
        * include/gnu_java_awt_peer_gtk_GtkWindowPeer.h:
        Regenerated.


/Roman
Index: java/awt/Component.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Component.java,v
retrieving revision 1.136
diff -u -1 -2 -r1.136 Component.java
--- java/awt/Component.java	17 Jul 2006 18:37:19 -0000	1.136
+++ java/awt/Component.java	25 Jul 2006 22:40:42 -0000
@@ -4198,74 +4198,25 @@
    * The behaviour of this method is platform-dependent.
    * [EMAIL PROTECTED] #requestFocusInWindow()} should be used instead.
    *
    * @see #requestFocusInWindow ()
    * @see FocusEvent
    * @see #addFocusListener (FocusListener)
    * @see #isFocusable ()
    * @see #isDisplayable ()
    * @see KeyboardFocusManager#clearGlobalFocusOwner ()
    */
   public void requestFocus ()
   {
-    if (isDisplayable ()
-	&& isShowing ()
-	&& isFocusable ())
-      {
-        synchronized (getTreeLock ())
-          {
-            // Find this Component's top-level ancestor.            
-            Container parent = (this instanceof Container) ? (Container) this
-                                                          : getParent();            
-            while (parent != null
-                   && !(parent instanceof Window))
-              parent = parent.getParent ();
-
-            if (parent == null)
-              return;
-            
-            Window toplevel = (Window) parent;
-            if (toplevel.isFocusableWindow ())
-              {
-                if (peer != null && !isLightweight())
-                  // This call will cause a FOCUS_GAINED event to be
-                  // posted to the system event queue if the native
-                  // windowing system grants the focus request.
-                  peer.requestFocus ();
-                else
-                  {
-                    // Either our peer hasn't been created yet or we're a
-                    // lightweight component.  In either case we want to
-                    // post a FOCUS_GAINED event.
-                    EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
-                    synchronized (eq)
-                      {
-                        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
-                        Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
-                        if (currentFocusOwner != null)
-                          {
-                            eq.postEvent (new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
-                                                         false, this));
-                            eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, false,
-                                                         currentFocusOwner));
-                          }
-                        else
-                          eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, false));
-                      }
-                  }
-              }
-            else
-              pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED);
-          }
-      }
+    requestFocusImpl(false, true);
   }
 
   /**
    * Request that this Component be given the keyboard input focus and
    * that its top-level ancestor become the focused Window.
    *
    * For the request to be granted, the Component must be focusable,
    * displayable and showing and the top-level Window to which it
    * belongs must be focusable.  If the request is initially denied on
    * the basis that the top-level Window is not focusable, the request
    * will be remembered and granted when the Window does become
    * focused.
@@ -4287,79 +4238,25 @@
    * @param temporary true if the focus request is temporary
    * @return true if the request has a chance of success
    * @see #requestFocusInWindow ()
    * @see FocusEvent
    * @see #addFocusListener (FocusListener)
    * @see #isFocusable ()
    * @see #isDisplayable ()
    * @see KeyboardFocusManager#clearGlobalFocusOwner ()
    * @since 1.4
    */
   protected boolean requestFocus (boolean temporary)
   {
-    if (isDisplayable ()
-	&& isShowing ()
-	&& isFocusable ())
-      {
-        synchronized (getTreeLock ())
-          {
-            // Find this Component's top-level ancestor.
-            Container parent = getParent ();
-
-            while (parent != null
-                   && !(parent instanceof Window))
-              parent = parent.getParent ();
-
-            Window toplevel = (Window) parent;
-            if (toplevel.isFocusableWindow ())
-              {
-                if (peer != null && !isLightweight())
-                  // This call will cause a FOCUS_GAINED event to be
-                  // posted to the system event queue if the native
-                  // windowing system grants the focus request.
-                  peer.requestFocus ();
-                else
-                  {
-                    // Either our peer hasn't been created yet or we're a
-                    // lightweight component.  In either case we want to
-                    // post a FOCUS_GAINED event.
-                    EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
-                    synchronized (eq)
-                      {
-                        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
-                        Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
-                        if (currentFocusOwner != null)
-                          {
-                            eq.postEvent (new FocusEvent(currentFocusOwner,
-                                                         FocusEvent.FOCUS_LOST,
-                                                         temporary, this));
-                            eq.postEvent (new FocusEvent(this,
-                                                         FocusEvent.FOCUS_GAINED,
-                                                         temporary,
-                                                         currentFocusOwner));
-                          }
-                        else
-                          eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
-                      }
-                  }
-              }
-            else
-              // FIXME: need to add a focus listener to our top-level
-              // ancestor, so that we can post this event when it becomes
-              // the focused window.
-              pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary);
-          }
-      }
-    // Always return true.
-    return true;
+    return requestFocusImpl(temporary, true);
   }
 
   /**
    * Request that this component be given the keyboard input focus, if
    * its top-level ancestor is the currently focused Window.  A
    * <code>FOCUS_GAINED</code> event will be fired if and only if this
    * request is successful. To be successful, the component must be
    * displayable, showing, and focusable, and its ancestor top-level
    * Window must be focused.
    *
    * If the return value is false, the request is guaranteed to fail.
    * If the return value is true, the request will succeed unless it
@@ -4369,25 +4266,25 @@
    *
    * @return true if the request has a chance of success
    * @see #requestFocus ()
    * @see FocusEvent
    * @see #addFocusListener (FocusListener)
    * @see #isFocusable ()
    * @see #isDisplayable ()
    * @see KeyboardFocusManager#clearGlobalFocusOwner ()
    * @since 1.4
    */
   public boolean requestFocusInWindow ()
   {
-    return requestFocusInWindow (false);
+    return requestFocusImpl(false, false);
   }
 
   /**
    * Request that this component be given the keyboard input focus, if
    * its top-level ancestor is the currently focused Window.  A
    * <code>FOCUS_GAINED</code> event will be fired if and only if this
    * request is successful. To be successful, the component must be
    * displayable, showing, and focusable, and its ancestor top-level
    * Window must be focused.
    *
    * If the return value is false, the request is guaranteed to fail.
    * If the return value is true, the request will succeed unless it
@@ -4400,83 +4297,94 @@
    * @param temporary true if the focus request is temporary
    * @return true if the request has a chance of success
    * @see #requestFocus ()
    * @see FocusEvent
    * @see #addFocusListener (FocusListener)
    * @see #isFocusable ()
    * @see #isDisplayable ()
    * @see KeyboardFocusManager#clearGlobalFocusOwner ()
    * @since 1.4
    */
   protected boolean requestFocusInWindow (boolean temporary)
   {
-    KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
-
-    Window focusedWindow = manager.getFocusedWindow ();
+    return requestFocusImpl(temporary, false);
+  }
 
-    if (isDisplayable ()
-	&& isShowing ()
-	&& isFocusable ())
+  /**
+   * Helper method for all 4 requestFocus variants.
+   *
+   * @param temporary indicates if the focus change is temporary
+   * @param focusWindow indicates if the window focus may be changed
+   *
+   * @return <code>false</code> if the request has been definitely denied,
+   *         <code>true</code> otherwise
+   */
+  private boolean requestFocusImpl(boolean temporary, boolean focusWindow)
+  {
+    boolean retval = false;
+ 
+    // Don't try to focus non-focusable and non-visible components.
+    if (isFocusable() && isVisible())
       {
-        if (focusedWindow != null)
+        ComponentPeer myPeer = peer;
+        if (peer != null)
           {
-            synchronized (getTreeLock ())
+            // Find Window ancestor and find out if we're showing while
+            // doing this.
+            boolean showing = true;
+            Component window = this;
+            while (! (window instanceof Window))
               {
-                Container parent = getParent ();
-
-                while (parent != null
-                       && !(parent instanceof Window))
-                  parent = parent.getParent ();
-
-                Window toplevel = (Window) parent;
-
-                // Check if top-level ancestor is currently focused window.
-                if (focusedWindow == toplevel)
+                if (! window.isVisible())
+                  showing = false;
+                window = window.parent;
+              }
+            // Don't allow focus when there is no window or the window
+            // is not focusable.
+            if (window != null && ((Window) window).isFocusableWindow()
+                && showing)
+              {
+                // Search for nearest heavy ancestor (including this
+                // component).
+                Component heavyweightParent = this;
+                while (heavyweightParent.peer instanceof LightweightPeer)
+                  heavyweightParent = heavyweightParent.parent;
+
+                // Don't allow focus on lightweight components without
+                // visible heavyweight ancestor
+                if (heavyweightParent != null && heavyweightParent.isVisible())
                   {
-                    if (peer != null
-                        && !isLightweight()
-                        && !(this instanceof Window))
-                      // This call will cause a FOCUS_GAINED event to be
-                      // posted to the system event queue if the native
-                      // windowing system grants the focus request.
-                      peer.requestFocus ();
-                    else
+                    // Don't allow focus when heavyweightParent has no peer.
+                    myPeer = heavyweightParent.peer;
+                    if (myPeer != null)
                       {
-                        // Either our peer hasn't been created yet or we're a
-                        // lightweight component.  In either case we want to
-                        // post a FOCUS_GAINED event.
-                        EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
-                        synchronized (eq)
+                        // Try to focus the component.
+                        long time = EventQueue.getMostRecentEventTime();
+                        boolean success = myPeer.requestFocus(this, temporary,
+                                                              focusWindow,
+                                                              time);
+                        if (! success)
                           {
-                            Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
-                            if (currentFocusOwner != null)
-                              {
-                                eq.postEvent (new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
-                                                             temporary, this));
-                                eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary,
-                                                             currentFocusOwner));
-                              }
-                            else
-                              eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
+                            // Dequeue key events if focus request failed.
+                            KeyboardFocusManager kfm =
+                              KeyboardFocusManager.getCurrentKeyboardFocusManager();
+                            kfm.dequeueKeyEvents(time, this);
                           }
+                        retval = success;
                       }
                   }
-                else
-                  return false;
               }
           }
-
-        return true;
       }
-    return false;
+    return retval;
   }
 
   /**
    * Transfers focus to the next component in the focus traversal
    * order, as though this were the current focus owner.
    *
    * @see #requestFocus()
    * @since 1.1
    */
   public void transferFocus ()
   {
     nextFocus ();
Index: java/awt/peer/ComponentPeer.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/peer/ComponentPeer.java,v
retrieving revision 1.16
diff -u -1 -2 -r1.16 ComponentPeer.java
--- java/awt/peer/ComponentPeer.java	13 Jan 2006 22:23:17 -0000	1.16
+++ java/awt/peer/ComponentPeer.java	25 Jul 2006 22:40:42 -0000
@@ -253,30 +253,39 @@
    * Requests that this component receives the focus. This is called from
    * [EMAIL PROTECTED] Component#requestFocus()}.
    * 
    * @specnote Part of the earlier 1.1 API, apparently replaced by argument 
    *           form of the same method.
    */
   void requestFocus();
 
   /**
    * Requests that this component receives the focus. This is called from
    * [EMAIL PROTECTED] Component#requestFocus()}.
    *
-   * @param source TODO
-   * @param bool1 TODO
-   * @param bool2 TODO
-   * @param x TODO
+   * This method is only called for heavyweight component's peers. Lightweight
+   * components ask their nearest heavyweight component to request focus.
+   * It's up to the heavyweight peer to decide if any of it's lightweight
+   * descendants are allowed to receive keyboard input focus or not. If the
+   * focus request is finally approved, then the peer must post a FOCUS_GAINED
+   * event for the requested component.
+   *
+   * @param request the component for which the focus is requested
+   * @param temporary indicates if the focus change is temporary (true) or
+   *        permanent (false)
+   * @param allowWindowFocus indicates if it's allowed to change window focus
+   * @param time the timestamp
    */
-  boolean requestFocus(Component source, boolean bool1, boolean bool2, long x);
+  boolean requestFocus(Component request, boolean temporary,
+                       boolean allowWindowFocus, long time);
 
   /**
    * Notifies the peer that the bounds of this component have changed. This
    * is called by [EMAIL PROTECTED] Component#reshape(int, int, int, int)}.
    *
    * @param x the X coordinate of the upper left corner of the component
    * @param y the Y coordinate of the upper left corner of the component
    * @param width the width of the component
    * @param height the height of the component
    */
   void reshape(int x, int y, int width, int height);
 
Index: gnu/java/awt/peer/gtk/GtkComponentPeer.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java,v
retrieving revision 1.117
diff -u -1 -2 -r1.117 GtkComponentPeer.java
--- gnu/java/awt/peer/gtk/GtkComponentPeer.java	17 Jul 2006 22:41:03 -0000	1.117
+++ gnu/java/awt/peer/gtk/GtkComponentPeer.java	25 Jul 2006 22:40:43 -0000
@@ -48,77 +48,89 @@
 import java.awt.Cursor;
 import java.awt.Dimension;
 import java.awt.EventQueue;
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
 import java.awt.GraphicsConfiguration;
 import java.awt.GraphicsDevice;
 import java.awt.GraphicsEnvironment;
 import java.awt.Image;
 import java.awt.Insets;
 import java.awt.ItemSelectable;
+import java.awt.KeyboardFocusManager;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.Toolkit;
 import java.awt.Window;
 import java.awt.event.FocusEvent;
 import java.awt.event.ItemEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseWheelEvent;
 import java.awt.event.PaintEvent;
 import java.awt.event.TextEvent;
 import java.awt.image.ColorModel;
 import java.awt.image.ImageObserver;
 import java.awt.image.ImageProducer;
 import java.awt.image.VolatileImage;
 import java.awt.peer.ComponentPeer;
 import java.awt.peer.ContainerPeer;
+import java.awt.peer.LightweightPeer;
 import java.awt.peer.WindowPeer;
 import java.util.Timer;
 import java.util.TimerTask;
 
 public class GtkComponentPeer extends GtkGenericPeer
   implements ComponentPeer
 {
   VolatileImage backBuffer;
   BufferCapabilities caps;
 
   Component awtComponent;
 
   Insets insets;
 
+  /**
+   * Stores the actually requested focus component. This is used in
+   * [EMAIL PROTECTED] #postFocusEvent(int, boolean)} to determine the actual component
+   * which received focus.
+   */
+  private Component focusRequest;
+
   /* this isEnabled differs from Component.isEnabled, in that it
      knows if a parent is disabled.  In that case Component.isEnabled 
      may return true, but our isEnabled will always return false */
   native boolean isEnabled ();
   static native boolean modalHasGrab();
 
   native int[] gtkWidgetGetForeground ();
   native int[] gtkWidgetGetBackground ();
   native void gtkWidgetGetDimensions (int[] dim);
   native void gtkWidgetGetPreferredDimensions (int[] dim);
   native void gtkWindowGetLocationOnScreen (int[] point);
   native void gtkWidgetGetLocationOnScreen (int[] point);
   native void gtkWidgetSetCursor (int type, GtkImage image, int x, int y);
   native void gtkWidgetSetCursorUnlocked (int type, GtkImage image,
 					  int x, int y);
   native void gtkWidgetSetBackground (int red, int green, int blue);
   native void gtkWidgetSetForeground (int red, int green, int blue);
   native void gtkWidgetSetSensitive (boolean sensitive);
   native void gtkWidgetSetParent (ComponentPeer parent);
   native void gtkWidgetRequestFocus ();
   native void gtkWidgetDispatchKeyEvent (int id, long when, int mods,
                                          int keyCode, int keyLocation);
+  native boolean gtkWidgetHasFocus();
+  native boolean gtkWidgetCanFocus();
+
   native void realize();
   native void setNativeEventMask ();
 
   void create ()
   {
     throw new RuntimeException ();
   }
 
   native void connectSignals ();
 
   protected GtkComponentPeer (Component awtComponent)
   {
@@ -406,26 +418,25 @@
                                      new Rectangle (x, y, width, height)));
     }
 
     static void schedule(long tm, int x, int y, int width, int height,
 			 Component c)
     {
       repaintTimer.schedule(new RepaintTimerTask(c, x, y, width, height), tm);
     }
   }
 
   public void requestFocus ()
   {
-    gtkWidgetRequestFocus();
-    postFocusEvent(FocusEvent.FOCUS_GAINED, false);
+    assert false: "Call new requestFocus() method instead";
   }
 
   public void reshape (int x, int y, int width, int height) 
   {
     setBounds (x, y, width, height);
   }
 
   public void setBackground (Color c) 
   {
     gtkWidgetSetBackground (c.getRed(), c.getGreen(), c.getBlue());
   }
 
@@ -620,27 +631,38 @@
 	  {
 	    q.postEvent(keyEvent);
 	    keyEvent = new KeyEvent(awtComponent, KeyEvent.KEY_TYPED, when,
 				    mods, KeyEvent.VK_UNDEFINED, keyChar,
 				    keyLocation);
 	    q.postEvent(keyEvent);
           }
       }
     else
       q.postEvent(keyEvent);
   }
 
+  protected void postFocusEvent (int id, boolean temporary, Component target)
+  {
+    q().postEvent (new FocusEvent (target, id, temporary));
+  }
+
+  /**
+   * Referenced from native code.
+   *
+   * @param id
+   * @param temporary
+   */
   protected void postFocusEvent (int id, boolean temporary)
   {
-    q().postEvent (new FocusEvent (awtComponent, id, temporary));
+    postFocusEvent(id, temporary, focusRequest);
   }
 
   protected void postItemEvent (Object item, int stateChange)
   {
     q().postEvent (new ItemEvent ((ItemSelectable)awtComponent, 
 				ItemEvent.ITEM_STATE_CHANGED,
 				item, stateChange));
   }
 
   protected void postTextEvent ()
   {
     q().postEvent (new TextEvent (awtComponent, TextEvent.TEXT_VALUE_CHANGED));
@@ -655,28 +677,91 @@
   }
 
   public void setEventMask (long mask)
   {
     // FIXME: just a stub for now.
   }
 
   public boolean isFocusable ()
   {
     return false;
   }
 
-  public boolean requestFocus (Component source, boolean b1, 
-                               boolean b2, long x)
+  public boolean requestFocus (Component request, boolean temporary, 
+                               boolean allowWindowFocus, long time)
   {
-    return false;
+    assert request == awtComponent || isLightweightDescendant(request);
+    boolean retval = false;
+    if (gtkWidgetHasFocus())
+      {
+        KeyboardFocusManager kfm =
+          KeyboardFocusManager.getCurrentKeyboardFocusManager();
+        Component currentFocus = kfm.getFocusOwner();
+        if (currentFocus == request)
+          // Nothing to do in this trivial case.
+          retval = true;
+        else
+          {
+            // Requested component is a lightweight descendant of this one
+            // or the actual heavyweight.
+            // Since this (native) component is already focused, we simply
+            // change the actual focus and be done.
+            postFocusEvent(FocusEvent.FOCUS_GAINED, temporary, request);
+            retval = true;
+          }
+      }
+    else
+      {
+        if (gtkWidgetCanFocus())
+          {
+            if (allowWindowFocus)
+              {
+                Window window = getWindowFor(request);
+                GtkWindowPeer wPeer = (GtkWindowPeer) window.getPeer();
+                if (! wPeer.gtkWindowHasFocus())
+                  wPeer.requestWindowFocus();
+              }
+            // Store requested focus component so that the corresponding
+            // event is dispatched correctly.
+            focusRequest = request;
+            gtkWidgetRequestFocus();
+            retval = true;
+          }
+      }
+    return retval;
+  }
+
+  private Window getWindowFor(Component c)
+  {
+    Component comp = c;
+    while (! (comp instanceof Window))
+      comp = comp.getParent();
+    return (Window) comp;
+  }
+
+  /**
+   * Returns <code>true</code> if the component is a direct (== no intermediate
+   * heavyweights) lightweight descendant of this peer's component.
+   *
+   * @param c the component to check
+   *
+   * @return <code>true</code> if the component is a direct (== no intermediate
+   *         heavyweights) lightweight descendant of this peer's component
+   */
+  protected boolean isLightweightDescendant(Component c)
+  {
+    Component comp = c;
+    while (comp.getPeer() instanceof LightweightPeer)
+      comp = comp.getParent();
+    return comp == awtComponent;
   }
 
   public boolean isObscured ()
   {
     return false;
   }
 
   public boolean canDetermineObscurity ()
   {
     return false;
   }
 
Index: gnu/java/awt/peer/gtk/GtkWindowPeer.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java,v
retrieving revision 1.50
diff -u -1 -2 -r1.50 GtkWindowPeer.java
--- gnu/java/awt/peer/gtk/GtkWindowPeer.java	17 Jul 2006 22:41:03 -0000	1.50
+++ gnu/java/awt/peer/gtk/GtkWindowPeer.java	25 Jul 2006 22:40:43 -0000
@@ -32,27 +32,29 @@
 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.Component;
 import java.awt.Frame;
 import java.awt.Graphics;
+import java.awt.KeyboardFocusManager;
 import java.awt.Rectangle;
 import java.awt.Window;
 import java.awt.event.ComponentEvent;
+import java.awt.event.FocusEvent;
 import java.awt.event.PaintEvent;
 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;
@@ -61,24 +63,25 @@
   protected static final int GDK_WINDOW_TYPE_HINT_DESKTOP = 7;
 
   private boolean hasBeenShown = false;
   private int oldState = 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 ();
 
   /** Returns the cached width of the AWT window component. */
   int getX ()
   {
     return x;
   }
 
   /** Returns the cached width of the AWT window component. */
   int getY ()
   {
     return y;
@@ -292,25 +295,58 @@
     // non-zero.
     q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
                                    new Rectangle (x + insets.left, 
                                                   y + insets.top, 
                                                   width, height)));
   }
 
   public boolean requestWindowFocus()
   {
     // TODO Auto-generated method stub
     return false;
   }
-  
+
+  public boolean requestFocus (Component request, boolean temporary, 
+                               boolean allowWindowFocus, long time)
+  {
+    assert request == awtComponent || isLightweightDescendant(request);
+    boolean retval = false;
+    if (gtkWindowHasFocus())
+      {
+        KeyboardFocusManager kfm =
+          KeyboardFocusManager.getCurrentKeyboardFocusManager();
+        Component currentFocus = kfm.getFocusOwner();
+        if (currentFocus == request)
+          // Nothing to do in this trivial case.
+          retval = true;
+        else
+          {
+            // Requested component is a lightweight descendant of this one
+            // or the actual heavyweight.
+            // Since this (native) component is already focused, we simply
+            // change the actual focus and be done.
+            postFocusEvent(FocusEvent.FOCUS_GAINED, temporary, request);
+            retval = true;
+          }
+      }
+    else
+      {
+        if (allowWindowFocus)
+          {
+            retval = requestWindowFocus();
+          }
+      }
+    return retval;
+  }
+
   public Graphics getGraphics ()
   {
     Graphics g = super.getGraphics ();
     // Translate AWT co-ordinates, which include a window frame's
     // insets, to GTK co-ordinates, which do not include a window
     // frame's insets.  GtkWindowPeer should always have all-zero
     // insets but GtkFramePeer and GtkDialogPeer insets will be
     // non-zero.
     g.translate (-insets.left, -insets.top);
     return g;
   }
 
Index: include/gnu_java_awt_peer_gtk_GtkComponentPeer.h
===================================================================
RCS file: /cvsroot/classpath/classpath/include/gnu_java_awt_peer_gtk_GtkComponentPeer.h,v
retrieving revision 1.24
diff -u -1 -2 -r1.24 gnu_java_awt_peer_gtk_GtkComponentPeer.h
--- include/gnu_java_awt_peer_gtk_GtkComponentPeer.h	25 May 2006 15:29:36 -0000	1.24
+++ include/gnu_java_awt_peer_gtk_GtkComponentPeer.h	25 Jul 2006 22:40:43 -0000
@@ -17,24 +17,26 @@
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetDimensions (JNIEnv *env, jobject, jintArray);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetPreferredDimensions (JNIEnv *env, jobject, jintArray);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWindowGetLocationOnScreen (JNIEnv *env, jobject, jintArray);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetLocationOnScreen (JNIEnv *env, jobject, jintArray);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursor (JNIEnv *env, jobject, jint, jobject, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursorUnlocked (JNIEnv *env, jobject, jint, jobject, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetBackground (JNIEnv *env, jobject, jint, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetForeground (JNIEnv *env, jobject, jint, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetSensitive (JNIEnv *env, jobject, jboolean);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetParent (JNIEnv *env, jobject, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetDispatchKeyEvent (JNIEnv *env, jobject, jint, jlong, jint, jint, jint);
+JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetHasFocus (JNIEnv *env, jobject);
+JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetCanFocus (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_realize (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeEventMask (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeBounds (JNIEnv *env, jobject, jint, jint, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNative (JNIEnv *env, jobject, jboolean);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked (JNIEnv *env, jobject, jboolean);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* __gnu_java_awt_peer_gtk_GtkComponentPeer__ */
Index: include/gnu_java_awt_peer_gtk_GtkWindowPeer.h
===================================================================
RCS file: /cvsroot/classpath/classpath/include/gnu_java_awt_peer_gtk_GtkWindowPeer.h,v
retrieving revision 1.24
diff -u -1 -2 -r1.24 gnu_java_awt_peer_gtk_GtkWindowPeer.h
--- include/gnu_java_awt_peer_gtk_GtkWindowPeer.h	15 Jul 2006 19:54:55 -0000	1.24
+++ include/gnu_java_awt_peer_gtk_GtkWindowPeer.h	25 Jul 2006 22:40:43 -0000
@@ -5,24 +5,25 @@
 
 #include <jni.h>
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetTitle (JNIEnv *env, jobject, jstring);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetResizable (JNIEnv *env, jobject, jboolean);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal (JNIEnv *env, jobject, jboolean);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetAlwaysOnTop (JNIEnv *env, jobject, jboolean);
+JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowHasFocus (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_realize (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create (JNIEnv *env, jobject, jint, jboolean, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNative (JNIEnv *env, jobject, jboolean);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNativeUnlocked (JNIEnv *env, jobject, jboolean);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env, jobject);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds (JNIEnv *env, jobject, jint, jint, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBoundsUnlocked (JNIEnv *env, jobject, jint, jint, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocation (JNIEnv *env, jobject, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocationUnlocked (JNIEnv *env, jobject, jint, jint);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize (JNIEnv *env, jobject, jint, jint);
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c,v
retrieving revision 1.64
diff -u -1 -2 -r1.64 gnu_java_awt_peer_gtk_GtkComponentPeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	25 May 2006 15:29:36 -0000	1.64
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	25 Jul 2006 22:40:43 -0000
@@ -330,24 +330,60 @@
 {
   void *ptr;
 
   gdk_threads_enter ();
 
   ptr = NSA_GET_PTR (env, obj);
 
   gtk_widget_set_sensitive (get_widget(GTK_WIDGET (ptr)), sensitive);
 
   gdk_threads_leave ();
 }
 
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetHasFocus
+(JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  jboolean retval;
+
+  gdk_threads_enter ();
+
+  ptr = NSA_GET_PTR (env, obj);
+  
+  retval = GTK_WIDGET_HAS_FOCUS((GTK_WIDGET (ptr)));
+
+  gdk_threads_leave ();
+
+  return retval;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetCanFocus
+(JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  jboolean retval;
+
+  gdk_threads_enter ();
+
+  ptr = NSA_GET_PTR (env, obj);
+  
+  retval = GTK_WIDGET_CAN_FOCUS((GTK_WIDGET (ptr)));
+
+  gdk_threads_leave ();
+
+  return retval;
+}
+
 JNIEXPORT void JNICALL
 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus
   (JNIEnv *env, jobject obj)
 {
   void *ptr;
 
   gdk_threads_enter ();
 
   ptr = NSA_GET_PTR (env, obj);
   
   gtk_widget_grab_focus (get_widget(GTK_WIDGET (ptr)));
 
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.68
diff -u -1 -2 -r1.68 gnu_java_awt_peer_gtk_GtkWindowPeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c	15 Jul 2006 08:02:23 -0000	1.68
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c	25 Jul 2006 22:40:46 -0000
@@ -1250,24 +1250,41 @@
 {
   void *ptr;
 
   gdk_threads_enter ();
 
   ptr = NSA_GET_PTR (env, obj);
 
   gtk_window_set_keep_above (GTK_WINDOW (ptr), alwaysOnTop);
 
   gdk_threads_leave ();
 }
 
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowHasFocus
+(JNIEnv *env, jobject obj)
+{
+  void *ptr;
+  jboolean retval;
+
+  gdk_threads_enter ();
+
+  ptr = NSA_GET_PTR (env, obj);
+
+  retval = gtk_window_has_toplevel_focus (GTK_WINDOW (ptr));
+
+  gdk_threads_leave ();
+  return retval;
+}
+
 JNIEXPORT void JNICALL
 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNative
   (JNIEnv *env, jobject obj, jboolean visible)
 {
   gdk_threads_enter ();
 
   Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNativeUnlocked
     (env, obj, visible);
 
   gdk_flush ();
 
   gdk_threads_leave ();

Reply via email to