diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index 4d98324b285..5813404c56a 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -611,7 +611,6 @@ typedef struct _WND LARGE_UNICODE_STRING strName; /* Size of the extra data associated with the window. */ ULONG cbwndExtra; - HWND hWndLastActive; struct _WND *spwndLastActive; //HIMC hImc; // Input context associated with this window. LONG dwUserData; diff --git a/reactos/win32ss/user/ntuser/desktop.c b/reactos/win32ss/user/ntuser/desktop.c index c44a1fc4264..d4459827958 100644 --- a/reactos/win32ss/user/ntuser/desktop.c +++ b/reactos/win32ss/user/ntuser/desktop.c @@ -462,7 +462,10 @@ IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue) { (void)InterlockedExchangePointer((PVOID*)&Old->Desktop, 0); IntDereferenceMessageQueue(Old); + gpqForegroundPrev = Old; } + // Only one Q can have active foreground even when there are more than one desktop. + if (NewQueue) gpqForeground = pdo->ActiveMessageQueue; } HWND FASTCALL IntGetDesktopWindow(VOID) @@ -485,7 +488,7 @@ PWND FASTCALL UserGetDesktopWindow(VOID) TRACE("No active desktop\n"); return NULL; } - + // return pdo->pDeskInfo->spwnd; return UserGetWindowObject(pdo->DesktopWindow); } @@ -501,6 +504,18 @@ HWND FASTCALL IntGetMessageWindow(VOID) return pdo->spwndMessage->head.h; } +PWND FASTCALL UserGetMessageWindow(VOID) +{ + PDESKTOP pdo = IntGetActiveDesktop(); + + if (!pdo) + { + TRACE("No active desktop\n"); + return NULL; + } + return pdo->spwndMessage; +} + HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID) { PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); @@ -558,6 +573,7 @@ UserRedrawDesktop() NTSTATUS FASTCALL co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height) { +//#if 0 CSR_API_MESSAGE Request; Request.Type = MAKE_CSR_API(SHOW_DESKTOP, CSR_GUI); @@ -566,21 +582,27 @@ co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height) Request.Data.ShowDesktopRequest.Height = Height; return co_CsrNotify(&Request); +//#endif +#if 0 // DESKTOPWNDPROC + PWND Window; + + Window = IntGetWindowObject(Desktop->DesktopWindow); + + if (!Window) + { + ERR("No Desktop window.\n"); + return STATUS_UNSUCCESSFUL; + } + co_WinPosSetWindowPos(Window, NULL, 0, 0, Width, Height, SWP_NOACTIVATE|SWP_NOZORDER|SWP_SHOWWINDOW); + + co_UserRedrawWindow( Window, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN); + return STATUS_SUCCESS; +#endif } NTSTATUS FASTCALL IntHideDesktop(PDESKTOP Desktop) { -#if 0 - CSRSS_API_REQUEST Request; - CSRSS_API_REPLY Reply; - - Request.Type = CSRSS_HIDE_DESKTOP; - Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow; - - return NotifyCsrss(&Request, &Reply); -#else - PWND DesktopWnd; DesktopWnd = IntGetWindowObject(Desktop->DesktopWindow); @@ -591,12 +613,8 @@ IntHideDesktop(PDESKTOP Desktop) DesktopWnd->style &= ~WS_VISIBLE; return STATUS_SUCCESS; -#endif } - - - static HWND* FASTCALL UserBuildShellHookHwndList(PDESKTOP Desktop) @@ -637,14 +655,6 @@ VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam) if (!gpsi->uiShellMsg) { - - /* Too bad, this doesn't work. */ -#if 0 - UNICODE_STRING Str; - RtlInitUnicodeString(&Str, L"SHELLHOOK"); - gpsi->uiShellMsg = UserRegisterWindowMessage(&Str); -#endif - gpsi->uiShellMsg = IntAddAtom(L"SHELLHOOK"); TRACE("MsgType = %x\n", gpsi->uiShellMsg); @@ -745,6 +755,216 @@ IntFreeDesktopHeap(IN OUT PDESKTOP Desktop) Desktop->hsectionDesktop = NULL; } } + +BOOL FASTCALL +IntPaintDesktop(HDC hDC) +{ + RECTL Rect; + HBRUSH DesktopBrush, PreviousBrush; + HWND hWndDesktop; + BOOL doPatBlt = TRUE; + PWND WndDesktop; + static WCHAR s_wszSafeMode[] = L"Safe Mode"; + int len; + COLORREF color_old; + UINT align_old; + int mode_old; + + GdiGetClipBox(hDC, &Rect); + + hWndDesktop = IntGetDesktopWindow(); // rpdesk->DesktopWindow; + + WndDesktop = UserGetWindowObject(hWndDesktop); // rpdesk->pDeskInfo->spwnd; + if (!WndDesktop) + { + return FALSE; + } + + if (!UserGetSystemMetrics(SM_CLEANBOOT)) + { + DesktopBrush = (HBRUSH)WndDesktop->pcls->hbrBackground; + + /* + * Paint desktop background + */ + if (gspv.hbmWallpaper != NULL) + { + SIZE sz; + int x, y; + HDC hWallpaperDC; + + sz.cx = WndDesktop->rcWindow.right - WndDesktop->rcWindow.left; + sz.cy = WndDesktop->rcWindow.bottom - WndDesktop->rcWindow.top; + + if (gspv.WallpaperMode == wmStretch || + gspv.WallpaperMode == wmTile) + { + x = 0; + y = 0; + } + else + { + /* Find the upper left corner, can be negtive if the bitmap is bigger then the screen */ + x = (sz.cx / 2) - (gspv.cxWallpaper / 2); + y = (sz.cy / 2) - (gspv.cyWallpaper / 2); + } + + hWallpaperDC = NtGdiCreateCompatibleDC(hDC); + if(hWallpaperDC != NULL) + { + HBITMAP hOldBitmap; + + /* Fill in the area that the bitmap is not going to cover */ + if (x > 0 || y > 0) + { + /* FIXME: Clip out the bitmap + can be replaced with "NtGdiPatBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, PATCOPY | DSTINVERT);" + once we support DSTINVERT */ + PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush); + NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY); + NtGdiSelectBrush(hDC, PreviousBrush); + } + + /*Do not fill the background after it is painted no matter the size of the picture */ + doPatBlt = FALSE; + + hOldBitmap = NtGdiSelectBitmap(hWallpaperDC, gspv.hbmWallpaper); + + if (gspv.WallpaperMode == wmStretch) + { + if(Rect.right && Rect.bottom) + NtGdiStretchBlt(hDC, + x, + y, + sz.cx, + sz.cy, + hWallpaperDC, + 0, + 0, + gspv.cxWallpaper, + gspv.cyWallpaper, + SRCCOPY, + 0); + + } + else if (gspv.WallpaperMode == wmTile) + { + /* Paint the bitmap across the screen then down */ + for(y = 0; y < Rect.bottom; y += gspv.cyWallpaper) + { + for(x = 0; x < Rect.right; x += gspv.cxWallpaper) + { + NtGdiBitBlt(hDC, + x, + y, + gspv.cxWallpaper, + gspv.cyWallpaper, + hWallpaperDC, + 0, + 0, + SRCCOPY, + 0, + 0); + } + } + } + else + { + NtGdiBitBlt(hDC, + x, + y, + gspv.cxWallpaper, + gspv.cyWallpaper, + hWallpaperDC, + 0, + 0, + SRCCOPY, + 0, + 0); + } + NtGdiSelectBitmap(hWallpaperDC, hOldBitmap); + NtGdiDeleteObjectApp(hWallpaperDC); + } + } + } + else + { + /* Black desktop background in Safe Mode */ + DesktopBrush = StockObjects[BLACK_BRUSH]; + } + + /* Back ground is set to none, clear the screen */ + if (doPatBlt) + { + PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush); + NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY); + NtGdiSelectBrush(hDC, PreviousBrush); + } + + /* + * Display system version on the desktop background + */ + + if (g_PaintDesktopVersion||UserGetSystemMetrics(SM_CLEANBOOT)) + { + static WCHAR s_wszVersion[256] = {0}; + RECTL rect; + + if (*s_wszVersion) + { + len = wcslen(s_wszVersion); + } + else + { + len = GetSystemVersionString(s_wszVersion); + } + + if (len) + { + if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0)) + { + rect.right = UserGetSystemMetrics(SM_CXSCREEN); + rect.bottom = UserGetSystemMetrics(SM_CYSCREEN); + } + + color_old = IntGdiSetTextColor(hDC, RGB(255,255,255)); + align_old = IntGdiSetTextAlign(hDC, TA_RIGHT); + mode_old = IntGdiSetBkMode(hDC, TRANSPARENT); + + if(!UserGetSystemMetrics(SM_CLEANBOOT)) + { + GreExtTextOutW(hDC, rect.right-16, rect.bottom-48, 0, NULL, s_wszVersion, len, NULL, 0); + } + else + { + /* Safe Mode */ + /* Version information text in top center */ + IntGdiSetTextAlign(hDC, TA_CENTER|TA_TOP); + GreExtTextOutW(hDC, (rect.right+rect.left)/2, rect.top, 0, NULL, s_wszVersion, len, NULL, 0); + /* Safe Mode text in corners */ + len = wcslen(s_wszSafeMode); + IntGdiSetTextAlign(hDC, TA_RIGHT|TA_TOP); + GreExtTextOutW(hDC, rect.right, rect.top, 0, NULL, s_wszSafeMode, len, NULL, 0); + IntGdiSetTextAlign(hDC, TA_RIGHT|TA_BASELINE); + GreExtTextOutW(hDC, rect.right, rect.bottom, 0, NULL, s_wszSafeMode, len, NULL, 0); + IntGdiSetTextAlign(hDC, TA_LEFT|TA_TOP); + GreExtTextOutW(hDC, rect.left, rect.top, 0, NULL, s_wszSafeMode, len, NULL, 0); + IntGdiSetTextAlign(hDC, TA_LEFT|TA_BASELINE); + GreExtTextOutW(hDC, rect.left, rect.bottom, 0, NULL, s_wszSafeMode, len, NULL, 0); + + } + + + IntGdiSetBkMode(hDC, mode_old); + IntGdiSetTextAlign(hDC, align_old); + IntGdiSetTextColor(hDC, color_old); + } + } + + return TRUE; +} + + /* SYSCALLS *******************************************************************/ /* @@ -911,15 +1131,15 @@ NtUserCreateDesktop( /* Initialize some local (to win32k) desktop state. */ InitializeListHead(&DesktopObject->PtiList); DesktopObject->ActiveMessageQueue = NULL; + /* Setup Global Hooks. */ for (i = 0; i < NB_HOOKS; i++) { InitializeListHead(&DesktopObject->pDeskInfo->aphkStart[i]); } - - +//#if 0 /* - * Create a handle for CSRSS and notify CSRSS for Creating Desktop Window. + * Create a handle for CSRSS and notify CSRSS for Creating Desktop Background Window. */ Request.Type = MAKE_CSR_API(CREATE_DESKTOP, CSR_GUI); Status = CsrInsertObject(Desktop, @@ -942,10 +1162,23 @@ NtUserCreateDesktop( SetLastNtError(Status); RETURN( NULL); } -#if 0 // Turn on when server side proc is ready. +//#endif + if (!ptiCurrent->rpdesk) IntSetThreadDesktop(Desktop,FALSE); + + /* + Based on wine/server/window.c in get_desktop_window. + */ + +#if 0 // DESKTOPWNDPROC from Revision 6908 Dedicated to GvG! + // Turn on when server side proc is ready. // // Create desktop window. // + /* + Currently this works but it hangs in + co_IntShowDesktop->co_UserRedrawWindow->co_IntPaintWindows->co_IntSendMessage + Commenting out co_UserRedrawWindow will allow it to run with gui issues. + */ ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_DESKTOP]))); ClassName.Length = 0; RtlZeroMemory(&WindowName, sizeof(WindowName)); @@ -956,27 +1189,24 @@ NtUserCreateDesktop( Cs.cx = UserGetSystemMetrics(SM_CXVIRTUALSCREEN); Cs.cy = UserGetSystemMetrics(SM_CYVIRTUALSCREEN); Cs.style = WS_POPUP|WS_CLIPCHILDREN; - Cs.hInstance = hModClient; // Experimental mode... Move csr stuff to User32. hModuleWin; // Server side winproc! + Cs.hInstance = hModClient; // Experimental mode... hModuleWin; // Server side winproc! Cs.lpszName = (LPCWSTR) &WindowName; Cs.lpszClass = (LPCWSTR) &ClassName; - pWndDesktop = co_UserCreateWindowEx(&Cs, &ClassName, &WindowName, NULL); + pWnd = co_UserCreateWindowEx(&Cs, &ClassName, &WindowName, NULL); if (!pWnd) { ERR("Failed to create Desktop window handle\n"); } else - { - DesktopObject->pDeskInfo->spwnd = pWndDesktop; + { // Should be set in window.c, Justin Case, + if (!DesktopObject->DesktopWindow) + { + DesktopObject->pDeskInfo->spwnd = pWnd; + DesktopObject->DesktopWindow = UserHMGetHandle(pWnd); + } } #endif - - if (!ptiCurrent->rpdesk) IntSetThreadDesktop(Desktop,FALSE); - - /* - Based on wine/server/window.c in get_desktop_window. - */ - ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_HWNDMESSAGE]))); ClassName.Length = 0; RtlZeroMemory(&WindowName, sizeof(WindowName)); @@ -1207,9 +1437,6 @@ CLEANUP: END_CLEANUP; } - - - /* * NtUserPaintDesktop * @@ -1228,221 +1455,15 @@ CLEANUP: BOOL APIENTRY NtUserPaintDesktop(HDC hDC) { - RECTL Rect; - HBRUSH DesktopBrush, PreviousBrush; - HWND hWndDesktop; - BOOL doPatBlt = TRUE; - PWND WndDesktop; - static WCHAR s_wszSafeMode[] = L"Safe Mode"; - int len; - COLORREF color_old; - UINT align_old; - int mode_old; - DECLARE_RETURN(BOOL); - + BOOL Ret; UserEnterExclusive(); TRACE("Enter NtUserPaintDesktop\n"); - - GdiGetClipBox(hDC, &Rect); - - hWndDesktop = IntGetDesktopWindow(); - - WndDesktop = UserGetWindowObject(hWndDesktop); - if (!WndDesktop) - { - RETURN(FALSE); - } - - if (!UserGetSystemMetrics(SM_CLEANBOOT)) - { - DesktopBrush = (HBRUSH)WndDesktop->pcls->hbrBackground; - - /* - * Paint desktop background - */ - if (gspv.hbmWallpaper != NULL) - { - SIZE sz; - int x, y; - HDC hWallpaperDC; - - sz.cx = WndDesktop->rcWindow.right - WndDesktop->rcWindow.left; - sz.cy = WndDesktop->rcWindow.bottom - WndDesktop->rcWindow.top; - - if (gspv.WallpaperMode == wmStretch || - gspv.WallpaperMode == wmTile) - { - x = 0; - y = 0; - } - else - { - /* Find the upper left corner, can be negtive if the bitmap is bigger then the screen */ - x = (sz.cx / 2) - (gspv.cxWallpaper / 2); - y = (sz.cy / 2) - (gspv.cyWallpaper / 2); - } - - hWallpaperDC = NtGdiCreateCompatibleDC(hDC); - if(hWallpaperDC != NULL) - { - HBITMAP hOldBitmap; - - /* Fill in the area that the bitmap is not going to cover */ - if (x > 0 || y > 0) - { - /* FIXME: Clip out the bitmap - can be replaced with "NtGdiPatBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, PATCOPY | DSTINVERT);" - once we support DSTINVERT */ - PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush); - NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY); - NtGdiSelectBrush(hDC, PreviousBrush); - } - - /*Do not fill the background after it is painted no matter the size of the picture */ - doPatBlt = FALSE; - - hOldBitmap = NtGdiSelectBitmap(hWallpaperDC, gspv.hbmWallpaper); - - if (gspv.WallpaperMode == wmStretch) - { - if(Rect.right && Rect.bottom) - NtGdiStretchBlt(hDC, - x, - y, - sz.cx, - sz.cy, - hWallpaperDC, - 0, - 0, - gspv.cxWallpaper, - gspv.cyWallpaper, - SRCCOPY, - 0); - - } - else if (gspv.WallpaperMode == wmTile) - { - /* Paint the bitmap across the screen then down */ - for(y = 0; y < Rect.bottom; y += gspv.cyWallpaper) - { - for(x = 0; x < Rect.right; x += gspv.cxWallpaper) - { - NtGdiBitBlt(hDC, - x, - y, - gspv.cxWallpaper, - gspv.cyWallpaper, - hWallpaperDC, - 0, - 0, - SRCCOPY, - 0, - 0); - } - } - } - else - { - NtGdiBitBlt(hDC, - x, - y, - gspv.cxWallpaper, - gspv.cyWallpaper, - hWallpaperDC, - 0, - 0, - SRCCOPY, - 0, - 0); - } - NtGdiSelectBitmap(hWallpaperDC, hOldBitmap); - NtGdiDeleteObjectApp(hWallpaperDC); - } - } - } - else - { - /* Black desktop background in Safe Mode */ - DesktopBrush = StockObjects[BLACK_BRUSH]; - } - - /* Back ground is set to none, clear the screen */ - if (doPatBlt) - { - PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush); - NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY); - NtGdiSelectBrush(hDC, PreviousBrush); - } - - /* - * Display system version on the desktop background - */ - - if (g_PaintDesktopVersion||UserGetSystemMetrics(SM_CLEANBOOT)) - { - static WCHAR s_wszVersion[256] = {0}; - RECTL rect; - - if (*s_wszVersion) - { - len = wcslen(s_wszVersion); - } - else - { - len = GetSystemVersionString(s_wszVersion); - } - - if (len) - { - if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0)) - { - rect.right = UserGetSystemMetrics(SM_CXSCREEN); - rect.bottom = UserGetSystemMetrics(SM_CYSCREEN); - } - - color_old = IntGdiSetTextColor(hDC, RGB(255,255,255)); - align_old = IntGdiSetTextAlign(hDC, TA_RIGHT); - mode_old = IntGdiSetBkMode(hDC, TRANSPARENT); - - if(!UserGetSystemMetrics(SM_CLEANBOOT)) - { - GreExtTextOutW(hDC, rect.right-16, rect.bottom-48, 0, NULL, s_wszVersion, len, NULL, 0); - } - else - { - /* Safe Mode */ - /* Version information text in top center */ - IntGdiSetTextAlign(hDC, TA_CENTER|TA_TOP); - GreExtTextOutW(hDC, (rect.right+rect.left)/2, rect.top, 0, NULL, s_wszVersion, len, NULL, 0); - /* Safe Mode text in corners */ - len = wcslen(s_wszSafeMode); - IntGdiSetTextAlign(hDC, TA_RIGHT|TA_TOP); - GreExtTextOutW(hDC, rect.right, rect.top, 0, NULL, s_wszSafeMode, len, NULL, 0); - IntGdiSetTextAlign(hDC, TA_RIGHT|TA_BASELINE); - GreExtTextOutW(hDC, rect.right, rect.bottom, 0, NULL, s_wszSafeMode, len, NULL, 0); - IntGdiSetTextAlign(hDC, TA_LEFT|TA_TOP); - GreExtTextOutW(hDC, rect.left, rect.top, 0, NULL, s_wszSafeMode, len, NULL, 0); - IntGdiSetTextAlign(hDC, TA_LEFT|TA_BASELINE); - GreExtTextOutW(hDC, rect.left, rect.bottom, 0, NULL, s_wszSafeMode, len, NULL, 0); - - } - - - IntGdiSetBkMode(hDC, mode_old); - IntGdiSetTextAlign(hDC, align_old); - IntGdiSetTextColor(hDC, color_old); - } - } - - RETURN(TRUE); - -CLEANUP: - TRACE("Leave NtUserPaintDesktop, ret=%i\n",_ret_); + Ret = IntPaintDesktop(hDC); + TRACE("Leave NtUserPaintDesktop, ret=%i\n",Ret); UserLeave(); - END_CLEANUP; + return Ret; } - /* * NtUserSwitchDesktop * @@ -1720,7 +1741,7 @@ IntSetThreadDesktop(IN HDESK hDesktop, HDESK hdeskOld; PTHREADINFO pti; NTSTATUS Status; - PCLIENTTHREADINFO pctiOld, pctiNew; + PCLIENTTHREADINFO pctiOld, pctiNew = NULL; PCLIENTINFO pci; ASSERT(NtCurrentTeb()); diff --git a/reactos/win32ss/user/ntuser/desktop.h b/reactos/win32ss/user/ntuser/desktop.h index 6538ffa5875..e1f10e881d3 100644 --- a/reactos/win32ss/user/ntuser/desktop.h +++ b/reactos/win32ss/user/ntuser/desktop.h @@ -23,7 +23,7 @@ typedef struct _DESKTOP /* ReactOS */ /* Pointer to the active queue. */ - PVOID ActiveMessageQueue; + struct _USER_MESSAGE_QUEUE *ActiveMessageQueue; /* Handle of the desktop window. */ HWND DesktopWindow; /* Thread blocking input */ @@ -158,6 +158,7 @@ HDC FASTCALL UserGetDesktopDC(ULONG,BOOL,BOOL); NULL HWND FASTCALL IntGetMessageWindow(VOID); +PWND FASTCALL UserGetMessageWindow(VOID); static __inline PVOID DesktopHeapAlloc(IN PDESKTOP Desktop, diff --git a/reactos/win32ss/user/ntuser/focus.c b/reactos/win32ss/user/ntuser/focus.c index f0d2f580c46..8529f05dd53 100644 --- a/reactos/win32ss/user/ntuser/focus.c +++ b/reactos/win32ss/user/ntuser/focus.c @@ -11,6 +11,19 @@ DBG_DEFAULT_CHANNEL(UserFocus); PUSER_MESSAGE_QUEUE gpqForeground = NULL; PUSER_MESSAGE_QUEUE gpqForegroundPrev = NULL; +PTHREADINFO gptiForeground = NULL; +PPROCESSINFO gppiLockSFW = NULL; +ULONG guSFWLockCount = 0; // Rule #8, No menus are active. So should be zero. +PTHREADINFO ptiLastInput = NULL; + +/* + Check locking of a process or one or more menus are active. +*/ +BOOL FASTCALL +IsFGLocked(VOID) +{ + return (gppiLockSFW || guSFWLockCount); +} HWND FASTCALL IntGetCaptureWindow(VOID) @@ -19,20 +32,6 @@ IntGetCaptureWindow(VOID) return ForegroundQueue != NULL ? ForegroundQueue->CaptureWindow : 0; } -HWND FASTCALL -UserGetFocusWindow(VOID) -{ - PTHREADINFO pti; - PUSER_MESSAGE_QUEUE ThreadQueue; - - pti = PsGetCurrentThreadWin32Thread(); - ThreadQueue = pti->MessageQueue; - /* Is it a foreground queue? */ - if (!ThreadQueue || ThreadQueue != IntGetFocusMessageQueue()) - return NULL; - return ThreadQueue->FocusWindow; -} - HWND FASTCALL IntGetThreadFocusWindow(VOID) { @@ -43,7 +42,7 @@ IntGetThreadFocusWindow(VOID) ThreadQueue = pti->MessageQueue; if (!ThreadQueue) return NULL; - return ThreadQueue->FocusWindow; + return ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; } VOID FASTCALL @@ -60,11 +59,31 @@ co_IntSendDeactivateMessages(HWND hWndPrev, HWND hWnd) } } +BOOL FASTCALL +co_IntMakeWindowActive(PWND Window) +{ + PWND spwndOwner; + if (Window) + { // Set last active for window and it's owner. + Window->spwndLastActive = Window; + spwndOwner = Window->spwndOwner; + while (spwndOwner) + { + spwndOwner->spwndLastActive = Window; + spwndOwner = spwndOwner->spwndOwner; + } + return TRUE; + } + ERR("MakeWindowActive Failed!\n"); + return FALSE; +} + VOID FASTCALL co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate) { USER_REFERENCE_ENTRY Ref, RefPrev; PWND Window, WindowPrev = NULL; + HANDLE OldTID, NewTID; if ((Window = UserGetWindowObject(hWnd))) { @@ -94,33 +113,32 @@ co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate) } if (Window) - { // Set last active for window and it's owner. - Window->hWndLastActive = hWnd; - if (Window->spwndOwner) - Window->spwndOwner->hWndLastActive = hWnd; + { Window->state |= WNDS_ACTIVEFRAME; + + if (Window->style & WS_MINIMIZE) + { + TRACE("Widow was minimized\n"); + } } if (WindowPrev) WindowPrev->state &= ~WNDS_ACTIVEFRAME; - if (Window && WindowPrev) + OldTID = WindowPrev ? IntGetWndThreadId(WindowPrev) : NULL; + NewTID = Window ? IntGetWndThreadId(Window) : NULL; + + TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID); + + if (OldTID != NewTID) { PWND cWindow; HWND *List, *phWnd; - HANDLE OldTID = IntGetWndThreadId(WindowPrev); - HANDLE NewTID = IntGetWndThreadId(Window); - TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID); - if (Window->style & WS_MINIMIZE) + List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow())); + if (List) { - TRACE("Widow was minimized\n"); - } - - if (OldTID != NewTID) - { - List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow())); - if (List) + if (OldTID) { for (phWnd = List; *phWnd; ++phWnd) { @@ -132,6 +150,9 @@ co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate) co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID); } } + } + if (NewTID) + { for (phWnd = List; *phWnd; ++phWnd) { cWindow = UserGetWindowObject(*phWnd); @@ -141,11 +162,12 @@ co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate) co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID); } } - ExFreePool(List); } + ExFreePool(List); } - UserDerefObjectCo(WindowPrev); // Now allow the previous window to die. } + if (WindowPrev) + UserDerefObjectCo(WindowPrev); // Now allow the previous window to die. UserDerefObjectCo(Window); @@ -175,8 +197,11 @@ co_IntSendSetFocusMessages(HWND hWndPrev, HWND hWnd) if (hWnd) { PWND pWnd = UserGetWindowObject(hWnd); - IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0); - co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0); + if (pWnd) + { + IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0); + co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0); + } } } @@ -202,6 +227,23 @@ IntFindChildWindowToOwner(PWND Root, PWND Owner) return NULL; } +/* + Can the system force foreground from one or more conditions. + */ +BOOL FASTCALL +CanForceFG(PPROCESSINFO ppi) +{ + if (!ptiLastInput || + ptiLastInput->ppi == ppi || + !gptiForeground || + gptiForeground->ppi == ppi || + ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_SETFOREGROUNDALLOWED) || + gppiInputProvider == ppi || + !gpqForeground + ) return TRUE; + return FALSE; +} + /* MSDN: The system restricts which processes can set the foreground window. A process @@ -216,88 +258,83 @@ IntFindChildWindowToOwner(PWND Root, PWND Owner) * 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) +co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate) { - CBTACTIVATESTRUCT cbt; - HWND hWnd = Wnd->head.h; + HWND hWnd = UserHMGetHandle(Wnd); HWND hWndPrev = NULL; - HWND hWndFocus = FocusWindow->head.h; - HWND hWndFocusPrev = NULL; PUSER_MESSAGE_QUEUE PrevForegroundQueue; + PTHREADINFO pti; + BOOL fgRet = FALSE, Ret = FALSE; ASSERT_REFS_CO(Wnd); - TRACE("IntSetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, hWndFocus, MouseActivate ? "TRUE" : "FALSE"); + TRACE("SetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, MouseActivate ? "TRUE" : "FALSE"); - if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) - { - TRACE("Failed - Child\n"); - return FALSE; + PrevForegroundQueue = IntGetFocusMessageQueue(); // Use this active desktop. + pti = PsGetCurrentThreadWin32Thread(); + + if (PrevForegroundQueue) + { // Same Window Q as foreground just do active. + if (Wnd && Wnd->head.pti->MessageQueue == PrevForegroundQueue) + { + if (pti->MessageQueue == PrevForegroundQueue) + { // Same WQ and TQ go active. + Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE); + } + else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) + { // Same WQ and it is active. + Ret = TRUE; + } + else + { // Same WQ as FG but not the same TQ send active. + co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate ); + Ret = TRUE; + } + return Ret; + } + + hWndPrev = PrevForegroundQueue->spwndActive ? UserHMGetHandle(PrevForegroundQueue->spwndActive) : 0; } - if (0 == (Wnd->style & WS_VISIBLE) && - Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess) - { - ERR("Failed - Invisible\n"); - return FALSE; + if ( (( !IsFGLocked() || pti->ppi == gppiInputProvider ) && + ( CanForceFG(pti->ppi) || pti->TIF_flags & (TIF_SYSTEMTHREAD|TIF_CSRSSTHREAD|TIF_ALLOWFOREGROUNDACTIVATE) )) || + pti->ppi == ppiScrnSaver + ) + { + IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue); + gptiForeground = Wnd->head.pti; + fgRet = TRUE; } - PrevForegroundQueue = IntGetFocusMessageQueue(); - if (PrevForegroundQueue != 0) +//// Fix FG Bounce with regedit but breaks test_SFW todos + if (hWndPrev != hWnd ) { - hWndPrev = PrevForegroundQueue->ActiveWindow; - hWndFocusPrev = PrevForegroundQueue->FocusWindow; + if (PrevForegroundQueue && + fgRet && + Wnd->head.pti->MessageQueue != PrevForegroundQueue && + PrevForegroundQueue->spwndActive) + { + co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 ); + } } - if (hWndPrev == hWnd) + if (pti->MessageQueue == Wnd->head.pti->MessageQueue) { - TRACE("Failed - Same\n"); - return TRUE; + Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE); + } + else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) + { + Ret = TRUE; + } + else + { + co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate ); + Ret = TRUE; } - /* 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); - - - IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue); - - if (Wnd->head.pti->MessageQueue) - { - Wnd->head.pti->MessageQueue->ActiveWindow = hWnd; - } - - if (FocusWindow->head.pti->MessageQueue) - { - FocusWindow->head.pti->MessageQueue->FocusWindow = hWndFocus; - } - - if (PrevForegroundQueue != Wnd->head.pti->MessageQueue) - { - /* FIXME: Send WM_ACTIVATEAPP to all thread windows. */ - } - - co_IntSendSetFocusMessages(hWndFocusPrev, hWndFocus); - co_IntSendActivateMessages(hWndPrev, hWnd, MouseActivate); - - return TRUE; -} - -BOOL FASTCALL -co_IntSetForegroundWindow(PWND Window) // FIXME: Can Window be NULL?? -{ - /*if (Window)*/ ASSERT_REFS_CO(Window); - - return co_IntSetForegroundAndFocusWindow(Window, Window, FALSE); + return Ret && fgRet; } BOOL FASTCALL @@ -309,15 +346,15 @@ co_IntMouseActivateWindow(PWND Wnd) ASSERT_REFS_CO(Wnd); - if(Wnd->style & WS_DISABLED) + if (Wnd->style & WS_DISABLED) { BOOL Ret; PWND TopWnd; PWND DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); - if(DesktopWindow) + if (DesktopWindow) { Top = IntFindChildWindowToOwner(DesktopWindow, Wnd); - if((TopWnd = UserGetWindowObject(Top))) + if ((TopWnd = UserGetWindowObject(Top))) { UserRefObjectCo(TopWnd, &Ref); Ret = co_IntMouseActivateWindow(TopWnd); @@ -329,22 +366,21 @@ co_IntMouseActivateWindow(PWND Wnd) return FALSE; } - TopWindow = UserGetAncestor(Wnd, GA_ROOT); if (!TopWindow) return FALSE; /* TMN: Check return valud from this function? */ UserRefObjectCo(TopWindow, &Ref); - co_IntSetForegroundAndFocusWindow(TopWindow, Wnd, TRUE); + co_IntSetForegroundAndFocusWindow(TopWindow, TRUE); UserDerefObjectCo(TopWindow); return TRUE; } -HWND FASTCALL -co_IntSetActiveWindow(PWND Wnd OPTIONAL) +BOOL FASTCALL +co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; @@ -353,46 +389,79 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL) CBTACTIVATESTRUCT cbt; if (Wnd) + { ASSERT_REFS_CO(Wnd); + hWnd = UserHMGetHandle(Wnd); + } pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); - if (Wnd != 0) - { - 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; - } + hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL; + if (Prev) *Prev = hWndPrev; + if (hWndPrev == hWnd) return TRUE; - hWndPrev = ThreadQueue->ActiveWindow; - if (hWndPrev == hWnd) + if (Wnd) { - return hWndPrev; + if (ThreadQueue != Wnd->head.pti->MessageQueue) + { + PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); + // Rule 1 & 4, We are foreground so set this FG window or NULL foreground.... + if (!ForegroundQueue || ForegroundQueue == ThreadQueue) + { + return co_IntSetForegroundAndFocusWindow(Wnd, bMouse); + } + } + + if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE; } /* Call CBT hook chain */ - cbt.fMouse = FALSE; + cbt.fMouse = bMouse; cbt.hWndActive = hWndPrev; if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) { ERR("SetActiveWindow WH_CBT Call Hook return!\n"); - return 0; + return FALSE; } co_IntSendDeactivateMessages(hWndPrev, hWnd); - ThreadQueue->ActiveWindow = hWnd; + if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED; - co_IntSendActivateMessages(hWndPrev, hWnd, FALSE); + IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); - /* FIXME */ - /* return IntIsWindow(hWndPrev) ? hWndPrev : 0;*/ - return hWndPrev; + /* check if the specified window can be set in the input data of a given queue */ + if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue) + { + /* set the current thread active window */ + if (!Wnd || co_IntMakeWindowActive(Wnd)) + { + ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive; + ThreadQueue->spwndActive = Wnd; + } + } + + co_IntSendActivateMessages(hWndPrev, hWnd, bMouse); + + /* now change focus if necessary */ + if (bFocus) + { + /* Do not change focus if the window is no longer active */ + if (ThreadQueue->spwndActive == Wnd) + { + if (!ThreadQueue->spwndFocus || + !Wnd || + UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd) + { + co_UserSetFocus(Wnd); + } + } + } + + if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED; + return TRUE; } HWND FASTCALL @@ -410,20 +479,33 @@ co_UserSetFocus(PWND Window) ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); - hWndPrev = ThreadQueue->FocusWindow; + hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; if (Window != 0) { - if (hWndPrev == Window->head.h) + if (hWndPrev == UserHMGetHandle(Window)) { return hWndPrev; /* Nothing to do */ } + if (Window->head.pti->MessageQueue != ThreadQueue) + { + ERR("SetFocus Must have the same Q!\n"); + return 0; + } + /* Check if we can set the focus to this window */ - for (pwndTop = Window; pwndTop != NULL; pwndTop = pwndTop->spwndParent ) + pwndTop = Window; + for (;;) { if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0; - if ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break; + if (!pwndTop->spwndParent || pwndTop->spwndParent == UserGetDesktopWindow()) + { + if ((pwndTop->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return 0; + break; + } + if (pwndTop->spwndParent == UserGetMessageWindow()) return 0; + pwndTop = pwndTop->spwndParent; } if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) @@ -433,37 +515,63 @@ co_UserSetFocus(PWND Window) } /* Activate pwndTop if needed. */ - if (pwndTop->head.h != ThreadQueue->ActiveWindow) + if (pwndTop != ThreadQueue->spwndActive) { - co_IntSetActiveWindow(pwndTop); + PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Keep it based on desktop. + if (ThreadQueue != ForegroundQueue) // HACK see rule 2 & 3. + { + if (!co_IntSetForegroundAndFocusWindow(pwndTop, FALSE)) + { + ERR("SetFocus Set Foreground and Focus Failed!\n"); + return 0; + } + } + + /* Set Active when it is needed. */ + if (pwndTop != ThreadQueue->spwndActive) + { + if (!co_IntSetActiveWindow(pwndTop, NULL, FALSE, FALSE)) + { + ERR("SetFocus Set Active Failed!\n"); + return 0; + } + } + /* 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) + if (pwndTop != ThreadQueue->spwndActive) { ERR("SetFocus Top window did not go active!\n"); return 0; } } - ThreadQueue->FocusWindow = Window->head.h; + /* check if the specified window can be set in the input data of a given queue */ + if ( !Window || ThreadQueue == Window->head.pti->MessageQueue) + /* set the current thread focus window */ + ThreadQueue->spwndFocus = Window; + TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h); co_IntSendKillFocusMessages(hWndPrev, Window->head.h); co_IntSendSetFocusMessages(hWndPrev, Window->head.h); } - else + else /* NULL hwnd passed in */ { - ThreadQueue->FocusWindow = 0; + if (!hWndPrev) return 0; /* nothing to do */ if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) { ERR("SetFocusWindow 2 WH_CBT Call Hook return!\n"); return 0; } + /* set the current thread focus window null */ + ThreadQueue->spwndFocus = 0; + co_IntSendKillFocusMessages(hWndPrev, 0); } - return hWndPrev; + return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; } HWND FASTCALL @@ -472,7 +580,7 @@ UserGetForegroundWindow(VOID) PUSER_MESSAGE_QUEUE ForegroundQueue; ForegroundQueue = IntGetFocusMessageQueue(); - return( ForegroundQueue != NULL ? ForegroundQueue->ActiveWindow : 0); + return( ForegroundQueue ? (ForegroundQueue->spwndActive ? UserHMGetHandle(ForegroundQueue->spwndActive) : 0) : 0); } HWND FASTCALL UserGetActiveWindow(VOID) @@ -482,7 +590,7 @@ HWND FASTCALL UserGetActiveWindow(VOID) pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; - return( ThreadQueue ? ThreadQueue->ActiveWindow : 0); + return( ThreadQueue ? (ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : 0) : 0); } HWND APIENTRY @@ -568,6 +676,9 @@ co_UserSetCapture(HWND hWnd) return hWndPrev; } +/* + API Call +*/ BOOL FASTCALL IntReleaseCapture(VOID) @@ -586,6 +697,91 @@ IntReleaseCapture(VOID) return TRUE; } +/* + API Call +*/ +BOOL FASTCALL +co_IntSetForegroundWindow(PWND Window) +{ + ASSERT_REFS_CO(Window); + + return co_IntSetForegroundAndFocusWindow(Window, FALSE); +} + +/* + API Call +*/ +BOOL FASTCALL +IntLockSetForegroundWindow(UINT uLockCode) +{ + ULONG Err = ERROR_ACCESS_DENIED; + PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); + switch (uLockCode) + { + case LSFW_LOCK: + if ( CanForceFG(ppi) && !gppiLockSFW ) + { + gppiLockSFW = ppi; + return TRUE; + } + break; + case LSFW_UNLOCK: + if ( gppiLockSFW == ppi) + { + gppiLockSFW = NULL; + return TRUE; + } + break; + default: + Err = ERROR_INVALID_PARAMETER; + } + EngSetLastError(Err); + return FALSE; +} + +/* + API Call +*/ +BOOL FASTCALL +IntAllowSetForegroundWindow(DWORD dwProcessId) +{ + PPROCESSINFO ppi, ppiCur; + PEPROCESS Process = NULL; + + ppi = NULL; + if (dwProcessId != ASFW_ANY) + { + if (!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)dwProcessId, &Process))) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + ppi = PsGetProcessWin32Process(Process); + if (!ppi) + { + ObDereferenceObject(Process); + return FALSE; + } + } + ppiCur = PsGetCurrentProcessWin32Process(); + if (!CanForceFG(ppiCur)) + { + if (Process) ObDereferenceObject(Process); + EngSetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } + if (dwProcessId == ASFW_ANY) + { // All processes will be enabled to set the foreground window. + ptiLastInput = NULL; + } + else + { // Rule #3, last input event in force. + ptiLastInput = ppi->ptiList; + ObDereferenceObject(Process); + } + return TRUE; +} + /* * @implemented */ @@ -609,42 +805,33 @@ HWND APIENTRY NtUserSetActiveWindow(HWND hWnd) { USER_REFERENCE_ENTRY Ref; + HWND hWndPrev; + PWND Window; DECLARE_RETURN(HWND); TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd); UserEnterExclusive(); + Window = NULL; 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); + if (!Window || + Window->head.pti->MessageQueue == gptiCurrent->MessageQueue) + { + if (Window) UserRefObjectCo(Window, &Ref); + if (!co_IntSetActiveWindow(Window, &hWndPrev, FALSE, TRUE)) hWndPrev = NULL; + if (Window) UserDerefObjectCo(Window); } else - { - RETURN( co_IntSetActiveWindow(0)); - } + hWndPrev = NULL; + + RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 ); CLEANUP: TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_); diff --git a/reactos/win32ss/user/ntuser/focus.h b/reactos/win32ss/user/ntuser/focus.h index 60a6dccb962..f0f2c97a577 100644 --- a/reactos/win32ss/user/ntuser/focus.h +++ b/reactos/win32ss/user/ntuser/focus.h @@ -1,5 +1,8 @@ #pragma once +extern PUSER_MESSAGE_QUEUE gpqForeground; +extern PUSER_MESSAGE_QUEUE gpqForegroundPrev; + /* * These functions take the window handles from current message queue. */ @@ -12,8 +15,9 @@ BOOL FASTCALL IntReleaseCapture(VOID); */ HWND FASTCALL IntGetThreadFocusWindow(VOID); HWND APIENTRY IntGetCapture(VOID); -HWND FASTCALL UserGetFocusWindow(VOID); HWND FASTCALL UserGetActiveWindow(VOID); BOOL FASTCALL co_IntMouseActivateWindow(PWND Window); BOOL FASTCALL co_IntSetForegroundWindow(PWND Window); -HWND FASTCALL co_IntSetActiveWindow(PWND Window); +BOOL FASTCALL co_IntSetActiveWindow(PWND Window,HWND * Prev,BOOL bMouse,BOOL bFocus); +BOOL FASTCALL IntLockSetForegroundWindow(UINT uLockCode); +BOOL FASTCALL IntAllowSetForegroundWindow(DWORD dwProcessId); diff --git a/reactos/win32ss/user/ntuser/input.c b/reactos/win32ss/user/ntuser/input.c index c90c960bdcf..68326c704be 100644 --- a/reactos/win32ss/user/ntuser/input.c +++ b/reactos/win32ss/user/ntuser/input.c @@ -74,7 +74,7 @@ DoTheScreenSaver(VOID) else { PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); - if (ForegroundQueue && ForegroundQueue->ActiveWindow) + if (ForegroundQueue && ForegroundQueue->spwndActive) UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 1); // lParam 1 == Secure else UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 0); diff --git a/reactos/win32ss/user/ntuser/kbdlayout.c b/reactos/win32ss/user/ntuser/kbdlayout.c index 531d70772ba..3f6f434ef29 100644 --- a/reactos/win32ss/user/ntuser/kbdlayout.c +++ b/reactos/win32ss/user/ntuser/kbdlayout.c @@ -386,7 +386,7 @@ co_UserActivateKbl(PTHREADINFO pti, PKL pKl, UINT Flags) } // Send WM_INPUTLANGCHANGE to thread's focus window - co_IntSendMessage(pti->MessageQueue->FocusWindow, + co_IntSendMessage(pti->MessageQueue->spwndFocus ? UserHMGetHandle(pti->MessageQueue->spwndFocus) : 0, WM_INPUTLANGCHANGE, (WPARAM)pKl->iBaseCharset, // FIXME: How to set it? (LPARAM)pKl->hkl); // hkl diff --git a/reactos/win32ss/user/ntuser/keyboard.c b/reactos/win32ss/user/ntuser/keyboard.c index 36bac2f05fc..5267bb1c9db 100644 --- a/reactos/win32ss/user/ntuser/keyboard.c +++ b/reactos/win32ss/user/ntuser/keyboard.c @@ -851,7 +851,7 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d IS_KEY_DOWN(gafAsyncKeyState, VK_MENU) && !IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL)) { - SnapWindow(pFocusQueue->FocusWindow); + SnapWindow(pFocusQueue->spwndFocus ? UserHMGetHandle(pFocusQueue->spwndFocus) : 0); } else SnapWindow(NULL); @@ -859,7 +859,7 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d else if (pFocusQueue && bPostMsg) { /* Init message */ - Msg.hwnd = pFocusQueue->FocusWindow; + Msg.hwnd = pFocusQueue->spwndFocus ? UserHMGetHandle(pFocusQueue->spwndFocus) : 0; Msg.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */ Msg.lParam = MAKELPARAM(1, wScanCode); Msg.time = dwTime; @@ -903,6 +903,8 @@ UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected) DWORD dwTime; BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE; + gppiInputProvider = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->ppi; + /* Find the target thread whose locale is in effect */ pFocusQueue = IntGetFocusMessageQueue(); diff --git a/reactos/win32ss/user/ntuser/message.c b/reactos/win32ss/user/ntuser/message.c index 35f36f8cb16..d141580b81f 100644 --- a/reactos/win32ss/user/ntuser/message.c +++ b/reactos/win32ss/user/ntuser/message.c @@ -594,10 +594,11 @@ IntCallWndProcRet ( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPar static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPARAM lparam ) { LRESULT lRes; + USER_REFERENCE_ENTRY Ref; if (!pWnd || - pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - pWnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND return 0; ERR("Internal Event Msg %p\n",msg); @@ -620,6 +621,14 @@ static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPAR ExFreePoolWithTag(winpos, USERTAG_SWP); return lRes; } + case WM_ASYNC_SETACTIVEWINDOW: + { + PWND Window = (PWND)wparam; + if (wparam) UserRefObjectCo(Window, &Ref); + lRes = (LRESULT)co_IntSetActiveWindow(Window,NULL,(BOOL)lparam,TRUE); + if (wparam) UserDerefObjectCo(Window); + return lRes; + } } return 0; } diff --git a/reactos/win32ss/user/ntuser/misc.c b/reactos/win32ss/user/ntuser/misc.c index 92d29795aa3..91f51153a96 100644 --- a/reactos/win32ss/user/ntuser/misc.c +++ b/reactos/win32ss/user/ntuser/misc.c @@ -164,7 +164,7 @@ NtUserGetThreadState( GetW32ThreadInfo(); break; case THREADSTATE_FOCUSWINDOW: - ret = (DWORD_PTR)UserGetFocusWindow(); + ret = (DWORD_PTR)IntGetThreadFocusWindow(); break; case THREADSTATE_CAPTUREWINDOW: /* FIXME: Should use UserEnterShared */ @@ -350,8 +350,8 @@ NtUserGetGUIThreadInfo( /* FIXME: Add flag GUI_16BITTASK */ - SafeGui.hwndActive = MsgQueue->ActiveWindow; - SafeGui.hwndFocus = MsgQueue->FocusWindow; + SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0; + SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0; SafeGui.hwndCapture = MsgQueue->CaptureWindow; SafeGui.hwndMenuOwner = MsgQueue->MenuOwner; SafeGui.hwndMoveSize = MsgQueue->MoveSize; diff --git a/reactos/win32ss/user/ntuser/mouse.c b/reactos/win32ss/user/ntuser/mouse.c index a6425e91e63..8101cb1530c 100644 --- a/reactos/win32ss/user/ntuser/mouse.c +++ b/reactos/win32ss/user/ntuser/mouse.c @@ -178,6 +178,8 @@ UserSendMouseInput(MOUSEINPUT *pmi, BOOL bInjected) ptCursor = gpsi->ptCursor; dwFlags = IntFixMouseInputButtons(pmi->dwFlags); + gppiInputProvider = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->ppi; + if (pmi->dwFlags & MOUSEEVENTF_MOVE) { /* Mouse has changes position */ diff --git a/reactos/win32ss/user/ntuser/msgqueue.c b/reactos/win32ss/user/ntuser/msgqueue.c index f4129286039..9914df71fdd 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.c +++ b/reactos/win32ss/user/ntuser/msgqueue.c @@ -517,7 +517,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook if (co_HOOK_CallHooks(WH_MOUSE_LL, HC_ACTION, Msg->message, (LPARAM) &MouseHookData)) return; } - + /* Get the desktop window */ pwndDesktop = UserGetDesktopWindow(); if (!pwndDesktop) return; @@ -717,8 +717,8 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue) (HHOOK)Message->Msg.lParam, Message->Msg.wParam); } - else if ((Message->CompletionCallback) - && (Message->CallBackSenderQueue == MessageQueue)) + else if ((Message->CompletionCallback) && + (Message->CallBackSenderQueue == MessageQueue)) { /* Call the callback routine */ if (Message->QS_Flags & QS_SMRESULT) { @@ -982,14 +982,6 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, PLIST_ENTRY Entry; LRESULT Result = 0; //// Result could be trashed. //// - if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG))) - { - ERR("MsqSendMessage(): Not enough memory to allocate a message"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - KeInitializeEvent(&CompletionEvent, NotificationEvent, FALSE); - pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ptirec = MessageQueue->Thread->Tcb.Win32Thread; @@ -999,10 +991,45 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, /* Don't send from or to a dying thread */ if (pti->TIF_flags & TIF_INCLEANUP || ptirec->TIF_flags & TIF_INCLEANUP) { - *uResult = -1; - return STATUS_TIMEOUT; + if (uResult) *uResult = -1; + ERR("MsqSM: Current pti %d or Rec pti %d\n",pti->TIF_flags & TIF_INCLEANUP, ptirec->TIF_flags & TIF_INCLEANUP); + return STATUS_UNSUCCESSFUL; } + if ( HookMessage == MSQ_NORMAL ) + { + // These can not cross International Border lines! + if ( pti->ppi != ptirec->ppi ) + { + switch(Msg) + { + case EM_GETLINE: + case EM_SETPASSWORDCHAR: + case WM_GETTEXT: + case WM_NOTIFY: + if (uResult) *uResult = -1; + ERR("Running across the border without a passport!\n"); + return STATUS_UNSUCCESSFUL; + } + } + + // These can not cross State lines! + if ( Msg == WM_CREATE || Msg == WM_NCCREATE ) + { + if (uResult) *uResult = -1; + ERR("Can not tell the other State we have Create!\n"); + return STATUS_UNSUCCESSFUL; + } + } + + if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG))) + { + ERR("MsqSendMessage(): Not enough memory to allocate a message"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + KeInitializeEvent(&CompletionEvent, NotificationEvent, FALSE); + Timeout.QuadPart = (LONGLONG) uTimeout * (LONGLONG) -10000; /* FIXME: Increase reference counter of sender's message queue here */ @@ -1203,7 +1230,7 @@ MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue, ULONG ExitCode) */ static void MsqSendParentNotify( PWND pwnd, WORD event, WORD idChild, POINT pt ) { - PWND pwndDesktop = UserGetWindowObject(IntGetDesktopWindow()); + PWND pwndDesktop = UserGetDesktopWindow(); /* pt has to be in the client coordinates of the parent window */ pt.x += pwndDesktop->rcClient.left - pwnd->rcClient.left; @@ -1231,7 +1258,7 @@ FASTCALL IntTrackMouseMove(PWND pwndTrack, PDESKTOP pDesk, PMSG msg, USHORT hittest) { // PWND pwndTrack = IntChildrenWindowFromPoint(pwndMsg, msg->pt.x, msg->pt.y); -// hittest = GetNCHitEx(pwndTrack, msg->pt); + hittest = GetNCHitEx(pwndTrack, msg->pt); if ( pDesk->spwndTrack != pwndTrack || // Change with tracking window or msg->message != WM_MOUSEMOVE || // Mouse click changes or @@ -1836,7 +1863,7 @@ MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQu MessageQueue->QuitExitCode = 0; KeQueryTickCount(&LargeTickCount); MessageQueue->LastMsgRead = LargeTickCount.u.LowPart; - MessageQueue->FocusWindow = NULL; + MessageQueue->spwndFocus = NULL; MessageQueue->NewMessagesHandle = NULL; MessageQueue->ShowingCursor = 0; MessageQueue->CursorObject = NULL; @@ -2146,12 +2173,12 @@ MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd) MessageQueue->CaptureWindow = hWnd; return Prev; case MSQ_STATE_ACTIVE: - Prev = MessageQueue->ActiveWindow; - MessageQueue->ActiveWindow = hWnd; + Prev = MessageQueue->spwndActive ? UserHMGetHandle(MessageQueue->spwndActive) : 0; + MessageQueue->spwndActive = UserGetWindowObject(hWnd); return Prev; case MSQ_STATE_FOCUS: - Prev = MessageQueue->FocusWindow; - MessageQueue->FocusWindow = hWnd; + Prev = MessageQueue->spwndFocus ? UserHMGetHandle(MessageQueue->spwndFocus) : 0; + MessageQueue->spwndFocus = UserGetWindowObject(hWnd); return Prev; case MSQ_STATE_MENUOWNER: Prev = MessageQueue->MenuOwner; diff --git a/reactos/win32ss/user/ntuser/msgqueue.h b/reactos/win32ss/user/ntuser/msgqueue.h index e23d2799ca1..6e5ba59a8c6 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.h +++ b/reactos/win32ss/user/ntuser/msgqueue.h @@ -78,10 +78,8 @@ typedef struct _USER_MESSAGE_QUEUE HWND CaptureWindow; PWND spwndCapture; /* Current window with focus (ie. receives keyboard input) for this queue. */ - HWND FocusWindow; PWND spwndFocus; /* Current active window for this queue. */ - HWND ActiveWindow; PWND spwndActive; PWND spwndActivePrev; /* Current move/size window for this queue */ @@ -146,7 +144,8 @@ typedef struct _USER_MESSAGE_QUEUE enum internal_event_message { WM_ASYNC_SHOWWINDOW = 0x80000000, - WM_ASYNC_SETWINDOWPOS + WM_ASYNC_SETWINDOWPOS, + WM_ASYNC_SETACTIVEWINDOW }; BOOL FASTCALL MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue); diff --git a/reactos/win32ss/user/ntuser/simplecall.c b/reactos/win32ss/user/ntuser/simplecall.c index dd306eac77b..7b0bdca7bff 100644 --- a/reactos/win32ss/user/ntuser/simplecall.c +++ b/reactos/win32ss/user/ntuser/simplecall.c @@ -380,6 +380,10 @@ NtUserCallOneParam( /* TODO: Implement sound sentry */ case ONEPARAM_ROUTINE_CREATESYSTEMTHREADS: RETURN(CreateSystemThreads(Param)); + case ONEPARAM_ROUTINE_LOCKFOREGNDWINDOW: + RETURN( (DWORD_PTR)IntLockSetForegroundWindow(Param)); + case ONEPARAM_ROUTINE_ALLOWSETFOREGND: + RETURN( (DWORD_PTR)IntAllowSetForegroundWindow(Param)); } ERR("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n", Routine, Param); diff --git a/reactos/win32ss/user/ntuser/win32.h b/reactos/win32ss/user/ntuser/win32.h index cb89c0a61a4..efb001c54da 100644 --- a/reactos/win32ss/user/ntuser/win32.h +++ b/reactos/win32ss/user/ntuser/win32.h @@ -17,6 +17,7 @@ #define W32PF_CLASSESREGISTERED 0x00002000 #define W32PF_THREADCONNECTED 0x00004000 #define W32PF_PROCESSCONNECTED 0x00008000 +#define W32PF_SETFOREGROUNDALLOWED 0x00008000 #define W32PF_WAKEWOWEXEC 0x00010000 #define W32PF_WAITFORINPUTIDLE 0x00020000 #define W32PF_IOWINSTA 0x00040000 diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index e86625d4b9b..63198421a80 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -499,33 +499,6 @@ static LRESULT co_UserFreeWindow(PWND Window, return 0; } -VOID FASTCALL -IntGetWindowBorderMeasures(PWND Wnd, UINT *cx, UINT *cy) -{ - if(HAS_DLGFRAME(Wnd->style, Wnd->ExStyle) && !(Wnd->style & WS_MINIMIZE)) - { - *cx = UserGetSystemMetrics(SM_CXDLGFRAME); - *cy = UserGetSystemMetrics(SM_CYDLGFRAME); - } - else - { - if(HAS_THICKFRAME(Wnd->style, Wnd->ExStyle)&& !(Wnd->style & WS_MINIMIZE)) - { - *cx = UserGetSystemMetrics(SM_CXFRAME); - *cy = UserGetSystemMetrics(SM_CYFRAME); - } - else if(HAS_THINFRAME(Wnd->style, Wnd->ExStyle)) - { - *cx = UserGetSystemMetrics(SM_CXBORDER); - *cy = UserGetSystemMetrics(SM_CYBORDER); - } - else - { - *cx = *cy = 0; - } - } -} - // // Same as User32:IntGetWndProc. // @@ -777,41 +750,6 @@ co_DestroyThreadWindows(struct _ETHREAD *Thread) } } -/*! - * Internal function. - * Returns client window rectangle relative to the upper-left corner of client area. - * - * \note Does not check the validity of the parameters -*/ -VOID FASTCALL -IntGetClientRect(PWND Wnd, RECTL *Rect) -{ - ASSERT( Wnd ); - ASSERT( Rect ); - 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) { @@ -968,7 +906,9 @@ IntLinkWindow( } } - +/* + Note: Wnd->spwndParent can be null if it is the desktop. +*/ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev) { if (hWndPrev == HWND_NOTOPMOST) @@ -1626,7 +1566,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, pWnd->spwndParent = ParentWindow; pWnd->spwndOwner = OwnerWindow; pWnd->fnid = 0; - pWnd->hWndLastActive = hWnd; + pWnd->spwndLastActive = pWnd; pWnd->state2 |= WNDS2_WIN40COMPAT; // FIXME!!! pWnd->pcls = Class; pWnd->hModule = Cs->hInstance; @@ -1754,14 +1694,15 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, } } - /* - * 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; + /* WS_EX_WINDOWEDGE depends on some other styles */ + if (pWnd->ExStyle & WS_EX_DLGMODALFRAME) + pWnd->ExStyle |= WS_EX_WINDOWEDGE; + else if (pWnd->style & (WS_DLGFRAME | WS_THICKFRAME)) + { + if (!((pWnd->ExStyle & WS_EX_STATICEDGE) && + (pWnd->style & (WS_CHILD | WS_POPUP)))) + pWnd->ExStyle |= WS_EX_WINDOWEDGE; + } else pWnd->ExStyle &= ~WS_EX_WINDOWEDGE; @@ -2061,6 +2002,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, Window->rcWindow.bottom = Cs->y + Size.cy; if (0 != (Window->style & WS_CHILD) && ParentWindow) { +// ERR("co_UserCreateWindowEx(): Offset rcWindow\n"); RECTL_vOffsetRect(&Window->rcWindow, ParentWindow->rcClient.left, ParentWindow->rcClient.top); @@ -2421,10 +2363,10 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) } } - if (Window->head.pti->MessageQueue->ActiveWindow == Window->head.h) - Window->head.pti->MessageQueue->ActiveWindow = NULL; - if (Window->head.pti->MessageQueue->FocusWindow == Window->head.h) - Window->head.pti->MessageQueue->FocusWindow = NULL; + if (Window->head.pti->MessageQueue->spwndActive == Window) + Window->head.pti->MessageQueue->spwndActive = NULL; + if (Window->head.pti->MessageQueue->spwndFocus == Window) + Window->head.pti->MessageQueue->spwndFocus = NULL; if (Window->head.pti->MessageQueue->CaptureWindow == Window->head.h) Window->head.pti->MessageQueue->CaptureWindow = NULL; @@ -3519,11 +3461,11 @@ NtUserQueryWindow(HWND hWnd, DWORD Index) break; case QUERY_WINDOW_ACTIVE: - Result = (DWORD)pWnd->head.pti->MessageQueue->ActiveWindow; + Result = (DWORD)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0); break; case QUERY_WINDOW_FOCUS: - Result = (DWORD)pWnd->head.pti->MessageQueue->FocusWindow; + Result = (DWORD)(pWnd->head.pti->MessageQueue->spwndFocus ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndFocus) : 0); break; case QUERY_WINDOW_ISHUNG: diff --git a/reactos/win32ss/user/ntuser/winpos.c b/reactos/win32ss/user/ntuser/winpos.c index 19d3c55b220..d69e466d323 100644 --- a/reactos/win32ss/user/ntuser/winpos.c +++ b/reactos/win32ss/user/ntuser/winpos.c @@ -45,6 +45,97 @@ IntGetClientOrigin(PWND Window OPTIONAL, LPPOINT Point) return TRUE; } +/*! + * Internal function. + * Returns client window rectangle relative to the upper-left corner of client area. + * + * \note Does not check the validity of the parameters +*/ +VOID FASTCALL +IntGetClientRect(PWND Wnd, RECTL *Rect) +{ + ASSERT( Wnd ); + ASSERT( Rect ); + 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); + */ + } +} + +INT FASTCALL +IntMapWindowPoints(PWND FromWnd, PWND ToWnd, LPPOINT lpPoints, UINT cPoints) +{ + BOOL mirror_from, mirror_to; + POINT Delta; + UINT i; + int Change = 1; + + /* Note: Desktop Top and Left is always 0! */ + Delta.x = Delta.y = 0; + mirror_from = mirror_to = FALSE; + + if (FromWnd && FromWnd != UserGetDesktopWindow()) // FromWnd->fnid != FNID_DESKTOP) + { + if (FromWnd->ExStyle & WS_EX_LAYOUTRTL) + { + mirror_from = TRUE; + Change = -Change; + Delta.x = -FromWnd->rcClient.right; + } + else + Delta.x = FromWnd->rcClient.left; + Delta.y = FromWnd->rcClient.top; + } + + if (ToWnd && ToWnd != UserGetDesktopWindow()) // ToWnd->fnid != FNID_DESKTOP) + { + if (ToWnd->ExStyle & WS_EX_LAYOUTRTL) + { + mirror_to = TRUE; + Change = -Change; + Delta.x += Change * ToWnd->rcClient.right; + } + else + Delta.x -= Change * ToWnd->rcClient.left; + Delta.y -= ToWnd->rcClient.top; + } + + if (mirror_from) Delta.x = -Delta.x; + + for (i = 0; i != cPoints; i++) + { + lpPoints[i].x += Delta.x; + lpPoints[i].x *= Change; + lpPoints[i].y += Delta.y; + } + + if ((mirror_from || mirror_to) && cPoints == 2) /* special case for rectangle */ + { + int tmp = min(lpPoints[0].x, lpPoints[1].x); + lpPoints[1].x = max(lpPoints[0].x, lpPoints[1].x); + lpPoints[0].x = tmp; + } + + return MAKELONG(LOWORD(Delta.x), LOWORD(Delta.y)); +} /******************************************************************* * can_activate_window @@ -80,7 +171,7 @@ VOID FASTCALL co_WinPosActivateOtherWindow(PWND Wnd) { PWND WndTo = NULL; - HWND Fg; + HWND Fg, previous; USER_REFERENCE_ENTRY Ref; ASSERT_REFS_CO(Wnd); @@ -122,32 +213,13 @@ done: } } - if (!co_IntSetActiveWindow(WndTo)) /* Ok for WndTo to be NULL here */ - co_IntSetActiveWindow(0); + if (!co_IntSetActiveWindow(WndTo,&previous,FALSE,TRUE) || /* Ok for WndTo to be NULL here */ + !previous) + co_IntSetActiveWindow(0,NULL,FALSE,TRUE); if (WndTo) UserDerefObjectCo(WndTo); } -BOOL -FASTCALL -WinPosShowIconTitle( PWND pWnd, BOOL bShow ) -{ - HICON hIcon; - if (!pWnd->pcls || pWnd->fnid == FNID_DESKTOP) return FALSE; - hIcon = pWnd->pcls->hIconSm; - if (!hIcon) hIcon = pWnd->pcls->hIcon; - if (!hIcon) return FALSE; - - if ( bShow ) - { - // FIXME: Draw ICON! - } - else if (hIcon) - return FALSE; - - return FALSE; -} - UINT FASTCALL co_WinPosArrangeIconicWindows(PWND parent) @@ -165,13 +237,14 @@ co_WinPosArrangeIconicWindows(PWND parent) } IntGetClientRect( parent, &rectParent ); + // FIXME: Support gspv.mm.iArrange. x = rectParent.left; y = rectParent.bottom; xspacing = (UserGetSystemMetrics(SM_CXMINSPACING)/2)+UserGetSystemMetrics(SM_CXBORDER); yspacing = (UserGetSystemMetrics(SM_CYMINSPACING)/2)+UserGetSystemMetrics(SM_CYBORDER); - TRACE("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing); + //ERR("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing); for(i = 0; List[i]; i++) { @@ -194,6 +267,7 @@ co_WinPosArrangeIconicWindows(PWND parent) Child->InternalPos.IconPos.x = sx; Child->InternalPos.IconPos.y = sy; Child->InternalPos.flags |= WPF_MININIT; + Child->InternalPos.flags &= ~WPF_SETMINPOSITION; UserDerefObjectCo(Child); @@ -204,7 +278,7 @@ co_WinPosArrangeIconicWindows(PWND parent) x = rectParent.left; y -= yspacing; } - TRACE("X:%d Y:%d\n",x,y); + //ERR("X:%d Y:%d\n",x,y); } } ExFreePool(List); @@ -214,67 +288,63 @@ co_WinPosArrangeIconicWindows(PWND parent) static VOID FASTCALL WinPosFindIconPos(PWND Window, POINT *Pos) { - RECT rect, rectParent; + RECT rectParent; PWND pwndChild, pwndParent; - HRGN hrgn, tmp; - int xspacing, yspacing; + int x, y, xspacing, yspacing; pwndParent = Window->spwndParent; if (pwndParent == UserGetDesktopWindow()) { /* ReactOS doesn't support iconic minimize to desktop */ Pos->x = Pos->y = -32000; + Window->InternalPos.flags |= WPF_MININIT; + Window->InternalPos.IconPos.x = Pos->x; + Window->InternalPos.IconPos.y = Pos->y; return; } IntGetClientRect( pwndParent, &rectParent ); - if ((Pos->x >= rectParent.left) && ((Pos->x + UserGetSystemMetrics(SM_CXICON)) < rectParent.right) && - (Pos->y >= rectParent.top) && ((Pos->y + UserGetSystemMetrics(SM_CYICON)) < rectParent.bottom)) - return; /* The icon already has a suitable position */ + // FIXME: Support gspv.mm.iArrange. + x = rectParent.left; + y = rectParent.bottom; - xspacing = UserGetSystemMetrics(SM_CXICONSPACING); - yspacing = UserGetSystemMetrics(SM_CYICONSPACING); + xspacing = (UserGetSystemMetrics(SM_CXMINSPACING)/2)+UserGetSystemMetrics(SM_CXBORDER); + yspacing = (UserGetSystemMetrics(SM_CYMINSPACING)/2)+UserGetSystemMetrics(SM_CYBORDER); - /* Check if another icon already occupies this spot */ - /* FIXME: this is completely inefficient */ + //ERR("X:%d Y:%d XS:%d YS:%d\n",Pos->x,Pos->y,xspacing,yspacing); + + // Set to default position when minimized. + Pos->x = x + UserGetSystemMetrics(SM_CXBORDER); + Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); - hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 ); - tmp = IntSysCreateRectRgn( 0, 0, 0, 0 ); for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext) { if (pwndChild == Window) continue; - if ((pwndChild->style & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE)) - continue; - if ( pwndChild->spwndParent ) - { - PWND Parent = pwndChild->spwndParent; - rect.left = rect.top = 0; - rect.right = Parent->rcWindow.right - Parent->rcWindow.left; - rect.bottom = Parent->rcWindow.bottom - Parent->rcWindow.top; - NtGdiSetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom ); - NtGdiCombineRgn( hrgn, hrgn, tmp, RGN_OR ); - } - } - GreDeleteObject( tmp ); - for (rect.bottom = rectParent.bottom; rect.bottom >= yspacing; rect.bottom -= yspacing) - { - for (rect.left = rectParent.left; rect.left <= rectParent.right - xspacing; rect.left += xspacing) - { - rect.right = rect.left + xspacing; - rect.top = rect.bottom - yspacing; - if (!IntRectInRegion( hrgn, &rect )) - { - /* No window was found, so it's OK for us */ - Pos->x = rect.left + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2; - Pos->y = rect.top + (yspacing - UserGetSystemMetrics(SM_CYICON)) / 2; - GreDeleteObject( hrgn ); - return; - } + if (pwndChild->style & WS_VISIBLE) + { + //ERR("Loop!\n"); + continue; + } + //ERR("Pos Child X %d Y %d!\n", pwndChild->InternalPos.IconPos.x, pwndChild->InternalPos.IconPos.y); + if ( pwndChild->InternalPos.IconPos.x == Pos->x && + pwndChild->InternalPos.IconPos.y == Pos->y ) + { + if (x <= rectParent.right - UserGetSystemMetrics(SM_CXMINSPACING)) + x += xspacing; + else + { + x = rectParent.left; + y -= yspacing; + } + Pos->x = x + UserGetSystemMetrics(SM_CXBORDER); + Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); } } - GreDeleteObject( hrgn ); - Pos->x = Pos->y = 0; + Window->InternalPos.IconPos.x = Pos->x; + Window->InternalPos.IconPos.y = Pos->y; + Window->InternalPos.flags |= WPF_MININIT; + //ERR("Position is set! X:%d Y:%d\n",Pos->x,Pos->y); return; } @@ -324,16 +394,27 @@ WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect) { RECTL WorkArea; PMONITOR pmonitor = UserMonitorFromRect(&Rect, MONITOR_DEFAULTTOPRIMARY ); - // FIXME: support DPI aware, rcWorkDPI/Real etc.. - if (!(Wnd->style & WS_MAXIMIZEBOX) || (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen) - WorkArea = pmonitor->rcMonitor; - else - WorkArea = pmonitor->rcWork; + WorkArea = pmonitor->rcMonitor; + + if (Wnd->style & WS_MAXIMIZEBOX) + { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too. + if ((Wnd->style & WS_CAPTION) == WS_CAPTION || !(Wnd->style & (WS_CHILD | WS_POPUP))) + { + WorkArea = pmonitor->rcWork; + //ERR("rcWork\n"); + } + } Wnd->InternalPos.MaxPos.x = Rect.left - WorkArea.left; Wnd->InternalPos.MaxPos.y = Rect.top - WorkArea.top; - TRACE("WinPosIP 2 X %d Y %d\n",Wnd->InternalPos.MaxPos.x,Wnd->InternalPos.MaxPos.y); + + /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n", + Wnd->InternalPos.MaxPos.x, + Rect.left, WorkArea.left, + Wnd->InternalPos.MaxPos.y, + Rect.top, WorkArea.top); + */ } } else @@ -472,7 +553,7 @@ IntSetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *wpl, UINT Flags) if (Wnd->style & WS_MINIMIZE ) { - if (Flags & PLACE_MIN) + if (Flags & PLACE_MIN || Wnd->InternalPos.flags & WPF_SETMINPOSITION) { co_WinPosSetWindowPos(Wnd, HWND_TOP, wpl->ptMinPosition.x, wpl->ptMinPosition.y, 0, 0, @@ -552,6 +633,7 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) { Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED; Wnd->style &= ~WS_MAXIMIZE; + SwpFlags |= SWP_STATECHANGED; } else { @@ -560,8 +642,16 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT); Wnd->style |= WS_MINIMIZE; + if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION)) + Wnd->InternalPos.flags &= ~WPF_MININIT; WinPosFindIconPos(Wnd, &wpl.ptMinPosition); + /*ERR("Minimize: %d,%d %dx%d\n", + wpl.ptMinPosition.x, wpl.ptMinPosition.y, UserGetSystemMetrics(SM_CXMINIMIZED), + UserGetSystemMetrics(SM_CYMINIMIZED)); + */ RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y, +// wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED), +// wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED)); UserGetSystemMetrics(SM_CXMINIMIZED), UserGetSystemMetrics(SM_CYMINIMIZED)); SwpFlags |= SWP_NOCOPYBITS; @@ -572,14 +662,18 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) { co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); - TRACE("Maximize: %d,%d %dx%d\n", + /*ERR("Maximize: %d,%d %dx%d\n", wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); + */ if (Wnd->style & WS_MINIMIZE) { + SwpFlags |= SWP_STATECHANGED; Wnd->style &= ~WS_MINIMIZE; } Wnd->style |= WS_MAXIMIZE; - RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); + RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, +// wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); + Size.x, Size.y); break; } @@ -591,14 +685,22 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED) { co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); - + SwpFlags |= SWP_STATECHANGED; Wnd->style |= WS_MAXIMIZE; - RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); + /*ERR("Restore to Max: %d,%d %dx%d\n", + wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); + */ + RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, +// wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); + Size.x, Size.y); break; } else { *NewPos = wpl.rcNormalPosition; + /*ERR("Restore Max: %d,%d %dx%d\n", + NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top); + */ NewPos->right -= NewPos->left; NewPos->bottom -= NewPos->top; break; @@ -611,15 +713,19 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) return 0; } Wnd->style &= ~WS_MAXIMIZE; + SwpFlags |= SWP_STATECHANGED; Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; *NewPos = wpl.rcNormalPosition; + /*ERR("Restore Min: %d,%d %dx%d\n", + NewPos->left, NewPos->top, NewPos->right - NewPos->left, NewPos->bottom - NewPos->top); + */ NewPos->right -= NewPos->left; NewPos->bottom -= NewPos->top; break; } } } - return(SwpFlags); + return SwpFlags; } BOOL @@ -639,6 +745,33 @@ UserHasWindowEdge(DWORD Style, DWORD ExStyle) return FALSE; } +VOID FASTCALL +IntGetWindowBorderMeasures(PWND Wnd, UINT *cx, UINT *cy) +{ + if(HAS_DLGFRAME(Wnd->style, Wnd->ExStyle) && !(Wnd->style & WS_MINIMIZE)) + { + *cx = UserGetSystemMetrics(SM_CXDLGFRAME); + *cy = UserGetSystemMetrics(SM_CYDLGFRAME); + } + else + { + if(HAS_THICKFRAME(Wnd->style, Wnd->ExStyle)&& !(Wnd->style & WS_MINIMIZE)) + { + *cx = UserGetSystemMetrics(SM_CXFRAME); + *cy = UserGetSystemMetrics(SM_CYFRAME); + } + else if(HAS_THINFRAME(Wnd->style, Wnd->ExStyle)) + { + *cx = UserGetSystemMetrics(SM_CXBORDER); + *cy = UserGetSystemMetrics(SM_CYBORDER); + } + else + { + *cx = *cy = 0; + } + } +} + VOID UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient) { @@ -694,8 +827,8 @@ UINT FASTCALL co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos, POINT* MinTrack, POINT* MaxTrack) { - MINMAXINFO MinMax; - PMONITOR monitor; + MINMAXINFO MinMax; + PMONITOR monitor; INT xinc, yinc; LONG style = Window->style; LONG adjustedStyle; @@ -767,6 +900,11 @@ co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos, MinMax.ptMaxPosition.x = rc_work.left - xinc; MinMax.ptMaxPosition.y = rc_work.top - yinc; } + if (MinMax.ptMaxSize.x >= (monitor->rcMonitor.right - monitor->rcMonitor.left) && + MinMax.ptMaxSize.y >= (monitor->rcMonitor.bottom - monitor->rcMonitor.top) ) + Window->state |= WNDS_MAXIMIZESTOMONITOR; + else + Window->state &= ~WNDS_MAXIMIZESTOMONITOR; } @@ -1170,6 +1308,12 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) if (InsAfterWnd->spwndParent != Wnd->spwndParent) { + /* Note from wine User32 Win test_SetWindowPos: + "Returns TRUE also for windows that are not siblings" + "Does not seem to do anything even without passing flags, still returns TRUE" + "Same thing the other way around." + ".. and with these windows." + */ return FALSE; } else @@ -1228,11 +1372,12 @@ co_WinPosSetWindowPos( */ if ( Window->head.h == IntGetDesktopWindow() && - Window->head.pti->pEThread->ThreadsProcess != PsGetCurrentProcess()) + Window->head.pti->ppi != PsGetCurrentProcessWin32Process()) { ERR("Desktop Window...\n"); return FALSE; } + bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y); WinPos.hwnd = Window->head.h; @@ -1255,8 +1400,8 @@ co_WinPosSetWindowPos( /* Fix up the flags. */ if (!WinPosFixupFlags(&WinPos, Window)) { - EngSetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + // See Note. + return TRUE; } Ancestor = UserGetAncestor(Window, GA_PARENT); @@ -1566,17 +1711,18 @@ co_WinPosSetWindowPos( { GreDeleteObject(VisAfter); } + } - if (!(WinPos.flags & SWP_NOACTIVATE)) + if (!(WinPos.flags & SWP_NOACTIVATE))//(SWP_NOACTIVATE|SWP_HIDEWINDOW))) + { + if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) { - if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) - { - co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0); - } - else - { - co_IntSetForegroundWindow(Window); - } + co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0); + } + else + { + TRACE("SetWindowPos Set FG Window!\n"); + co_IntSetForegroundWindow(Window); } } @@ -1622,7 +1768,7 @@ co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect) ASSERT_REFS_CO(Window); *ClientRect = *WindowRect; - Result = co_IntSendMessage(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect); + Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect); FixClientRect(ClientRect, WindowRect); @@ -1656,6 +1802,7 @@ co_WinPosSendSizeMove(PWND Wnd) lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top); co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam); + IntEngWindowChanged(Wnd, WOC_RGN_CLIENT); } @@ -1667,6 +1814,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) RECTL NewPos; BOOLEAN ShowFlag; LONG style; + PWND Parent; // HRGN VisibleRgn; ASSERT_REFS_CO(Wnd); @@ -1782,45 +1930,41 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) { 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); + co_IntSetActiveWindow(Wnd,NULL,FALSE,TRUE); 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)); + + co_WinPosSetWindowPos( Wnd, + 0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP, + NewPos.left, + NewPos.top, + NewPos.right, //NewPos.right - NewPos.left, + NewPos.bottom, //NewPos.bottom - NewPos.top, + LOWORD(Swp)); if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE)) { - PWND ThreadFocusWindow; + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); - /* FIXME: This will cause the window to be activated irrespective - * of whether it is owned by the same thread. Has to be done - * asynchronously. - */ - - if (Wnd->head.h == UserGetActiveWindow()) + // and Rule #1. + if (Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue()) { co_WinPosActivateOtherWindow(Wnd); } - - // Temp HACK - ThreadFocusWindow = UserGetWindowObject(IntGetThreadFocusWindow()); - /* Revert focus to parent */ -/* if (ThreadFocusWindow && (Wnd == ThreadFocusWindow || - IntIsChildWindow(Wnd, ThreadFocusWindow))) -*/ - if (Wnd == ThreadFocusWindow) + if (Wnd == pti->MessageQueue->spwndFocus) { - // FIXME: As long as we have ref on Window, we also, indirectly, have ref on parent... - co_UserSetFocus(Wnd->spwndParent); + Parent = Wnd->spwndParent; + if (Wnd->spwndParent == UserGetDesktopWindow()) Parent = 0; + co_UserSetFocus(Parent); } } @@ -2198,9 +2342,9 @@ NtUserDeferWindowPos(HDWP WinPosInfo, } pWnd = UserGetWindowObject(Wnd); - if ( !pWnd || // FIXME: - pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - pWnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + if ( !pWnd || // FIXME: + pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { goto Exit; } @@ -2212,8 +2356,8 @@ NtUserDeferWindowPos(HDWP WinPosInfo, { pWndIA = UserGetWindowObject(WndInsertAfter); if ( !pWndIA || - pWndIA == IntGetDesktopWindow() || - pWndIA == IntGetMessageWindow() ) + pWndIA == UserGetDesktopWindow() || + pWndIA == UserGetMessageWindow() ) { goto Exit; } @@ -2364,9 +2508,9 @@ NtUserMinMaximize( UserEnterExclusive(); pWnd = UserGetWindowObject(hWnd); - if ( !pWnd || // FIXME: - pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - pWnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + if ( !pWnd || // FIXME: + pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { goto Exit; } @@ -2385,8 +2529,8 @@ NtUserMinMaximize( NULL, NewPos.left, NewPos.top, - NewPos.right, - NewPos.bottom, + NewPos.right, //NewPos.right - NewPos.left, + NewPos.bottom, //NewPos.bottom - NewPos.top, SwFlags); co_WinPosShowWindow(pWnd, cmd); @@ -2436,9 +2580,11 @@ NtUserSetWindowPos( UserEnterExclusive(); if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: - Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND +// Due to desktopbg.c +// Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { + ERR("NtUserSetWindowPos bad window handle!\n"); RETURN(FALSE); } @@ -2447,11 +2593,11 @@ NtUserSetWindowPos( hWndInsertAfter != HWND_TOPMOST && hWndInsertAfter != HWND_NOTOPMOST ) { - pWndIA = UserGetWindowObject(hWndInsertAfter); - if ( !pWndIA || - pWndIA == IntGetDesktopWindow() || - pWndIA == IntGetMessageWindow() ) + if (!(pWndIA = UserGetWindowObject(hWndInsertAfter)) || + pWndIA == UserGetDesktopWindow() || + pWndIA == UserGetMessageWindow() ) { + ERR("NtUserSetWindowPos bad insert window handle!\n"); RETURN(FALSE); } } @@ -2503,8 +2649,8 @@ NtUserSetWindowRgn( UserEnterExclusive(); if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: - Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN( 0); } @@ -2572,8 +2718,8 @@ NtUserSetInternalWindowPos( UserEnterExclusive(); if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME: - Wnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Wnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + Wnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + Wnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN( FALSE); } @@ -2642,8 +2788,8 @@ NtUserSetWindowPlacement(HWND hWnd, UserEnterExclusive(); if (!(Wnd = UserGetWindowObject(hWnd)) || // FIXME: - Wnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Wnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + Wnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + Wnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN( FALSE); } @@ -2693,8 +2839,8 @@ NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow) UserEnterExclusive(); if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: - Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN(FALSE); } @@ -2733,8 +2879,8 @@ NtUserShowWindow(HWND hWnd, LONG nCmdShow) UserEnterExclusive(); if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: - Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP - Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND + Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN(FALSE); } diff --git a/reactos/win32ss/user/user32/include/ntwrapper.h b/reactos/win32ss/user/user32/include/ntwrapper.h index 7e7873d3cc0..2245003afb8 100644 --- a/reactos/win32ss/user/user32/include/ntwrapper.h +++ b/reactos/win32ss/user/user32/include/ntwrapper.h @@ -809,3 +809,13 @@ EXTINLINE BOOL NtUserxRegisterLogonProcess(DWORD dwProcessId, BOOL bRegister) { return (BOOL)NtUserCallTwoParam((DWORD_PTR)dwProcessId, (DWORD_PTR)bRegister, TWOPARAM_ROUTINE_REGISTERLOGONPROCESS); } + +EXTINLINE BOOL NtUserxAllowSetForegroundWindow(DWORD dwProcessId) +{ + return (BOOL)NtUserCallOneParam((DWORD_PTR)dwProcessId, ONEPARAM_ROUTINE_ALLOWSETFOREGND); +} + +EXTINLINE BOOL NtUserxLockSetForegroundWindow(UINT uLockCode) +{ + return (BOOL)NtUserCallOneParam((DWORD_PTR)uLockCode, ONEPARAM_ROUTINE_LOCKFOREGNDWINDOW); +} diff --git a/reactos/win32ss/user/user32/include/user32p.h b/reactos/win32ss/user/user32/include/user32p.h index b7d8affdb43..b4ec23d4b82 100644 --- a/reactos/win32ss/user/user32/include/user32p.h +++ b/reactos/win32ss/user/user32/include/user32p.h @@ -84,6 +84,7 @@ VOID MenuTrackMouseMenuBar(HWND hWnd, ULONG Ht, POINT Pt); VOID MenuTrackKbdMenuBar(HWND hWnd, UINT wParam, WCHAR wChar); /* misc definitions */ +void mirror_rect( const RECT *window_rect, RECT *rect ); BOOL FASTCALL DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi); VOID FASTCALL ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt); HCURSOR CursorIconToCursor(HICON hIcon, BOOL SemiTransparent); diff --git a/reactos/win32ss/user/user32/windows/window.c b/reactos/win32ss/user/user32/windows/window.c index 6a594862818..81b9e3cce73 100644 --- a/reactos/win32ss/user/user32/windows/window.c +++ b/reactos/win32ss/user/user32/windows/window.c @@ -44,18 +44,12 @@ User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength) /* - * @unimplemented + * @implemented */ BOOL WINAPI AllowSetForegroundWindow(DWORD dwProcessId) { - static BOOL show_message = TRUE; - if (show_message) - { - UNIMPLEMENTED; - show_message = FALSE; - } - return TRUE; + return NtUserxAllowSetForegroundWindow(dwProcessId); } @@ -1002,8 +996,11 @@ GetLastActivePopup(HWND hWnd) { _SEH2_TRY { - if (Wnd->hWndLastActive) - Ret = Wnd->hWndLastActive; + if (Wnd->spwndLastActive) + { + PWND LastActive = DesktopPtrToUser(Wnd->spwndLastActive); + Ret = UserHMGetHandle(LastActive); + } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1627,13 +1624,12 @@ IsZoomed(HWND hWnd) /* - * @unimplemented + * @implemented */ BOOL WINAPI LockSetForegroundWindow(UINT uLockCode) { - UNIMPLEMENTED; - return TRUE; + return NtUserxLockSetForegroundWindow(uLockCode); } diff --git a/reactos/win32ss/user/user32/windows/winpos.c b/reactos/win32ss/user/user32/windows/winpos.c index a6c04cfc989..1ea3d01f2e1 100644 --- a/reactos/win32ss/user/user32/windows/winpos.c +++ b/reactos/win32ss/user/user32/windows/winpos.c @@ -15,6 +15,14 @@ #include WINE_DEFAULT_DEBUG_CHANNEL(user32); +void mirror_rect( const RECT *window_rect, RECT *rect ) +{ + int width = window_rect->right - window_rect->left; + int tmp = rect->left; + rect->left = width - rect->right; + rect->right = width - tmp; +} + /* FUNCTIONS *****************************************************************/ /******************************************************************* @@ -206,7 +214,6 @@ WindowFromPoint(POINT Point) return NtUserWindowFromPoint(Point.x, Point.y); } - /* * @implemented */ @@ -217,6 +224,7 @@ MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints) BOOL mirror_from, mirror_to; POINT Delta; UINT i; + int Change = 1; if (hWndFrom) { @@ -240,7 +248,8 @@ MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints) if (FromWnd->ExStyle & WS_EX_LAYOUTRTL) { mirror_from = TRUE; - Delta.x = FromWnd->rcClient.right - FromWnd->rcClient.left; + Change = -Change; + Delta.x = -FromWnd->rcClient.right; } else Delta.x = FromWnd->rcClient.left; @@ -252,10 +261,11 @@ MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints) if (ToWnd->ExStyle & WS_EX_LAYOUTRTL) { mirror_to = TRUE; - Delta.x -= ToWnd->rcClient.right - ToWnd->rcClient.left; + Change = -Change; + Delta.x += Change * ToWnd->rcClient.right; } else - Delta.x -= ToWnd->rcClient.left; + Delta.x -= Change * ToWnd->rcClient.left; Delta.y -= ToWnd->rcClient.top; } @@ -264,21 +274,20 @@ MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints) for (i = 0; i != cPoints; i++) { lpPoints[i].x += Delta.x; + lpPoints[i].x *= Change; lpPoints[i].y += Delta.y; - if (mirror_from || mirror_to) lpPoints[i].x = -lpPoints[i].x; } if ((mirror_from || mirror_to) && cPoints == 2) /* special case for rectangle */ { - int tmp = lpPoints[0].x; - lpPoints[0].x = lpPoints[1].x; - lpPoints[1].x = tmp; + int tmp = min(lpPoints[0].x, lpPoints[1].x); + lpPoints[1].x = max(lpPoints[0].x, lpPoints[1].x); + lpPoints[0].x = tmp; } return MAKELONG(LOWORD(Delta.x), LOWORD(Delta.y)); } - /* * @implemented */ @@ -302,7 +311,6 @@ ScreenToClient(HWND hWnd, LPPOINT lpPoint) return TRUE; } - /* * @implemented */ @@ -325,4 +333,3 @@ ClientToScreen(HWND hWnd, LPPOINT lpPoint) } return TRUE; } -