[
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) {