JDK-4380809 : Focus disappears after deiconifying frame
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_nt
  • CPU: x86
  • Submitted: 2000-10-19
  • Updated: 2004-09-21
  • Resolved: 2000-12-20
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.
Other Other
1.3.1_14Fixed 1.4.0 betaFixed
Related Reports
Relates :  
Relates :  
Description

Name: pzR10082			Date: 10/19/2000



Run the program below and pass focus to the button.
Minimize the frame and then restore it. The button
now is not focused.

---------------------------------------------
import javax.swing.*;

public class Test extends JFrame {

    public Test() {
        JButton button = new JButton("focused");
        getContentPane().add(button);
    }

    public static void main(String args[]) {
        Test frame = new Test();
        frame.pack();
        frame.setVisible(true);
    }
}
---------------------------------------------

This bug cannot be reproduced on Solaris using window
managers with focus-follows-mouse policy. It can be
easily reproduced on Windows, however.

This bug appeared in Merlin after focus changes.
It didn't exist in 1.3 or 1.2.2.

======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.3.1_14 merlin-beta FIXED IN: 1.3.1_14 merlin-beta INTEGRATED IN: merlin-beta
02-10-2004

SUGGESTED FIX ###@###.### 2000-12-14 ------- awt_Component.h ------- *** /tmp/d0eN45S Thu Dec 14 11:14:24 2000 --- awt_Component.h Wed Dec 13 16:39:16 2000 *************** *** 552,557 **** --- 552,558 ---- static MSG* CreateMessage(UINT message, WPARAM wParam, LPARAM lParam, int x, int y); static HWND sm_focusOwner; + static HWND sm_focusedWindow; static BOOL m_isWin95; static BOOL m_isWin2000; ------- awt_Component.cpp ------- *** /tmp/d0eN45S Thu Dec 14 11:14:25 2000 --- awt_Component.cpp Wed Dec 13 16:39:00 2000 *************** *** 77,82 **** --- 77,83 ---- BOOL AwtComponent::sm_suppressFocusAndActivation; HWND AwtComponent::sm_focusOwner; + HWND AwtComponent::sm_focusedWindow; HWND AwtComponent::sm_realFocusOpposite; #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) *************** *** 172,177 **** --- 173,181 ---- if (sm_focusOwner == GetHWnd()) { ::SetFocus(NULL); } + if (sm_focusedWindow == GetHWnd()) { + sm_focusedWindow = NULL; + } if (sm_realFocusOpposite == GetHWnd()) { sm_realFocusOpposite = NULL; } *************** *** 931,947 **** break; case WM_SETFOCUS: ! mr = (!sm_suppressFocusAndActivation) ? WmSetFocus((HWND)wParam) : mrConsume; break; case WM_KILLFOCUS: ! mr = (!sm_suppressFocusAndActivation) ? WmKillFocus((HWND)wParam) : mrConsume; break; case WM_ACTIVATE: ! if (!sm_suppressFocusAndActivation) { mr = WmActivate(LOWORD(wParam), (BOOL)HIWORD(wParam), ! (HWND)lParam); AwtToolkit::GetInstance().UpdateThemesStatus(); } else { mr = mrConsume; --- 935,953 ---- break; case WM_SETFOCUS: ! mr = (!sm_suppressFocusAndActivation && (sm_focusedWindow != NULL)) ? WmSetFocus((HWND)wParam) : mrConsume; break; case WM_KILLFOCUS: ! mr = (!sm_suppressFocusAndActivation && (sm_focusedWindow != NULL)) ? WmKillFocus((HWND)wParam) : mrConsume; break; case WM_ACTIVATE: ! if (!sm_suppressFocusAndActivation && ! (!(BOOL)HIWORD(wParam) || (LOWORD(wParam) == WA_INACTIVE))) ! { mr = WmActivate(LOWORD(wParam), (BOOL)HIWORD(wParam), ! (HWND)lParam); AwtToolkit::GetInstance().UpdateThemesStatus(); } else { mr = mrConsume; *************** *** 1442,1448 **** SendFocusEvent(java_awt_event_FocusEvent_FOCUS_LOST, isTemporary, hWndGotFocus); - return mrDoDefault; } --- 1448,1453 ---- ------- awt_Frame.cpp ------- *** /tmp/d0eN45S Thu Dec 14 11:14:25 2000 --- awt_Frame.cpp Wed Dec 13 16:37:54 2000 *************** *** 351,359 **** if (nState != WA_INACTIVE) { ::SetFocus(NULL); // The KeyboardFocusManager will set focus later ! type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; } else { type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; } SendWindowEvent(type, opposite); --- 351,361 ---- if (nState != WA_INACTIVE) { ::SetFocus(NULL); // The KeyboardFocusManager will set focus later ! type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; ! sm_focusedWindow = GetHWnd(); } else { type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; + sm_focusedWindow = NULL; } SendWindowEvent(type, opposite); ------- awt_Window.cpp ------- *** /tmp/d0eN45S Thu Dec 14 11:14:26 2000 --- awt_Window.cpp Wed Dec 13 16:37:17 2000 *************** *** 459,471 **** if (nState != WA_INACTIVE) { ::SetFocus((sm_focusOwner == NULL || ! AwtComponent::GetTopLevelParentForWindow(sm_focusOwner) != ! GetHWnd()) ? NULL : sm_focusOwner); type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; ! AwtToolkit::GetInstance(). ! InvokeFunctionLater(BounceActivation, this); } else { type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; } SendWindowEvent(type, opposite); --- 459,473 ---- if (nState != WA_INACTIVE) { ::SetFocus((sm_focusOwner == NULL || ! AwtComponent::GetTopLevelParentForWindow(sm_focusOwner) != ! GetHWnd()) ? NULL : sm_focusOwner); type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; ! AwtToolkit::GetInstance(). ! InvokeFunctionLater(BounceActivation, this); ! sm_focusedWindow = GetHWnd(); } else { type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; + sm_focusedWindow = NULL; } SendWindowEvent(type, opposite);
02-10-2004

