Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [albireo-dev] border and focus

Hi Gordon,

Here are the fixes to make focus mostly work with border.

What works (on Windows): the first three test cases of
  http://wiki.eclipse.org/Albireo_Focus_Management_Test_Cases
(Getting these to work dictated whether to use the swingControl or the
borderlessChild in FocusHandler. We must use the borderlessChild.)

What does not work: Traversal is partially broken.
To reproduce: Set the Parameters.borderFlag constant to SWT.BORDER. Then
look at the TextFieldsView.
      - Select first text field, Shift-Tab -> the focus never comes back.
      - Select last text field, Tab repeatedly -> the focus never comes back.

Other things I tried:
  - Use SWT.NO_FOCUS instead of 0 in the line determining the SwingControl's
    style. Hardly any effect.
  - In the final 'else' clause of SwingControl.forceFocus, tried to change
    super.forceFocus() ->  super.forceFocus() && borderlessChild.forceFocus().
    Effect:
      - Select first text field, Shift-Tab -> cycles to last text field,
        should instead cycle to SWT widgets.
      - Select last text field, Tab repeatedly -> after the tab header was
        focused, the last text field is focused. Should focus the first text
        field instead.

I'm a bit lost here, since I don't know the mechanics of focus traversal.


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.69
diff -c -3 -r1.69 SwingControl.java
*** src/org/eclipse/albireo/core/SwingControl.java	25 Apr 2008 17:04:47 -0000	1.69
--- src/org/eclipse/albireo/core/SwingControl.java	25 Apr 2008 19:53:38 -0000
***************
*** 170,175 ****
--- 170,188 ----
                          SwingControl.this.assignInitialClientArea(rect);
                          return rect;
                      }
+                     /** 
+                      * Overridden to return false and prevent any focus change
+                      * if the embedded Swing component is not focusable. 
+                      */
+                     public boolean forceFocus() {
+                         checkWidget();
+                         if ((swingComponent != null) && !swingComponent.isFocusable()) {
+                             return false;
+                         } else {
+                             boolean result = super.forceFocus();
+                             return handleForceFocus(result);
+                         }
+                     }
                  };
          } else {
              // If no border is needed, there is no need to create another
***************
*** 1053,1059 ****
          assert frame != null;
          assert Display.getCurrent() != null;     // On SWT event thread
          
!         focusHandler = new FocusHandler(this, frame);   
      }
      
      
--- 1066,1072 ----
          assert frame != null;
          assert Display.getCurrent() != null;     // On SWT event thread
          
!         focusHandler = new FocusHandler(this, borderlessChild, frame);   
      }
      
      
***************
*** 1102,1108 ****
          if ((swingComponent != null) && !swingComponent.isFocusable()) {
              return false;
          } else {
!             return super.setFocus();
          }
      }
  
--- 1115,1124 ----
          if ((swingComponent != null) && !swingComponent.isFocusable()) {
              return false;
          } else {
!             if (borderlessChild == this)
!                 return super.setFocus();
!             else
!                 return borderlessChild.setFocus();
          }
      }
  
***************
*** 1114,1132 ****
       */
      public boolean forceFocus() {
          checkWidget();
!         
!         if ((swingComponent != null) && !swingComponent.isFocusable()) {
!             return false;
          } else {
              boolean result = super.forceFocus();
-             if (focusHandler != null) {
-                 result = focusHandler.handleForceFocus(result);
-             }
              return result;
          }
      }
!     
!     
      // ============================= Events and Listeners =============================
  
      private List sizeListeners = new ArrayList();
--- 1130,1159 ----
       */
      public boolean forceFocus() {
          checkWidget();
! 
!         if (borderlessChild == this) {
!             if ((swingComponent != null) && !swingComponent.isFocusable()) {
!                 return false;
!             } else {
!                 boolean result = super.forceFocus();
!                 return handleForceFocus(result);
!             }
          } else {
              boolean result = super.forceFocus();
              return result;
          }
      }
! 
!     /**
!      * Postprocess the super.forceFocus() result.
!      */
!     boolean handleForceFocus(boolean result) {
!         if (focusHandler != null) {
!             result = focusHandler.handleForceFocus(result);
!         }
!         return result;
!     }
! 
      // ============================= Events and Listeners =============================
  
      private List sizeListeners = new ArrayList();
