Bug 330749 - Focus not correctly restored after opening/closing another shell
Summary: Focus not correctly restored after opening/closing another shell
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.7   Edit
Hardware: PC Mac OS X
: P3 major (vote)
Target Milestone: 3.7 M4   Edit
Assignee: Scott Kovatch CLA
QA Contact: Silenio Quarti CLA
URL:
Whiteboard:
Keywords: accessibility
Depends on:
Blocks:
 
Reported: 2010-11-21 11:11 EST by Markus Keller CLA
Modified: 2010-12-02 12:09 EST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Keller CLA 2010-11-21 11:11:59 EST
N20101119-2000 Cocoa, was OK in 3.6.1

- ControlExample > Shell
- click into the text field in the Listeners group
- click Create Shell
- click Close
=> Focus should be back in the text field, but it's somewhere else.

I discovered the problem in the SDK in a Java editor: After "Refactoring > Extract Local Variable", the focus was not in the editor's StyledText any more.

What's strange though, is that this doesn't happen with all dialogs
(e.g. "Open Type, Cancel" is OK).
Comment 1 Markus Keller CLA 2010-11-25 08:30:54 EST
This bug is really annoying and is a regression compared to 3.7 M3.
Could you please schedule this for M4?
Comment 2 Scott Kovatch CLA 2010-11-25 13:15:14 EST
I'll check into it when I get back on Monday. (I'm not even supposed to be reading this right now.) :-)
Comment 3 Markus Keller CLA 2010-11-25 13:43:15 EST
Wonderful, thanks! Enjoy the weekend.
Comment 4 Scott Kovatch CLA 2010-11-29 13:57:25 EST
This is fallout from the fix for bug 312195. Decorations.saveFocus() is supposed to get the current window's first responder and then calculate the Control corresponding to that view. This will always fail, however, because in windowDidResignKey the NSWindow has already deactivated, so Display.getFocusControl() will return either null or the Control of the first responder for the active window. When the window activates again, the saved focus is the last item you tabbed to.

All of this focus saving and restoring is probably unnecessary, as Cocoa does a good job of tracking it via the first responder, but I'm not going to touch it at this point. Fix is to set the focussed control in becomeFirstResponder, which is called whether you click a control or tab into it.
Comment 5 Scott Kovatch CLA 2010-11-29 13:59:06 EST
Fixed > 20101129.
Comment 6 Markus Keller CLA 2010-12-01 03:43:28 EST
Hmm, I guess I should just have posted my initial scenario with the "Extract Local Variable" refactoring.

In HEAD, I can't reproduce the problem in the ControlExample any more, but the refactoring scenario is still broken.
Comment 7 Scott Kovatch CLA 2010-12-01 16:16:10 EST
(In reply to comment #6)
> Hmm, I guess I should just have posted my initial scenario with the "Extract
> Local Variable" refactoring.

The problem is in fixFocus -- calling window.becomeFirstResponder() is definitely not the thing to do, as that eventually calls windowDidBecomeKey, and another activate/restoreFocus is done. In this case, the focus ends up bouncing around to a lot of different controls before ending up on the Shell.

The previous code 'window.makeFirstResponder(window)' should have been the right thing to do, but I see it was taken out for 291788.

Shell#setEnabled(boolean) is still commented out, so the fix for 290759 really isn't right to begin with. I'm still trying to understand what fixFocus is trying to accomplish, and why it's clearing the focus.
Comment 8 Scott Kovatch CLA 2010-12-01 17:36:27 EST
Got it. fixFocus() is supposed to clear the focus for the window, and then Shell#setEnabled() restores the focus if the window is active. That check was commented out. My comment #7 above is correct; the problem was that the setEnabled() was never completed.

In the second case the problem happens because the progress indicator dialog calls setEnabled(false) and then setEnabled(true) on the workbench window. Since the check to restore focus in Shell#setEnabled() was commented out, the focus never got restored properly.

I also put back Decorations#saveFocus(), because it was mostly correct -- it needs to find the Control for the shell's first responder, not the active window's first responder.

Fixed (again) > 20101201.
Comment 9 Markus Keller CLA 2010-12-02 05:13:31 EST
[I'm reopening this bug because the follow-up problems are directly related to the previous change. Please speak up if you want me to open new bugs.]

In HEAD, the scenario with "Extract Local Variable" is fixed, but now I see collateral damage in the Breadcrumb (scenario was OK before):
- In a Java Editor, enable the breadcrumb (e.g. Navigate > Show in Breadcrumb)
- click the last black arrow in the breadcrumb
- click another member
=> focus is in the main toolbar; should be in the editor's text area

When you set a breakpoint to Control#setFocus() with hit count 2, you see that the focus goes to the StyledText (it was on the breadcrumb tree before). Then set an access&modification breakpoint on Decorations#savedFocus and resume. When that breakpoint is hit, you see that Shell#windowDidResignKey() is called on the workbench window, and this destroys the contents of savedFocus for that shell.
Comment 10 Scott Kovatch CLA 2010-12-02 12:09:36 EST
(In reply to comment #9)
> [I'm reopening this bug because the follow-up problems are directly related to
> the previous change. Please speak up if you want me to open new bugs.]

In general, I would say that if the original bug is fixed any new bugs that fall out should be entered as new bugs. Chances are good that I've just exposed new problems that we weren't handling properly in the first place.

I created bug 331676 to track the new problem.