Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [albireo-dev] Focus Management Test Cases

Gordon Hirsch wrote:
> I have a different, simpler way of tracing the AWT focus events. It uses 
> a property change listener on the keyboard focus manager. It's a little 
> more helpful to me because it also tracks events on AWT dialogs.

Good.

> I'm committing this debug code to AwtEnvironment. If it can provide all 
> the AWT information that the FocusDebugging provides, then I suggest 
> keeping only this simpler version of the trace code and removing the AWT 
> tracing from FocusDebugging.

With the example test case (I will soon rebuild for your testing) it
became clear to me that focus handling is a multi-player game. The players
involved are:
  1- The focus manager of the SWT window,
  2- The focus handling of the native SWT peer of the SwingControl,
  3- The focus handling of the native AWT peer of the EmbeddedFrame,
  4- The focus handling of each AWT Component in it,
  5- The global AWT KeyboardFocusManager.

When you have a bug, you need to collect the focus-related information of
as many players as possible. Your debugging code gives info about player #5.
Mine gives info about players #2, #3, #4.

So the codes are complementary. It would be an illusion to think you can
understand focus bugs (and find reliable workarounds) by looking only at #5.

I'm integrating both debugging codes in the same class, because too much
debugging code in the main source code can clutter up the real code.

Bruno


Index: src/org/eclipse/albireo/core/SwingControl.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.albireo/org.eclipse.albireo.core/src/org/eclipse/albireo/core/SwingControl.java,v
retrieving revision 1.28
diff -c -3 -r1.28 SwingControl.java
*** src/org/eclipse/albireo/core/SwingControl.java	12 Feb 2008 15:11:38 -0000	1.28
--- src/org/eclipse/albireo/core/SwingControl.java	13 Feb 2008 19:11:12 -0000
***************
*** 47,56 ****
  
      // Whether to print debugging information regarding size propagation
      // and layout.
!     private static final boolean verboseSizeLayout = false;
  
      // Whether to print debugging information regarding focus events.
