From 083311294cb607b4bd6a2d237ea131faefc0e6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Thu, 23 Oct 2003 09:07:54 +0000 Subject: [PATCH] Work on activation/focus svn path=/trunk/; revision=6412 --- reactos/subsys/win32k/include/winpos.h | 1 + reactos/subsys/win32k/ntuser/window.c | 148 ++++++++++++++++++++++--- reactos/subsys/win32k/ntuser/winpos.c | 78 ++++++++++++- 3 files changed, 207 insertions(+), 20 deletions(-) diff --git a/reactos/subsys/win32k/include/winpos.h b/reactos/subsys/win32k/include/winpos.h index a084ee3d1e7..4969e74aa29 100644 --- a/reactos/subsys/win32k/include/winpos.h +++ b/reactos/subsys/win32k/include/winpos.h @@ -17,3 +17,4 @@ WinPosShowWindow(HWND Wnd, INT Cmd); USHORT STDCALL WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint, PWINDOW_OBJECT* Window); +VOID FASTCALL WinPosActivateOtherWindow(PWINDOW_OBJECT Window); diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index 61d3d985f70..8559e041f1d 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: window.c,v 1.117 2003/10/22 21:10:24 gvg Exp $ +/* $Id: window.c,v 1.118 2003/10/23 09:07:54 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -664,6 +664,59 @@ IntLinkWindow( } +/***************************************************************** + * set_focus_window + * + * Change the focus window, sending the WM_SETFOCUS and WM_KILLFOCUS messages + */ +static HWND FASTCALL +set_focus_window(HWND New, PWINDOW_OBJECT Window, HWND Previous) +{ + PDESKTOP_OBJECT Desktop; + + ASSERT(NULL == Window || New == Window->Self); + + Desktop = IntGetActiveDesktop(); + ASSERT(NULL != Desktop); + + if (Window != NULL) + { + Window->MessageQueue->FocusWindow = New; + (PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue = + Window->MessageQueue; + } + else + { + (PUSER_MESSAGE_QUEUE) Desktop->ActiveMessageQueue = NULL; + } + + if (Previous == New) + { + return Previous; + } + + if (NULL != Previous) + { + NtUserSendMessage(Previous, WM_KILLFOCUS, (WPARAM) New, 0); + + if ((NULL == Desktop->ActiveMessageQueue && NULL != New) + || (NULL != Desktop->ActiveMessageQueue + && ((PUSER_MESSAGE_QUEUE)(Desktop->ActiveMessageQueue))->FocusWindow != New)) + { + /* changed by the message */ + return Previous; + } + } + +#if 0 /* FIXME */ + if (IsWindow(New)) +#endif + { + NtUserSendMessage(New, WM_SETFOCUS, (WPARAM) Previous, 0); + } + + return Previous; +} HWND FASTCALL IntSetFocusWindow(HWND hWnd) @@ -672,6 +725,7 @@ IntSetFocusWindow(HWND hWnd) PDESKTOP_OBJECT DesktopObject; PWINDOW_OBJECT WindowObject; HWND hWndOldFocus; + HWND hWndTop; DPRINT("IntSetFocusWindow(hWnd 0x%x)\n", hWnd); @@ -686,20 +740,20 @@ IntSetFocusWindow(HWND hWnd) } } else - { - WindowObject = NULL; - } + { + WindowObject = NULL; + } DesktopObject = IntGetActiveDesktop(); - if (!DesktopObject) + if (! DesktopObject) { DPRINT("No active desktop\n"); if (WindowObject != NULL) { - IntReleaseWindowObject(WindowObject); + IntReleaseWindowObject(WindowObject); } SetLastWin32Error(ERROR_INVALID_HANDLE); - return (HWND)0; + return (HWND)0; } hWndOldFocus = (HWND)0; @@ -709,16 +763,74 @@ IntSetFocusWindow(HWND hWnd) hWndOldFocus = OldMessageQueue->FocusWindow; } - if (WindowObject != NULL) + if (hWndOldFocus == hWnd) { - WindowObject->MessageQueue->FocusWindow = hWnd; - (PUSER_MESSAGE_QUEUE)DesktopObject->ActiveMessageQueue = - WindowObject->MessageQueue; + /* Nothing to do */ IntReleaseWindowObject(WindowObject); + return hWndOldFocus; } + + if (NULL != WindowObject) + { + hWndTop = hWnd; + for (;;) + { + LONG style = NtUserGetWindowLong(hWndTop, GWL_STYLE, FALSE); + if (style & (WS_MINIMIZE | WS_DISABLED)) + { + IntReleaseWindowObject(WindowObject); + return NULL; + } + if (! (style & WS_CHILD)) + { + break; + } + hWndTop = NtUserGetAncestor(hWndTop, GA_PARENT); + } + +#if 0 /* FIXME */ + /* call hooks */ + if (HOOK_CallHooks(WH_CBT, HCBT_SETFOCUS, (WPARAM)hwnd, (LPARAM)previous, TRUE)) + { + IntReleaseWindowObject(WindowObject); + return NULL; + } +#endif + + /* activate hWndTop if needed. */ + if (hWndTop != NtUserGetActiveWindow()) + { +#ifdef TODO + if (! set_active_window(hWndTop, NULL, FALSE, FALSE)) + { + return NULL; + } +#endif +#if 0 /* FIXME */ + if (! NtUserIsWindow(hWnd)) + { + /* Abort if window destroyed */ + return NULL; + } +#endif + } + } +#if 0 /* FIXME */ else { - (PUSER_MESSAGE_QUEUE)DesktopObject->ActiveMessageQueue = NULL; + /* call hooks */ + if (HOOK_CallHooks(WH_CBT, HCBT_SETFOCUS, (WPARAM)hwnd, (LPARAM)previous, TRUE)) + { + IntReleaseWindowObject(WindowObject); + return NULL; + } + } +#endif + + hWndOldFocus = set_focus_window(hWnd, WindowObject, hWndOldFocus); + if (WindowObject != NULL) + { + IntReleaseWindowObject(WindowObject); } DPRINT("hWndOldFocus = 0x%x\n", hWndOldFocus); @@ -1517,7 +1629,7 @@ NtUserDestroyWindow(HWND Wnd) { Parent = NULL; } - IntSetFocusWindow(Parent); + IntSetFocusWindow(Parent); } /* Call hooks */ @@ -1553,12 +1665,14 @@ NtUserDestroyWindow(HWND Wnd) /* Hide the window */ if (! WinPosShowWindow(Wnd, SW_HIDE )) { -#if 0 /* FIXME */ - if (hwnd == GetActiveWindow()) + if (Wnd == NtUserGetActiveWindow()) { - WINPOS_ActivateOtherWindow( hwnd ); + PWINDOW_OBJECT ActiveWindow = IntGetWindowObject(Wnd); + if (NULL != ActiveWindow) + { + WinPosActivateOtherWindow(ActiveWindow); + } } -#endif } #if 0 /* FIXME */ diff --git a/reactos/subsys/win32k/ntuser/winpos.c b/reactos/subsys/win32k/ntuser/winpos.c index cb2185dfa87..93aa6887ccd 100644 --- a/reactos/subsys/win32k/ntuser/winpos.c +++ b/reactos/subsys/win32k/ntuser/winpos.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: winpos.c,v 1.35 2003/10/21 19:40:05 weiden Exp $ +/* $Id: winpos.c,v 1.36 2003/10/23 09:07:54 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -95,10 +95,82 @@ NtUserGetClientOrigin(HWND hWnd, LPPOINT Point) return(TRUE); } -BOOL FASTCALL +/******************************************************************* + * can_activate_window + * + * Check if we can activate the specified window. + */ +static BOOL FASTCALL +can_activate_window(HWND hwnd) +{ + LONG style; + + if (! hwnd) + { + return FALSE; + } + style = NtUserGetWindowLong(hwnd, GWL_STYLE, FALSE); + if (! (style & WS_VISIBLE)) + { + return FALSE; + } + if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) + { + return FALSE; + } + return ! (style & WS_DISABLED); +} + +/******************************************************************* + * WinPosActivateOtherWindow + * + * Activates window other than pWnd. + */ +void FASTCALL WinPosActivateOtherWindow(PWINDOW_OBJECT Window) { - return FALSE; + HWND hwndTo; +#if 0 + HWND fg; +#endif + + if ((NtUserGetWindowLong(Window->Self, GWL_STYLE, FALSE) & WS_POPUP) + && (hwndTo = NtUserGetWindow(Window->Self, GW_OWNER))) + { + hwndTo = NtUserGetAncestor(hwndTo, GA_ROOT); + if (can_activate_window(hwndTo)) goto done; + } + + hwndTo = Window->Self; + for (;;) + { + if (!(hwndTo = NtUserGetWindow(hwndTo, GW_HWNDNEXT))) + { + break; + } + if (can_activate_window(hwndTo)) + { + break; + } + } + +done: +#ifdef TODO + fg = NtUserGetForegroundWindow(); +/* TRACE("win = %p fg = %p\n", hwndTo, fg); */ + if (! fg || (hwnd == fg)) + { + if (NtUserSetForegroundWindow(hwndTo)) + { + return; + } + } +#endif + + if (! NtUserSetActiveWindow(hwndTo)) + { + NtUserSetActiveWindow(NULL); + } } POINT STATIC FASTCALL