Index: src/org/eclipse/albireo/internal/FocusHandler.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.albireo/org.eclipse.albireo.core/src/org/eclipse/albireo/internal/FocusHandler.java,v
retrieving revision 1.17
diff -c -3 -r1.17 FocusHandler.java
*** src/org/eclipse/albireo/internal/FocusHandler.java	25 Apr 2008 17:35:59 -0000	1.17
--- src/org/eclipse/albireo/internal/FocusHandler.java	25 Apr 2008 19:53:38 -0000
***************
*** 21,26 ****
--- 21,27 ----
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.FocusEvent;
  import org.eclipse.swt.events.FocusListener;
+ import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Control;
  import org.eclipse.swt.widgets.Display;
  import org.eclipse.swt.widgets.Event;
***************
*** 42,53 ****
      private static boolean synthesizeMethodInitialized = false;
      private static Method synthesizeMethod = null;
  
!     private static SwingControl activeSwingControl = null;
  
      // ========================================================================
  
      private final Frame frame;
!     private final SwingControl swingControl;
      private final Display display;
      private boolean pendingTraverseOut = false;
      private int pendingTraverseOutSeqNum = 0;
--- 43,55 ----
      private static boolean synthesizeMethodInitialized = false;
      private static Method synthesizeMethod = null;
  
!     private static Composite activeBorderless = null;
  
      // ========================================================================
  
      private final Frame frame;
!     private final Composite borderless; // the Control corresponding to the frame
!     private final SwingControl swingControl; // either borderless or its parent
      private final Display display;
      private boolean pendingTraverseOut = false;
      private int pendingTraverseOutSeqNum = 0;
***************
*** 62,74 ****
      private FocusListener swtFocusListener = new SwtFocusListener();
      private Listener swtEventFilter = new SwtEventFilter();
  
!     public FocusHandler(final SwingControl swingControl, final Frame frame) {
          assert Display.getCurrent() != null;     // On SWT event thread
  
          if (verboseFocusEvents)
              FocusDebugging.addFocusDebugListeners(swingControl, frame);
          
          this.swingControl = swingControl;
          this.frame = frame;
          display = swingControl.getDisplay();
          
--- 64,77 ----
      private FocusListener swtFocusListener = new SwtFocusListener();
      private Listener swtEventFilter = new SwtEventFilter();
  
!     public FocusHandler(final SwingControl swingControl, final Composite borderless, final Frame frame) {
          assert Display.getCurrent() != null;     // On SWT event thread
  
          if (verboseFocusEvents)
              FocusDebugging.addFocusDebugListeners(swingControl, frame);
          
          this.swingControl = swingControl;
+         this.borderless = borderless;
          this.frame = frame;
          display = swingControl.getDisplay();
          
***************
*** 81,94 ****
          
          // We won't get an Activate event for the newly created control, so update
          // the static tracking field here. 
!         if (display.getFocusControl() == swingControl) {
!             activeSwingControl = swingControl;
          }
          
          frame.addWindowFocusListener(awtWindowFocusListener);
          KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keyEventDispatcher);
          
!         swingControl.addFocusListener(swtFocusListener);
          
      }
      
--- 84,97 ----
          
          // We won't get an Activate event for the newly created control, so update
          // the static tracking field here. 
!         if (display.getFocusControl() == borderless) {
!             activeBorderless = borderless;
          }
          
          frame.addWindowFocusListener(awtWindowFocusListener);
          KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keyEventDispatcher);
          
!         borderless.addFocusListener(swtFocusListener);
          
      }
      
***************
*** 98,104 ****
          display.removeFilter(SWT.Traverse, swtEventFilter);
          frame.removeWindowFocusListener(awtWindowFocusListener);
          KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(keyEventDispatcher);
!         swingControl.removeFocusListener(swtFocusListener);
      }
      
      // ================ 
--- 101,107 ----
          display.removeFilter(SWT.Traverse, swtEventFilter);
          frame.removeWindowFocusListener(awtWindowFocusListener);
          KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(keyEventDispatcher);
!         borderless.removeFocusListener(swtFocusListener);
      }
      
      // ================ 
***************
*** 225,232 ****
          if (verboseTraverseOut) {
              trace("SWT: traversing, control=" + focusControl);
          }