EVALUATION As bug appeared after focus changes, reassigning to awt. scott.violet@eng 2000-10-23 Commit to fix in Merlin (regression). eric.hawkes@eng 2000-11-08 the problem is as follows: on Windows, when we retore window it receives three events: WM_ACTIVATE(nState=WA_ACTIVE, fMinimize=TRUE) WM_SETFOCUS(focus was set to this window) WM_ACTIVATE(nState=WA_ACTIVE, fMinimize=FALSE) So, all work about focus management is performed after first WM_ACTIVATE, after WM_SETFOCUS we set focus to frame, and for second WM_ACTIVATE in AwtFrame::WmActivate we set focus to NULL. In fact, java event WINDOW_ACTIVATED is eqvuivalent to WM_ACTIVATE(nState=WA_ACTIVE, fMinimize=FALSE). And our focus code assume that we receive WM_SETFOCUS after WM_ACTIVATE. So, to fix this problem we must skip any WM_ACTIVATE(WA_ACTIVE, TRUE). And skip WM_SETFOCUS and WM_KILLFOCUS untill we receive WM_ACTIVATE(fMinimized=FALSE). ###@###.### 2000-12-14 Here the fix is described with Win32 way of implementation: From my understanding on Windows messages and Java equivalents: 1. When a window(Frame) is minimized WM_SIZE:SIZE_MINIMIZED == windowIconified WM_KILLFOCUS:component-in-focus == focusLost:temporary WM_ACTIVATE:WA_INACTIVE == windowDeactivated 2. When a window(Frame) is restored WM_ACTIVATE:WA_ACTIVE/WA_CLICKACTIVE == windowActivated WM_SIZE:SIZE_RESTORED == windowDeiconified WM_SETFOCUS:top-app-window == focusGained:permanent Since the java.awt.Window.dispatchEventImpl() method always makes that particular instance as the current focus owner, the actual component is not gaining the focus. I remember in Windows programming, WM_ACTIVATE (restoring) will put the active window into focus. In this Windows window, WM_SETFOCUS handler is expected to SetFocus() on the required component. In case of Windows dialog, the component's focus would be received automatically. During the WM_KILLFOCUS, the previous focus owner is saved. This can be reused during the WM_SETFOCUS to restore the focus on the previous component. For this, the Java Window.dispatchEventImpl() has to accommodate the changes to allow the previous component restoration. There is no over-riding dispatchEventImpl method in Java Frame class. In the fix to Window.dispatchEventImpl():FOCUS_GAINED, the previous focus owner is not overwritten in case of Frame. Incidentally, Component.dispatchEventImpl() also does similar to this but for Window instances. Since in the earlier version, the main window (Java Frame) is setting itself to the focus owner the WM_SETFOCUS was redundant and required code to skip one. ###@###.### 2004-09-21
21-09-2004