JDK-6806217 : implement synthetic focus model for MS Windows
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows
  • CPU: generic,x86
  • Submitted: 2009-02-17
  • Updated: 2014-07-07
  • Resolved: 2011-03-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
7 b55Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
AWT has a semi-lightweight approach for *nix platforms. That concerns the focus management
subsystem as well. A lightweight focus means that AWT establishes some restrictions on
setting focus for the native system. Instead, AWT sets focus at certain time on the
component that should gain focus from its perspective.

The restrictions concern setting focus on a particular component in a toplevel window
and in some cases activating a toplevel window.

This approach gives us:
- more flexibility (much less dependance on the native system)
- less error-prone, more clear, easier to debug code (less native code)
- unification b/w XAWT & MSW AWT focus, hence easier to support
- ability to do further refactoring of the whole focus subsystem

Also, implementing this focus model will allow us to resolve such tough problems
like this: 6741987 (6638103 for jdk5). Moreover, we will get quite close to
the "synchronous focus" (6448060).

EVALUATION THE DESCRIPTION ------------------------ ACTIVE & FOCUSED WINDOWS ------------------------ MS Windows doesn't differentiate an *active* and a *focused* state of a toplevel window. So, when a simple _Window_ is a *focused window* from the perspective of AWT this is not the case from the perspective of the native system. For the native system only the *active window* may contain a *focus owner*, the component the keyboard input is sent to. Thus, a simple _Window_ being a *focused window* may not receive the keyboard input because its owner (whose title is highlighted) is natively active. ----------- FOCUS PROXY ----------- The *focus proxy* mechanism is aimed to support focusability of a simple _Window_. A *focus proxy* is a native component created as a child of a _Frame_ or a _Dialog_, not visible on the screen (with zero size). A *focus proxy* component has no peer. In new focus model a *focus proxy* component is used overall, not only for a simple _Window_. This makes the focus subsystem more uniform and has some more advantages described further. How it works. When a toplevel window (_Frame/Dialog_) is activated the native focus is set on its *focus proxy* child. Thus it receives all native key messages. Then the messages are forwarded to the component that is the *focus owner* from the perspective of AWT. --------------- NATIVE CONTROLS --------------- When a native control is clicked then in general the native system performs the following: 1. Activates the toplevel parent (if it's not yet active); 1. Focuses the control (if it's not yet focused); 1. Makes the control react on the click appropriately. AWT needs to control/suppress the first two actions because: * An *unfocusable* toplevel may not be activated at all; * A native control may not steal focus from a *focus proxy*. Setting the native style WS_EX_NOACTIVATE on the toplevel suppresses the 1st action. But for the majority of the controls (except _Label_, _Scrollbar_ & _ScrollPane_) this is not enough. When a control receives a mouse message it requests the native system to set focus on it. And if the toplevel parent is not active it's also set active. The latter completely breaks focusability of a simple _Window_ because it may not steal activation from its owner. In order to avoid this effect, a native mouse message is NOT passed to the default message procedure of a control. But this also means that the native control will not react on a mouse click. This responsibility is now delegated to AWT. And AWT achieves it by means of sending a control specially defined native messages. The activating key message (VK_SPACE) can also trigger a focus change for some controls, thus it's NOT passed to the default message procedure as well. As a native control may no longer be a native focus owner it's also necessary to simulate its focused/unfocused state. This is achieved by means of sending it WM_SETFOCUS/WM_KILLFOCUS native messages. (Note, that the message itself doesn't make the control focused/unfocused, it just hints it to paint itself appropriately.) --------------------- NATIVE INPUT MESSAGES --------------------- When an input message is being processed by a message procedure of a control (!WmMouseDown/Up, !WmKeyDown/Up) the message is not immediately passed to the default message procedure. Instead, a Java event matching the native message is created and is posted to the event queue. It is then handled on the Java layer and is eventually passed back to the native control where the matching native message is extracted and is post-processed. On post-processing a native input message a decision whether the default message procedure should be called or not is taken. It depends on whether the message is a trigger for a native focus change or not. Here's the scheme of a key message processing: <pre> 1. A keystroke occurs. The native system generates a native key message. 2. A focus proxy receives the message. 3. The message is translated to a java key event. The target of the event is set to the current *focus owner*. The event is posted the java event queue. The native message is consumed. 4. The event is handled by the target java component. 5. The event is passed back to the native control. The matching native message is extracted. 6. If the message is a focus change trigger, AWT consumes it and simulates reaction of the control, otherwise the message is passed to the default message procedure. </pre> The scheme of processing of a native mouse message is pretty the same, except that the message comes directly to a control (i.e. a *focus proxy* is not used). But here there's an important difference b/w the old and the new focus models. In the old model focus was automatically set on a native control at the moment its default message procedure received a native mouse message. Now focus is requested on the Java side, when a java peer component handles a java mouse event. ------------- THE MAIN GOAL ------------- The main goal of the transition to the new focus model is to delegate the responsibility of managing focus from the native code to the Java side. Indeed, we have the [Default]KeyboardFocusManager (further KFM) class that does most of the job required to manage focus appropriately. It knows which events and in what order should be generated in different states of an ongoing focus switching. The old focus model accepted native activation change b/w toplevels and native focus change b/w controls inside a single toplevel. Appropriate events had been posted to Java. As the result we had duplicate logic of managing focus on both Java and native sides. It was quite complicated to support all that stuff. Error-prone code and fragile reliability. Now we completely refused managing native focus change b/w controls. Focus is requested to the control and it's the KFM that decides which component and when should gain it. It also knows which component is the opposite one. The native system may still (like in XAWT) activate a toplevel in the following cases: * A user selects the toplevel by Alt-Tab; * A user clicks the toplevel's button in the taskbar; * The toplevel is being shown. But now when a toplevel is being activated we suppress any focus messages that come from the native system. It's the responsibility of the KFM to set focus on a proper component after the toplevel is made visible. The scheme is as follows: <pre> 1. A control is clicked with the mouse. 2. Focus is requested to the java component. The component becomes the most-recent-focus-owner in its toplevel parent. 3. The toplevel parent is focused (and activated if needed) (it's the only duty delegated to the native side). 4. The KFM receives WINDOW_GAINED_FOCUS event and decides which component should be the focus owner: - the default component; - the temporary-lost-focus component; - the most-recent-focus-owner component. 5. The KFM just notifies the native control of changing its focus state. </pre> ------- SUMMARY ------- Advantages of the new synthetic focus model: * Easier to understand/support/debug. * A basement for further potential refactoring of the Java side. * The focus logic/code is unified with the XAWT focus logic/code. * Now we're in a one step from the synchronous focus (if we need it). Disadvantages: * Additional efforts to simulate the native behavior of some controls. ---++ Affected workarounds Workarounds for the following CR's have been removed (R) or simplified (S): * (R) 6562716 focus request queue is not updated when rejecting focus on !EmbeddedFrame (win32) * (R) 4380809 Focus disappears after deiconifying frame * (R) 6200795 PIT: Regression testcase Button/DisabledButtonPress/DisabledButtonPress.html fails * (S) 6374321 Textfield loses focus after alt key hit in IE browser * (S) 6366006 REG: Choice stops working after opening and disposing a modal dialog in itemStateChanged ---++ Open issues The following issues are to be resolved: 1. The context menu is not popped up for !ScrollPane * Looks not critical. 1. Scrollbar's focus indicator doesn't adjust its position on scrolling * Looks not critical. 1. 6566434 REG: Choice on a non-focusable window responds to keyboard interactions, XToolkit * Looks Ok actually. We have to revise the behavior. 1. 6293432 Key events ('SPACE', 'UP', 'DOWN') aren't blocked if mouse is kept in 'PRESSED' state for List, XAWT * The appropriate fix developed for XAWT should be ported to MS Windows side.