!     private static final boolean verboseFocusEvents = false;
  
      private Listener settingsListener = new Listener() {
          public void handleEvent(Event event) {
--- 47,56 ----
  
      // Whether to print debugging information regarding size propagation
      // and layout.
!     static final boolean verboseSizeLayout = false;
  
      // Whether to print debugging information regarding focus events.
!     static final boolean verboseFocusEvents = false;
  
      private Listener settingsListener = new Listener() {
          public void handleEvent(Event event) {
Index: src/org/eclipse/albireo/core/AwtEnvironment.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.albireo/org.eclipse.albireo.core/src/org/eclipse/albireo/core/AwtEnvironment.java,v
retrieving revision 1.7
diff -c -3 -r1.7 AwtEnvironment.java
*** src/org/eclipse/albireo/core/AwtEnvironment.java	11 Feb 2008 22:46:31 -0000	1.7
--- src/org/eclipse/albireo/core/AwtEnvironment.java	13 Feb 2008 19:11:12 -0000
***************
*** 25,30 ****
--- 25,31 ----
  
  import javax.swing.UnsupportedLookAndFeelException;
  
+ import org.eclipse.albireo.internal.FocusDebugging;
  import org.eclipse.albireo.internal.SwtInputBlocker;
  import org.eclipse.albireo.internal.AwtDialogListener;
  import org.eclipse.swt.SWT;
***************
*** 141,159 ****
              EventQueue.invokeAndWait(new Runnable() {
                  public void run() {
                      setLookAndFeel();
! 
! //                    if (focusDebugListener == null) {
! //                        focusDebugListener = new PropertyChangeListener() {
! //                            public void propertyChange(PropertyChangeEvent event) {
! //                                System.out.println("@"+System.currentTimeMillis() +
! //                                        " " + event.getPropertyName() + 
! //                                        " new=" + event.getNewValue() +
! //                                        " old=" + event.getOldValue());
! //                            }
! //                        };
! //                        KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
! //                        focusManager.addPropertyChangeListener(focusDebugListener);
! //                    }
                  }
              });
          } catch (InterruptedException e) {
--- 142,149 ----
              EventQueue.invokeAndWait(new Runnable() {
                  public void run() {
                      setLookAndFeel();
!                     if (SwingControl.verboseFocusEvents)
!                         FocusDebugging.addFocusDebugListenerOnKeyboardFocusManager();
                  }
              });
          } catch (InterruptedException e) {
Index: src/org/eclipse/albireo/internal/FocusDebugging.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.albireo/org.eclipse.albireo.core/src/org/eclipse/albireo/internal/FocusDebugging.java,v
retrieving revision 1.1
diff -c -3 -r1.1 FocusDebugging.java
*** src/org/eclipse/albireo/internal/FocusDebugging.java	12 Feb 2008 15:11:38 -0000	1.1
--- src/org/eclipse/albireo/internal/FocusDebugging.java	13 Feb 2008 19:11:12 -0000
***************
*** 21,26 ****
--- 21,28 ----
  import java.awt.event.FocusListener;
  import java.awt.event.WindowEvent;
  import java.awt.event.WindowFocusListener;
+ import java.beans.PropertyChangeEvent;
+ import java.beans.PropertyChangeListener;
  
  /**
   * This class contains utility functions for debugging focus issues relating
***************
*** 31,48 ****
   * application window to be deactivated. Therefore a println based approach
   * has been adopted.
   * <p>
!  * There are three kinds of events:
   * <ul>
   *   <li>SWT focus events relating to the IlvSwingControl.</li>
   *   <li>AWT window focus events relating to the topmost window under the
   *       IlvSwingControl.</li>
   *   <li>AWT focus events relating to components inside that window.</li>
   * </ul>
   */
  public class FocusDebugging {
  
    /**
!    * Adds listeners for debugging all kinds of focus events.
     */
    public static void addFocusDebugListeners(org.eclipse.swt.widgets.Composite control,
                                              Container topLevelComponent) {
--- 33,52 ----
   * application window to be deactivated. Therefore a println based approach
   * has been adopted.
   * <p>
!  * There are four kinds of events:
   * <ul>
   *   <li>SWT focus events relating to the IlvSwingControl.</li>
   *   <li>AWT window focus events relating to the topmost window under the
   *       IlvSwingControl.</li>
   *   <li>AWT focus events relating to components inside that window.</li>
+  *   <li>Property change events of the AWT
+  *       <code>KeyboardFocusManager</code>.</li>
   * </ul>
   */
  public class FocusDebugging {
  
    /**
!    * Adds listeners for debugging the three first kinds of focus events.
     */
    public static void addFocusDebugListeners(org.eclipse.swt.widgets.Composite control,
                                              Container topLevelComponent) {
***************
*** 71,91 ****
     * Shows focus events on the top-level window on the AWT side.
     */
    private static class AWTWindowFocusListener implements WindowFocusListener {
      public void windowGainedFocus(WindowEvent event) {
        System.err.println("@"+System.currentTimeMillis()
                           +" AWT focus gained by window "+event.getWindow());
!       KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
!       System.err.println("owner1: "+kfm.getPermanentFocusOwner());
!       System.err.println("owner2: "+kfm.getFocusOwner());
!       System.err.println("owner3: "+event.getWindow().getFocusOwner());
      }
      public void windowLostFocus(WindowEvent event) {
        System.err.println("@"+System.currentTimeMillis()
                           +" AWT focus lost by window "+event.getWindow());
!       KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
!       System.err.println("owner1: "+kfm.getPermanentFocusOwner());
!       System.err.println("owner2: "+kfm.getFocusOwner());
!       System.err.println("owner3: "+event.getWindow().getFocusOwner());
      }
    }
    private static AWTWindowFocusListener _AWTWindowFocusListener = new AWTWindowFocusListener();
--- 75,95 ----
     * Shows focus events on the top-level window on the AWT side.
     */
    private static class AWTWindowFocusListener implements WindowFocusListener {
+     private void showKFMStatus(Window window) {
+       KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+       System.err.println("               permanentFocusOwner: "+kfm.getPermanentFocusOwner());
+       System.err.println("               focusOwner:          "+kfm.getFocusOwner());
+       System.err.println("               window's focusOwner: "+window.getFocusOwner());
+     }
      public void windowGainedFocus(WindowEvent event) {
        System.err.println("@"+System.currentTimeMillis()
                           +" AWT focus gained by window "+event.getWindow());
!       showKFMStatus(event.getWindow());
      }
      public void windowLostFocus(WindowEvent event) {
        System.err.println("@"+System.currentTimeMillis()
                           +" AWT focus lost by window "+event.getWindow());
!       showKFMStatus(event.getWindow());
      }
    }
    private static AWTWindowFocusListener _AWTWindowFocusListener = new AWTWindowFocusListener();
***************
*** 143,146 ****
--- 147,172 ----
      }
    }
  
+     // ------------------------------------------------------------------------
+ 
+     private static PropertyChangeListener focusDebugListener;
+ 
+     /**
+      * Adds listeners for debugging the fourth kind of focus events,
+      * on the AWT <code>KeyboardFocusManager</code> singleton.
+      */
+     public static void addFocusDebugListenerOnKeyboardFocusManager() {
+         if (focusDebugListener == null) {
+             focusDebugListener = new PropertyChangeListener() {
+                 public void propertyChange(PropertyChangeEvent event) {
+                     System.err.println("@"+System.currentTimeMillis()
+                                        + " AWT KFMPC " + event.getPropertyName()
+                                        + " new=" + event.getNewValue()
+                                        + " old=" + event.getOldValue());
+                 }
+             };
+             KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+             focusManager.addPropertyChangeListener(focusDebugListener);
+         }
+     }
  }


Back to the top