[Win32SS]

- Desktop: Added code for server side switch over and some notes. Did not include desktopbg.c.
- Focus: Fixes wine Win tests for SetParent, Active, Focus and Foreground. Leaving the wine todos. Msg tests improved. Pop up menus are still broken see bug 6751. The tests reflect these pop up menu issues.
- WinPos: (WIP) Fixed MapWindowPoints. Arrange icons is still broken. SetWindowPos sets the foreground when it should.
- Implemented AllowSetForegroundWindow and LockSetForegroundWindow.
- Commit to reset base lines for RegTest ComCtl32 and related bugs.
- Coding credits and complements go out to the Wine team.

svn path=/trunk/; revision=56396
This commit is contained in:
James Tabor 2012-04-23 18:51:48 +00:00
parent 7f3808dd4f
commit 3e02fbea93
21 changed files with 1048 additions and 690 deletions

View file

@ -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;

View file

@ -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());

View file

@ -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,

View file

@ -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_);

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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();

View file

@ -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;
}

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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:

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -15,6 +15,14 @@
#include <wine/debug.h>
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;
}