!         if ((focusControl == null) && (activeSwingControl != null)) {
!             focusControl = activeSwingControl;
              if (verboseTraverseOut) {
                  trace("SWT: current focus control is null; using=" + focusControl);
              }
--- 228,235 ----
          if (verboseTraverseOut) {
              trace("SWT: traversing, control=" + focusControl);
          }
!         if ((focusControl == null) && (activeBorderless != null)) {
!             focusControl = activeBorderless;
              if (verboseTraverseOut) {
                  trace("SWT: current focus control is null; using=" + focusControl);
              }
***************
*** 235,241 ****
              boolean traverse = focusControl.traverse(direction);
              
              Control newFocusControl = display.getFocusControl();
!             if (traverse && (newFocusControl == focusControl) && (newFocusControl == activeSwingControl)) {
                  // We were unable to traverse anywhere else.
                  if (verboseTraverseOut) {
                      trace("no-op traverse out, control=" + focusControl);
--- 238,244 ----
              boolean traverse = focusControl.traverse(direction);
              
              Control newFocusControl = display.getFocusControl();
!             if (traverse && (newFocusControl == focusControl) && (newFocusControl == activeBorderless)) {
                  // We were unable to traverse anywhere else.
                  if (verboseTraverseOut) {
                      trace("no-op traverse out, control=" + focusControl);
***************
*** 297,320 ****
          if (!display.isDisposed()) {
              ThreadingHandler.getInstance().asyncExec(display, new Runnable() {
                  public void run() {
!                     if (!swingControl.isDisposed() &&
                              
                          // Make sure that this control is in the active shell, so focus is not stolen from other windows    
!                         (display.getActiveShell() == swingControl.getShell()) && 
                          
                          // Check that this control still the focus control, despite the recent deactivation.
                          // BUT... Display.getFocusControl is unreliable when another embedded AWT window has 
                          // become active, so to be safe, make sure that no other Swing control has been activated
                          // (otherwise we will steal focus from some other active SwingControl)
!                         (swingControl == display.getFocusControl() && (activeSwingControl == null))) {
                          
                          if (verboseFocusEvents) {
!                             trace("Manually reactivating " + swingControl);
                          }
                          // Ideally, we would directly activate SwingControl here, but there seems to be 
                          // no way to do that, so activate the underlying AWT embedded frame
                          synthesizeWindowActivation(true);
!                         activeSwingControl = swingControl;
                      }
                  }
              });
--- 300,323 ----
          if (!display.isDisposed()) {
              ThreadingHandler.getInstance().asyncExec(display, new Runnable() {
                  public void run() {
!                     if (!borderless.isDisposed() &&
                              
                          // Make sure that this control is in the active shell, so focus is not stolen from other windows    
!                         (display.getActiveShell() == borderless.getShell()) && 
                          
                          // Check that this control still the focus control, despite the recent deactivation.
                          // BUT... Display.getFocusControl is unreliable when another embedded AWT window has 
                          // become active, so to be safe, make sure that no other Swing control has been activated
                          // (otherwise we will steal focus from some other active SwingControl)
!                         (borderless == display.getFocusControl() && (activeBorderless == null))) {
                          
                          if (verboseFocusEvents) {
!                             trace("Manually reactivating " + borderless);
                          }
                          // Ideally, we would directly activate SwingControl here, but there seems to be 
                          // no way to do that, so activate the underlying AWT embedded frame
                          synthesizeWindowActivation(true);
!                         activeBorderless = borderless;
                      }
                  }
              });
***************
*** 451,461 ****
                  currentSwtTraversal = event.detail;
                  return;
              }
!             if (event.widget == swingControl) {
                  switch (event.type) {
                  case SWT.Activate:
                      isActiveSwt = true;
!                     activeSwingControl = swingControl;
                      if (Platform.isWin32() && (Platform.SWT_VERSION < Platform.SWT_FIX216431) && (synthesizeMethod != null)) {
                          synthesizeWindowActivation(true);
                          if (verboseFocusEvents) {
--- 454,464 ----
                  currentSwtTraversal = event.detail;
                  return;
              }
!             if (event.widget == borderless) {
                  switch (event.type) {
                  case SWT.Activate:
                      isActiveSwt = true;
!                     activeBorderless = borderless;
                      if (Platform.isWin32() && (Platform.SWT_VERSION < Platform.SWT_FIX216431) && (synthesizeMethod != null)) {
                          synthesizeWindowActivation(true);
                          if (verboseFocusEvents) {
***************
*** 470,476 ****
  
                  case SWT.Deactivate:
                      isActiveSwt = false;
!                     activeSwingControl = null;
                      if (Platform.isWin32() && (Platform.SWT_VERSION < Platform.SWT_FIX216431) && (synthesizeMethod != null)) {
                          synthesizeWindowActivation(false);
                          if (verboseFocusEvents) {
--- 473,479 ----
  
                  case SWT.Deactivate:
                      isActiveSwt = false;
!                     activeBorderless = null;
                      if (Platform.isWin32() && (Platform.SWT_VERSION < Platform.SWT_FIX216431) && (synthesizeMethod != null)) {
                          synthesizeWindowActivation(false);
                          if (verboseFocusEvents) {


Back to the top