Author: jimtabor Date: Sat Dec 10 06:08:29 2011 New Revision: 54634
URL: http://svn.reactos.org/svn/reactos?rev=54634&view=rev Log: [Win32k] - Fixups to set focus and show window support, added notes. Add is window visible. Fix a binary bit return, 1 is TRUE. Fix get client rectangle. Minor fixups.
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/focus.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/focus.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/focus.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/focus.c [iso-8859-1] Sat Dec 10 06:08:29 2011 @@ -8,6 +8,9 @@
#include <win32k.h> DBG_DEFAULT_CHANNEL(UserFocus); + +PUSER_MESSAGE_QUEUE gpqForeground = NULL; +PUSER_MESSAGE_QUEUE gpqForegroundPrev = NULL;
HWND FASTCALL IntGetCaptureWindow(VOID) @@ -190,9 +193,24 @@ return NULL; }
+/* + MSDN: + The system restricts which processes can set the foreground window. A process + can set the foreground window only if one of the following conditions is true: + + * The process is the foreground process. + * The process was started by the foreground process. + * The process received the last input event. + * There is no foreground process. + * The foreground process is being debugged. + * The foreground is not locked (see LockSetForegroundWindow). + * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo). + * No menus are active. +*/ static BOOL FASTCALL co_IntSetForegroundAndFocusWindow(PWND Wnd, PWND FocusWindow, BOOL MouseActivate) { + CBTACTIVATESTRUCT cbt; HWND hWnd = Wnd->head.h; HWND hWndPrev = NULL; HWND hWndFocus = FocusWindow->head.h; @@ -212,7 +230,7 @@ if (0 == (Wnd->style & WS_VISIBLE) && Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess) { - TRACE("Failed - Invisible\n"); + ERR("Failed - Invisible\n"); return FALSE; }
@@ -229,7 +247,14 @@ return TRUE; }
- /* FIXME: Call hooks. */ + /* call CBT hook chain */ + cbt.fMouse = MouseActivate; + cbt.hWndActive = hWndPrev; + if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) + { + ERR("IntSetForegroundAndFocusWindow WH_CBT Call Hook return!\n"); + return 0; + }
co_IntSendDeactivateMessages(hWndPrev, hWnd); co_IntSendKillFocusMessages(hWndFocusPrev, hWndFocus); @@ -326,12 +351,11 @@ ASSERT(ThreadQueue != 0);
if (Wnd != 0) - { - if ((!(Wnd->style & WS_VISIBLE) && - Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess) || - (Wnd->style & (WS_POPUP | WS_CHILD)) == WS_CHILD) - { - return ThreadQueue ? 0 : ThreadQueue->ActiveWindow; + { + if ((Wnd->style & (WS_POPUP | WS_CHILD)) == WS_CHILD) + { + /* Windows doesn't seem to return an error here */ + return ThreadQueue->ActiveWindow; } hWnd = Wnd->head.h; } @@ -350,9 +374,11 @@ ERR("SetActiveWindow WH_CBT Call Hook return!\n"); return 0; } + + co_IntSendDeactivateMessages(hWndPrev, hWnd); + ThreadQueue->ActiveWindow = hWnd;
- co_IntSendDeactivateMessages(hWndPrev, hWnd); co_IntSendActivateMessages(hWndPrev, hWnd, FALSE);
/* FIXME */ @@ -360,11 +386,11 @@ return hWndPrev; }
-static HWND FASTCALL -co_IntSetFocusWindow(PWND Window OPTIONAL) +co_UserSetFocus(PWND Window) { HWND hWndPrev = 0; + PWND pwndTop; PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue;
@@ -381,14 +407,36 @@ { if (hWndPrev == Window->head.h) { - return hWndPrev; + return hWndPrev; /* nothing to do */ + } + + /* Check if we can set the focus to this window */ + for (pwndTop = Window; pwndTop != NULL; pwndTop = pwndTop->spwndParent ) + { + if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0; + if ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break; }
if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) { - ERR("SetFocusWindow 1 WH_CBT Call Hook return!\n"); + ERR("SetFocus 1 WH_CBT Call Hook return!\n"); return 0; } + + /* activate pwndTop if needed. */ + if (pwndTop->head.h != ThreadQueue->ActiveWindow) + { + co_IntSetActiveWindow(pwndTop); + /* Abort if window destroyed */ + if (Window->state2 & WNDS2_INDESTROY) return 0; + /* Do not change focus if the window is no longer active */ + if (pwndTop->head.h != ThreadQueue->ActiveWindow) + { + ERR("SetFocus Top window did not go active!\n"); + return 0; + } + } + ThreadQueue->FocusWindow = Window->head.h; TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h);
@@ -409,10 +457,6 @@ return hWndPrev; }
- -/* - * @implemented - */ HWND FASTCALL UserGetForegroundWindow(VOID) { @@ -421,27 +465,6 @@ ForegroundQueue = IntGetFocusMessageQueue(); return( ForegroundQueue != NULL ? ForegroundQueue->ActiveWindow : 0); } - - -/* - * @implemented - */ -HWND APIENTRY -NtUserGetForegroundWindow(VOID) -{ - DECLARE_RETURN(HWND); - - TRACE("Enter NtUserGetForegroundWindow\n"); - UserEnterExclusive(); - - RETURN( UserGetForegroundWindow()); - -CLEANUP: - TRACE("Leave NtUserGetForegroundWindow, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} -
HWND FASTCALL UserGetActiveWindow(VOID) { @@ -453,57 +476,6 @@ return( ThreadQueue ? ThreadQueue->ActiveWindow : 0); }
- -HWND APIENTRY -NtUserSetActiveWindow(HWND hWnd) -{ - USER_REFERENCE_ENTRY Ref; - DECLARE_RETURN(HWND); - - TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd); - UserEnterExclusive(); - - if (hWnd) - { - PWND Window; - PTHREADINFO pti; - PUSER_MESSAGE_QUEUE ThreadQueue; - HWND hWndPrev; - - if (!(Window = UserGetWindowObject(hWnd))) - { - RETURN( 0); - } - - pti = PsGetCurrentThreadWin32Thread(); - ThreadQueue = pti->MessageQueue; - - if (Window->head.pti->MessageQueue != ThreadQueue) - { - EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); - RETURN( 0); - } - - UserRefObjectCo(Window, &Ref); - hWndPrev = co_IntSetActiveWindow(Window); - UserDerefObjectCo(Window); - - RETURN( hWndPrev); - } - else - { - RETURN( co_IntSetActiveWindow(0)); - } - -CLEANUP: - TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - -/* - * @implemented - */ HWND APIENTRY IntGetCapture(VOID) { @@ -521,7 +493,6 @@ TRACE("Leave IntGetCapture, ret=%i\n",_ret_); END_CLEANUP; } -
HWND FASTCALL co_UserSetCapture(HWND hWnd) @@ -610,6 +581,72 @@ * @implemented */ HWND APIENTRY +NtUserGetForegroundWindow(VOID) +{ + DECLARE_RETURN(HWND); + + TRACE("Enter NtUserGetForegroundWindow\n"); + UserEnterExclusive(); + + RETURN( UserGetForegroundWindow()); + +CLEANUP: + TRACE("Leave NtUserGetForegroundWindow, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} + +HWND APIENTRY +NtUserSetActiveWindow(HWND hWnd) +{ + USER_REFERENCE_ENTRY Ref; + DECLARE_RETURN(HWND); + + TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd); + UserEnterExclusive(); + + if (hWnd) + { + PWND Window; + PTHREADINFO pti; + PUSER_MESSAGE_QUEUE ThreadQueue; + HWND hWndPrev; + + if (!(Window = UserGetWindowObject(hWnd))) + { + RETURN( 0); + } + + pti = PsGetCurrentThreadWin32Thread(); + ThreadQueue = pti->MessageQueue; + + if (Window->head.pti->MessageQueue != ThreadQueue) + { + EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); + RETURN( 0); + } + + UserRefObjectCo(Window, &Ref); + hWndPrev = co_IntSetActiveWindow(Window); + UserDerefObjectCo(Window); + + RETURN( hWndPrev); + } + else + { + RETURN( co_IntSetActiveWindow(0)); + } + +CLEANUP: + TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} + +/* + * @implemented + */ +HWND APIENTRY NtUserSetCapture(HWND hWnd) { DECLARE_RETURN(HWND); @@ -624,55 +661,6 @@ UserLeave(); END_CLEANUP; } - - - -HWND FASTCALL co_UserSetFocus(PWND Wnd OPTIONAL) -{ - if (Wnd) - { - PTHREADINFO pti; - PUSER_MESSAGE_QUEUE ThreadQueue; - HWND hWndPrev; - PWND TopWnd; - USER_REFERENCE_ENTRY Ref; - - ASSERT_REFS_CO(Wnd); - - pti = PsGetCurrentThreadWin32Thread(); - ThreadQueue = pti->MessageQueue; - - if (Wnd->style & (WS_MINIMIZE | WS_DISABLED)) - { - return( (ThreadQueue ? ThreadQueue->FocusWindow : 0)); - } - - if (Wnd->head.pti->MessageQueue != ThreadQueue) - { - EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); - return( 0); - } - - TopWnd = UserGetAncestor(Wnd, GA_ROOT); - if (TopWnd && TopWnd->head.h != UserGetActiveWindow()) - { -// PWND WndTops = UserGetWindowObject(hWndTop); - UserRefObjectCo(TopWnd, &Ref); - co_IntSetActiveWindow(TopWnd); - UserDerefObjectCo(TopWnd); - } - - hWndPrev = co_IntSetFocusWindow(Wnd); - - return( hWndPrev); - } - else - { - return( co_IntSetFocusWindow(NULL)); - } - -} -
/* * @implemented
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] Sat Dec 10 06:08:29 2011 @@ -108,6 +108,25 @@ return TRUE; }
+BOOL FASTCALL +IntIsWindowVisible(PWND Wnd) +{ + BOOL Ret = TRUE; + do + { + if (!(Wnd->style & WS_VISIBLE)) + { + Ret = FALSE; + break; + } + if (Wnd->spwndParent != NULL) + Wnd = Wnd->spwndParent; + else + break; + } + while (Wnd != NULL); + return Ret; +}
PWND FASTCALL IntGetParent(PWND Wnd) @@ -138,7 +157,7 @@ }
/* check if updating is needed */ - bIsDisabled = (pWnd->style & WS_DISABLED); + bIsDisabled = !!(pWnd->style & WS_DISABLED); Update = bIsDisabled;
if (bEnable) @@ -758,8 +777,6 @@ } }
- - /*! * Internal function. * Returns client window rectangle relative to the upper-left corner of client area. @@ -767,16 +784,33 @@ * \note Does not check the validity of the parameters */ VOID FASTCALL -IntGetClientRect(PWND Window, RECTL *Rect) -{ - ASSERT( Window ); +IntGetClientRect(PWND Wnd, RECTL *Rect) +{ + ASSERT( Wnd ); ASSERT( Rect ); - - Rect->left = Rect->top = 0; - Rect->right = Window->rcClient.right - Window->rcClient.left; - Rect->bottom = Window->rcClient.bottom - Window->rcClient.top; -} - + if (Wnd->style & WS_MINIMIZED) + { + Rect->left = Rect->top = 0; + Rect->right = UserGetSystemMetrics(SM_CXMINIMIZED); + Rect->bottom = UserGetSystemMetrics(SM_CYMINIMIZED); + return; + } + if ( Wnd != UserGetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP ) + { + *Rect = Wnd->rcClient; + RECTL_vOffsetRect(Rect, -Wnd->rcClient.left, -Wnd->rcClient.top); + } + else + { + Rect->left = Rect->top = 0; + Rect->right = Wnd->rcClient.right; + Rect->bottom = Wnd->rcClient.bottom; + /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics. + Rect->right = UserGetSystemMetrics(SM_CXSCREEN); + Rect->bottom = UserGetSystemMetrics(SM_CYSCREEN); + */ + } +}
PMENU_OBJECT FASTCALL IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) @@ -1125,6 +1159,7 @@ * FIXME: a WM_MOVE is also generated (in the DefWindowProc handler * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */ + if (WasVisible) co_WinPosShowWindow(Wnd, SW_SHOWNORMAL);
return WndOldParent; } @@ -1637,13 +1672,15 @@ pWnd->spwndOwner = OwnerWindow; pWnd->fnid = 0; pWnd->hWndLastActive = hWnd; - pWnd->state2 |= WNDS2_WIN40COMPAT; + pWnd->state2 |= WNDS2_WIN40COMPAT; // FIXME!!! pWnd->pcls = Class; pWnd->hModule = Cs->hInstance; pWnd->style = Cs->style & ~WS_VISIBLE; pWnd->ExStyle = Cs->dwExStyle; pWnd->cbwndExtra = pWnd->pcls->cbwndExtra; pWnd->pActCtx = acbiBuffer; + pWnd->InternalPos.MaxPos.x = pWnd->InternalPos.MaxPos.y = -1; + pWnd->InternalPos.IconPos.x = pWnd->InternalPos.IconPos.y = -1;
IntReferenceMessageQueue(pWnd->head.pti->MessageQueue); if (pWnd->spwndParent != NULL && Cs->hwndParent != 0) @@ -1759,15 +1796,22 @@ if (!(pWnd->style & WS_POPUP)) { pWnd->style |= WS_CAPTION; - pWnd->state |= WNDS_SENDSIZEMOVEMSGS; - } - } + } + } + + /* + * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so + * why does the user get to set it? + */
if ((pWnd->ExStyle & WS_EX_DLGMODALFRAME) || (pWnd->style & (WS_DLGFRAME | WS_THICKFRAME))) pWnd->ExStyle |= WS_EX_WINDOWEDGE; else pWnd->ExStyle &= ~WS_EX_WINDOWEDGE; + + if (!(pWnd->style & (WS_CHILD | WS_POPUP))) + pWnd->state |= WNDS_SENDSIZEMOVEMSGS;
/* create system menu */ if((Cs->style & WS_SYSMENU) )//&& (dwStyle & WS_CAPTION) == WS_CAPTION) @@ -3670,11 +3714,11 @@ break;
case QUERY_WINDOW_ACTIVE: - Result = (DWORD)UserGetActiveWindow(); + Result = (DWORD)pWnd->head.pti->MessageQueue->ActiveWindow; break;
case QUERY_WINDOW_FOCUS: - Result = (DWORD)IntGetFocusWindow(); + Result = (DWORD)pWnd->head.pti->MessageQueue->FocusWindow; break;
case QUERY_WINDOW_ISHUNG:
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c [iso-8859-1] Sat Dec 10 06:08:29 2011 @@ -22,6 +22,8 @@ (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER) #define SWP_AGG_STATUSFLAGS \ (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW) + +#define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
/* FUNCTIONS *****************************************************************/
@@ -325,6 +327,7 @@ return 0; } Wnd->style &= ~WS_MAXIMIZE; + Wnd->state2 &= ~WNDS2_MAXIMIZEBUTTONDOWN; *NewPos = Wnd->InternalPos.NormalRect; NewPos->right -= NewPos->left; NewPos->bottom -= NewPos->top; @@ -452,9 +455,9 @@ MinMax.ptMaxPosition.x = -xinc; MinMax.ptMaxPosition.y = -yinc;
- //if (!EMPTYPOINT(win->max_pos)) MinMax.ptMaxPosition = win->max_pos; - - co_IntSendMessage(Window->head.h, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax); + if (!EMPTYPOINT(Window->InternalPos.MaxPos)) MinMax.ptMaxPosition = Window->InternalPos.MaxPos; + + co_IntSendMessage(Window->head.h, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax);
/* if the app didn't change the values, adapt them for the current monitor */ if ((monitor = IntGetPrimaryMonitor())) @@ -1374,11 +1377,13 @@ UINT Swp = 0; RECTL NewPos; BOOLEAN ShowFlag; + LONG style; // HRGN VisibleRgn;
ASSERT_REFS_CO(Wnd);
WasVisible = (Wnd->style & WS_VISIBLE) != 0; + style = Wnd->style;
switch (Cmd) { @@ -1403,7 +1408,7 @@ case SW_MINIMIZE: { Swp |= SWP_NOACTIVATE; - if (!(Wnd->style & WS_MINIMIZE)) + if (!(style & WS_MINIMIZE)) { Swp |= co_WinPosMinMaximize(Wnd, SW_MINIMIZE, &NewPos) | SWP_FRAMECHANGED; @@ -1422,7 +1427,7 @@ case SW_SHOWMAXIMIZED: { Swp |= SWP_SHOWWINDOW; - if (!(Wnd->style & WS_MAXIMIZE)) + if (!(style & WS_MAXIMIZE)) { Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos) | SWP_FRAMECHANGED; @@ -1445,9 +1450,11 @@ if (WasVisible) return(TRUE); // Nothing to do! Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; /* Don't activate the topmost window. */ + if (style & WS_CHILD) Swp |= SWP_NOACTIVATE | SWP_NOZORDER; break;
case SW_SHOWNOACTIVATE: + Wnd->state2 &= ~WNDS2_MAXIMIZEBUTTONDOWN; //Swp |= SWP_NOZORDER; Swp |= SWP_NOACTIVATE | SWP_NOZORDER; /* Fall through. */ @@ -1455,7 +1462,7 @@ case SW_SHOWDEFAULT: case SW_RESTORE: Swp |= SWP_SHOWWINDOW; - if (Wnd->style & (WS_MINIMIZE | WS_MAXIMIZE)) + if (style & (WS_MINIMIZE | WS_MAXIMIZE)) { Swp |= co_WinPosMinMaximize(Wnd, SW_RESTORE, &NewPos) | SWP_FRAMECHANGED; @@ -1476,6 +1483,8 @@ if (ShowFlag != WasVisible) { co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0); + if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) + co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0); }
/* We can't activate a child window */ @@ -1484,7 +1493,15 @@ { Swp |= SWP_NOACTIVATE | SWP_NOZORDER; } - +#if 0 // Explorer issues with common controls. Someone does not know how CS_SAVEBITS works. + if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD && + Wnd->pcls->style & CS_SAVEBITS && + ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL))) + { + co_IntSetActiveWindow(Wnd); + Swp |= SWP_NOACTIVATE | SWP_NOZORDER; + } +#endif co_WinPosSetWindowPos(Wnd, 0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP, NewPos.left, NewPos.top, NewPos.right, NewPos.bottom, LOWORD(Swp)); @@ -1508,8 +1525,10 @@ ThreadFocusWindow = UserGetWindowObject(IntGetThreadFocusWindow());
/* Revert focus to parent */ - if (ThreadFocusWindow && (Wnd == ThreadFocusWindow || +/* if (ThreadFocusWindow && (Wnd == ThreadFocusWindow || IntIsChildWindow(Wnd, ThreadFocusWindow))) +*/ + if (Wnd == ThreadFocusWindow) { //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent... co_UserSetFocus(Wnd->spwndParent); @@ -1524,13 +1543,9 @@ co_WinPosSendSizeMove(Wnd); }
- /* Activate the window if activation is not requested and the window is not minimized */ - /* - if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->style & WS_MINIMIZE)) - { - WinPosChangeActiveWindow(Wnd, FALSE); - } - */ + /* if previous state was minimized Windows sets focus to the window */ + if (style & WS_MINIMIZE) co_UserSetFocus(Wnd); + return(WasVisible); }
@@ -1744,8 +1759,8 @@ winpos->pos.cx, winpos->pos.cy, winpos->pos.flags);
pwnd = UserGetWindowObject(winpos->pos.hwnd); - if(!pwnd) - continue; + if (!pwnd) + continue;
UserRefObjectCo(pwnd, &Ref);