[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; LARGE_UNICODE_STRING strName;
/* Size of the extra data associated with the window. */ /* Size of the extra data associated with the window. */
ULONG cbwndExtra; ULONG cbwndExtra;
HWND hWndLastActive;
struct _WND *spwndLastActive; struct _WND *spwndLastActive;
//HIMC hImc; // Input context associated with this window. //HIMC hImc; // Input context associated with this window.
LONG dwUserData; LONG dwUserData;

View file

@ -462,7 +462,10 @@ IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
{ {
(void)InterlockedExchangePointer((PVOID*)&Old->Desktop, 0); (void)InterlockedExchangePointer((PVOID*)&Old->Desktop, 0);
IntDereferenceMessageQueue(Old); 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) HWND FASTCALL IntGetDesktopWindow(VOID)
@ -485,7 +488,7 @@ PWND FASTCALL UserGetDesktopWindow(VOID)
TRACE("No active desktop\n"); TRACE("No active desktop\n");
return NULL; return NULL;
} }
// return pdo->pDeskInfo->spwnd;
return UserGetWindowObject(pdo->DesktopWindow); return UserGetWindowObject(pdo->DesktopWindow);
} }
@ -501,6 +504,18 @@ HWND FASTCALL IntGetMessageWindow(VOID)
return pdo->spwndMessage->head.h; 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) HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
{ {
PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
@ -558,6 +573,7 @@ UserRedrawDesktop()
NTSTATUS FASTCALL NTSTATUS FASTCALL
co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height) co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height)
{ {
//#if 0
CSR_API_MESSAGE Request; CSR_API_MESSAGE Request;
Request.Type = MAKE_CSR_API(SHOW_DESKTOP, CSR_GUI); 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; Request.Data.ShowDesktopRequest.Height = Height;
return co_CsrNotify(&Request); 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 NTSTATUS FASTCALL
IntHideDesktop(PDESKTOP Desktop) 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; PWND DesktopWnd;
DesktopWnd = IntGetWindowObject(Desktop->DesktopWindow); DesktopWnd = IntGetWindowObject(Desktop->DesktopWindow);
@ -591,12 +613,8 @@ IntHideDesktop(PDESKTOP Desktop)
DesktopWnd->style &= ~WS_VISIBLE; DesktopWnd->style &= ~WS_VISIBLE;
return STATUS_SUCCESS; return STATUS_SUCCESS;
#endif
} }
static static
HWND* FASTCALL HWND* FASTCALL
UserBuildShellHookHwndList(PDESKTOP Desktop) UserBuildShellHookHwndList(PDESKTOP Desktop)
@ -637,14 +655,6 @@ VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
if (!gpsi->uiShellMsg) 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"); gpsi->uiShellMsg = IntAddAtom(L"SHELLHOOK");
TRACE("MsgType = %x\n", gpsi->uiShellMsg); TRACE("MsgType = %x\n", gpsi->uiShellMsg);
@ -745,6 +755,216 @@ IntFreeDesktopHeap(IN OUT PDESKTOP Desktop)
Desktop->hsectionDesktop = NULL; 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 *******************************************************************/ /* SYSCALLS *******************************************************************/
/* /*
@ -911,15 +1131,15 @@ NtUserCreateDesktop(
/* Initialize some local (to win32k) desktop state. */ /* Initialize some local (to win32k) desktop state. */
InitializeListHead(&DesktopObject->PtiList); InitializeListHead(&DesktopObject->PtiList);
DesktopObject->ActiveMessageQueue = NULL; DesktopObject->ActiveMessageQueue = NULL;
/* Setup Global Hooks. */ /* Setup Global Hooks. */
for (i = 0; i < NB_HOOKS; i++) for (i = 0; i < NB_HOOKS; i++)
{ {
InitializeListHead(&DesktopObject->pDeskInfo->aphkStart[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); Request.Type = MAKE_CSR_API(CREATE_DESKTOP, CSR_GUI);
Status = CsrInsertObject(Desktop, Status = CsrInsertObject(Desktop,
@ -942,10 +1162,23 @@ NtUserCreateDesktop(
SetLastNtError(Status); SetLastNtError(Status);
RETURN( NULL); 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. // 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.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_DESKTOP])));
ClassName.Length = 0; ClassName.Length = 0;
RtlZeroMemory(&WindowName, sizeof(WindowName)); RtlZeroMemory(&WindowName, sizeof(WindowName));
@ -956,27 +1189,24 @@ NtUserCreateDesktop(
Cs.cx = UserGetSystemMetrics(SM_CXVIRTUALSCREEN); Cs.cx = UserGetSystemMetrics(SM_CXVIRTUALSCREEN);
Cs.cy = UserGetSystemMetrics(SM_CYVIRTUALSCREEN); Cs.cy = UserGetSystemMetrics(SM_CYVIRTUALSCREEN);
Cs.style = WS_POPUP|WS_CLIPCHILDREN; 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.lpszName = (LPCWSTR) &WindowName;
Cs.lpszClass = (LPCWSTR) &ClassName; Cs.lpszClass = (LPCWSTR) &ClassName;
pWndDesktop = co_UserCreateWindowEx(&Cs, &ClassName, &WindowName, NULL); pWnd = co_UserCreateWindowEx(&Cs, &ClassName, &WindowName, NULL);
if (!pWnd) if (!pWnd)
{ {
ERR("Failed to create Desktop window handle\n"); ERR("Failed to create Desktop window handle\n");
} }
else else
{ // Should be set in window.c, Justin Case,
if (!DesktopObject->DesktopWindow)
{ {
DesktopObject->pDeskInfo->spwnd = pWndDesktop; DesktopObject->pDeskInfo->spwnd = pWnd;
DesktopObject->DesktopWindow = UserHMGetHandle(pWnd);
}
} }
#endif #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.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_HWNDMESSAGE])));
ClassName.Length = 0; ClassName.Length = 0;
RtlZeroMemory(&WindowName, sizeof(WindowName)); RtlZeroMemory(&WindowName, sizeof(WindowName));
@ -1207,9 +1437,6 @@ CLEANUP:
END_CLEANUP; END_CLEANUP;
} }
/* /*
* NtUserPaintDesktop * NtUserPaintDesktop
* *
@ -1228,221 +1455,15 @@ CLEANUP:
BOOL APIENTRY BOOL APIENTRY
NtUserPaintDesktop(HDC hDC) NtUserPaintDesktop(HDC hDC)
{ {
RECTL Rect; BOOL Ret;
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);
UserEnterExclusive(); UserEnterExclusive();
TRACE("Enter NtUserPaintDesktop\n"); TRACE("Enter NtUserPaintDesktop\n");
Ret = IntPaintDesktop(hDC);
GdiGetClipBox(hDC, &Rect); TRACE("Leave NtUserPaintDesktop, ret=%i\n",Ret);
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_);
UserLeave(); UserLeave();
END_CLEANUP; return Ret;
} }
/* /*
* NtUserSwitchDesktop * NtUserSwitchDesktop
* *
@ -1720,7 +1741,7 @@ IntSetThreadDesktop(IN HDESK hDesktop,
HDESK hdeskOld; HDESK hdeskOld;
PTHREADINFO pti; PTHREADINFO pti;
NTSTATUS Status; NTSTATUS Status;
PCLIENTTHREADINFO pctiOld, pctiNew; PCLIENTTHREADINFO pctiOld, pctiNew = NULL;
PCLIENTINFO pci; PCLIENTINFO pci;
ASSERT(NtCurrentTeb()); ASSERT(NtCurrentTeb());

View file

@ -23,7 +23,7 @@ typedef struct _DESKTOP
/* ReactOS */ /* ReactOS */
/* Pointer to the active queue. */ /* Pointer to the active queue. */
PVOID ActiveMessageQueue; struct _USER_MESSAGE_QUEUE *ActiveMessageQueue;
/* Handle of the desktop window. */ /* Handle of the desktop window. */
HWND DesktopWindow; HWND DesktopWindow;
/* Thread blocking input */ /* Thread blocking input */
@ -158,6 +158,7 @@ HDC FASTCALL UserGetDesktopDC(ULONG,BOOL,BOOL);
NULL NULL
HWND FASTCALL IntGetMessageWindow(VOID); HWND FASTCALL IntGetMessageWindow(VOID);
PWND FASTCALL UserGetMessageWindow(VOID);
static __inline PVOID static __inline PVOID
DesktopHeapAlloc(IN PDESKTOP Desktop, DesktopHeapAlloc(IN PDESKTOP Desktop,

View file

@ -11,6 +11,19 @@ DBG_DEFAULT_CHANNEL(UserFocus);
PUSER_MESSAGE_QUEUE gpqForeground = NULL; PUSER_MESSAGE_QUEUE gpqForeground = NULL;
PUSER_MESSAGE_QUEUE gpqForegroundPrev = 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 HWND FASTCALL
IntGetCaptureWindow(VOID) IntGetCaptureWindow(VOID)
@ -19,20 +32,6 @@ IntGetCaptureWindow(VOID)
return ForegroundQueue != NULL ? ForegroundQueue->CaptureWindow : 0; 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 HWND FASTCALL
IntGetThreadFocusWindow(VOID) IntGetThreadFocusWindow(VOID)
{ {
@ -43,7 +42,7 @@ IntGetThreadFocusWindow(VOID)
ThreadQueue = pti->MessageQueue; ThreadQueue = pti->MessageQueue;
if (!ThreadQueue) if (!ThreadQueue)
return NULL; return NULL;
return ThreadQueue->FocusWindow; return ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0;
} }
VOID FASTCALL 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 VOID FASTCALL
co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate) co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
{ {
USER_REFERENCE_ENTRY Ref, RefPrev; USER_REFERENCE_ENTRY Ref, RefPrev;
PWND Window, WindowPrev = NULL; PWND Window, WindowPrev = NULL;
HANDLE OldTID, NewTID;
if ((Window = UserGetWindowObject(hWnd))) if ((Window = UserGetWindowObject(hWnd)))
{ {
@ -94,33 +113,32 @@ co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
} }
if (Window) 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; Window->state |= WNDS_ACTIVEFRAME;
if (Window->style & WS_MINIMIZE)
{
TRACE("Widow was minimized\n");
}
} }
if (WindowPrev) if (WindowPrev)
WindowPrev->state &= ~WNDS_ACTIVEFRAME; WindowPrev->state &= ~WNDS_ACTIVEFRAME;
if (Window && WindowPrev) OldTID = WindowPrev ? IntGetWndThreadId(WindowPrev) : NULL;
{ NewTID = Window ? IntGetWndThreadId(Window) : NULL;
PWND cWindow;
HWND *List, *phWnd;
HANDLE OldTID = IntGetWndThreadId(WindowPrev);
HANDLE NewTID = IntGetWndThreadId(Window);
TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID); TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID);
if (Window->style & WS_MINIMIZE)
{
TRACE("Widow was minimized\n");
}
if (OldTID != NewTID) if (OldTID != NewTID)
{ {
PWND cWindow;
HWND *List, *phWnd;
List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow())); List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
if (List) if (List)
{
if (OldTID)
{ {
for (phWnd = List; *phWnd; ++phWnd) 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); co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID);
} }
} }
}
if (NewTID)
{
for (phWnd = List; *phWnd; ++phWnd) for (phWnd = List; *phWnd; ++phWnd)
{ {
cWindow = UserGetWindowObject(*phWnd); cWindow = UserGetWindowObject(*phWnd);
@ -141,11 +162,12 @@ co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID); co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID);
} }
} }
}
ExFreePool(List); ExFreePool(List);
} }
} }
if (WindowPrev)
UserDerefObjectCo(WindowPrev); // Now allow the previous window to die. UserDerefObjectCo(WindowPrev); // Now allow the previous window to die.
}
UserDerefObjectCo(Window); UserDerefObjectCo(Window);
@ -175,10 +197,13 @@ co_IntSendSetFocusMessages(HWND hWndPrev, HWND hWnd)
if (hWnd) if (hWnd)
{ {
PWND pWnd = UserGetWindowObject(hWnd); PWND pWnd = UserGetWindowObject(hWnd);
if (pWnd)
{
IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0); IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0); co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0);
} }
} }
}
HWND FASTCALL HWND FASTCALL
IntFindChildWindowToOwner(PWND Root, PWND Owner) IntFindChildWindowToOwner(PWND Root, PWND Owner)
@ -202,6 +227,23 @@ IntFindChildWindowToOwner(PWND Root, PWND Owner)
return NULL; 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: MSDN:
The system restricts which processes can set the foreground window. A process 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). * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
* No menus are active. * No menus are active.
*/ */
static BOOL FASTCALL static BOOL FASTCALL
co_IntSetForegroundAndFocusWindow(PWND Wnd, PWND FocusWindow, BOOL MouseActivate) co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate)
{ {
CBTACTIVATESTRUCT cbt; HWND hWnd = UserHMGetHandle(Wnd);
HWND hWnd = Wnd->head.h;
HWND hWndPrev = NULL; HWND hWndPrev = NULL;
HWND hWndFocus = FocusWindow->head.h;
HWND hWndFocusPrev = NULL;
PUSER_MESSAGE_QUEUE PrevForegroundQueue; PUSER_MESSAGE_QUEUE PrevForegroundQueue;
PTHREADINFO pti;
BOOL fgRet = FALSE, Ret = FALSE;
ASSERT_REFS_CO(Wnd); 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) 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)
{ {
TRACE("Failed - Child\n"); if (pti->MessageQueue == PrevForegroundQueue)
return FALSE; { // 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;
} }
if (0 == (Wnd->style & WS_VISIBLE) && hWndPrev = PrevForegroundQueue->spwndActive ? UserHMGetHandle(PrevForegroundQueue->spwndActive) : 0;
Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess)
{
ERR("Failed - Invisible\n");
return FALSE;
} }
PrevForegroundQueue = IntGetFocusMessageQueue(); if ( (( !IsFGLocked() || pti->ppi == gppiInputProvider ) &&
if (PrevForegroundQueue != 0) ( CanForceFG(pti->ppi) || pti->TIF_flags & (TIF_SYSTEMTHREAD|TIF_CSRSSTHREAD|TIF_ALLOWFOREGROUNDACTIVATE) )) ||
pti->ppi == ppiScrnSaver
)
{ {
hWndPrev = PrevForegroundQueue->ActiveWindow;
hWndFocusPrev = PrevForegroundQueue->FocusWindow;
}
if (hWndPrev == hWnd)
{
TRACE("Failed - Same\n");
return 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); IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue);
gptiForeground = Wnd->head.pti;
if (Wnd->head.pti->MessageQueue) fgRet = TRUE;
{
Wnd->head.pti->MessageQueue->ActiveWindow = hWnd;
} }
if (FocusWindow->head.pti->MessageQueue) //// Fix FG Bounce with regedit but breaks test_SFW todos
if (hWndPrev != hWnd )
{ {
FocusWindow->head.pti->MessageQueue->FocusWindow = hWndFocus; if (PrevForegroundQueue &&
fgRet &&
Wnd->head.pti->MessageQueue != PrevForegroundQueue &&
PrevForegroundQueue->spwndActive)
{
co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 );
}
} }
if (PrevForegroundQueue != Wnd->head.pti->MessageQueue) if (pti->MessageQueue == Wnd->head.pti->MessageQueue)
{ {
/* FIXME: Send WM_ACTIVATEAPP to all thread windows. */ 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;
} }
co_IntSendSetFocusMessages(hWndFocusPrev, hWndFocus); return Ret && fgRet;
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);
} }
BOOL FASTCALL BOOL FASTCALL
@ -329,22 +366,21 @@ co_IntMouseActivateWindow(PWND Wnd)
return FALSE; return FALSE;
} }
TopWindow = UserGetAncestor(Wnd, GA_ROOT); TopWindow = UserGetAncestor(Wnd, GA_ROOT);
if (!TopWindow) return FALSE; if (!TopWindow) return FALSE;
/* TMN: Check return valud from this function? */ /* TMN: Check return valud from this function? */
UserRefObjectCo(TopWindow, &Ref); UserRefObjectCo(TopWindow, &Ref);
co_IntSetForegroundAndFocusWindow(TopWindow, Wnd, TRUE); co_IntSetForegroundAndFocusWindow(TopWindow, TRUE);
UserDerefObjectCo(TopWindow); UserDerefObjectCo(TopWindow);
return TRUE; return TRUE;
} }
HWND FASTCALL BOOL FASTCALL
co_IntSetActiveWindow(PWND Wnd OPTIONAL) co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus)
{ {
PTHREADINFO pti; PTHREADINFO pti;
PUSER_MESSAGE_QUEUE ThreadQueue; PUSER_MESSAGE_QUEUE ThreadQueue;
@ -353,46 +389,79 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL)
CBTACTIVATESTRUCT cbt; CBTACTIVATESTRUCT cbt;
if (Wnd) if (Wnd)
{
ASSERT_REFS_CO(Wnd); ASSERT_REFS_CO(Wnd);
hWnd = UserHMGetHandle(Wnd);
}
pti = PsGetCurrentThreadWin32Thread(); pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue; ThreadQueue = pti->MessageQueue;
ASSERT(ThreadQueue != 0); ASSERT(ThreadQueue != 0);
if (Wnd != 0) hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL;
if (Prev) *Prev = hWndPrev;
if (hWndPrev == hWnd) return TRUE;
if (Wnd)
{ {
if ((Wnd->style & (WS_POPUP | WS_CHILD)) == WS_CHILD) if (ThreadQueue != Wnd->head.pti->MessageQueue)
{ {
/* Windows doesn't seem to return an error here */ PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
return ThreadQueue->ActiveWindow; // Rule 1 & 4, We are foreground so set this FG window or NULL foreground....
if (!ForegroundQueue || ForegroundQueue == ThreadQueue)
{
return co_IntSetForegroundAndFocusWindow(Wnd, bMouse);
} }
hWnd = Wnd->head.h;
} }
hWndPrev = ThreadQueue->ActiveWindow; if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE;
if (hWndPrev == hWnd)
{
return hWndPrev;
} }
/* Call CBT hook chain */ /* Call CBT hook chain */
cbt.fMouse = FALSE; cbt.fMouse = bMouse;
cbt.hWndActive = hWndPrev; cbt.hWndActive = hWndPrev;
if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
{ {
ERR("SetActiveWindow WH_CBT Call Hook return!\n"); ERR("SetActiveWindow WH_CBT Call Hook return!\n");
return 0; return FALSE;
} }
co_IntSendDeactivateMessages(hWndPrev, hWnd); 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 */ /* check if the specified window can be set in the input data of a given queue */
/* return IntIsWindow(hWndPrev) ? hWndPrev : 0;*/ if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue)
return hWndPrev; {
/* 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 HWND FASTCALL
@ -410,20 +479,33 @@ co_UserSetFocus(PWND Window)
ThreadQueue = pti->MessageQueue; ThreadQueue = pti->MessageQueue;
ASSERT(ThreadQueue != 0); ASSERT(ThreadQueue != 0);
hWndPrev = ThreadQueue->FocusWindow; hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0;
if (Window != 0) if (Window != 0)
{ {
if (hWndPrev == Window->head.h) if (hWndPrev == UserHMGetHandle(Window))
{ {
return hWndPrev; /* Nothing to do */ 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 */ /* 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_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)) 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. */ /* 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 */ /* Abort if window destroyed */
if (Window->state2 & WNDS2_INDESTROY) return 0; if (Window->state2 & WNDS2_INDESTROY) return 0;
/* Do not change focus if the window is no longer active */ /* 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"); ERR("SetFocus Top window did not go active!\n");
return 0; 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); TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h);
co_IntSendKillFocusMessages(hWndPrev, Window->head.h); co_IntSendKillFocusMessages(hWndPrev, Window->head.h);
co_IntSendSetFocusMessages(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)) if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
{ {
ERR("SetFocusWindow 2 WH_CBT Call Hook return!\n"); ERR("SetFocusWindow 2 WH_CBT Call Hook return!\n");
return 0; return 0;
} }
/* set the current thread focus window null */
ThreadQueue->spwndFocus = 0;
co_IntSendKillFocusMessages(hWndPrev, 0); co_IntSendKillFocusMessages(hWndPrev, 0);
} }
return hWndPrev; return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0;
} }
HWND FASTCALL HWND FASTCALL
@ -472,7 +580,7 @@ UserGetForegroundWindow(VOID)
PUSER_MESSAGE_QUEUE ForegroundQueue; PUSER_MESSAGE_QUEUE ForegroundQueue;
ForegroundQueue = IntGetFocusMessageQueue(); ForegroundQueue = IntGetFocusMessageQueue();
return( ForegroundQueue != NULL ? ForegroundQueue->ActiveWindow : 0); return( ForegroundQueue ? (ForegroundQueue->spwndActive ? UserHMGetHandle(ForegroundQueue->spwndActive) : 0) : 0);
} }
HWND FASTCALL UserGetActiveWindow(VOID) HWND FASTCALL UserGetActiveWindow(VOID)
@ -482,7 +590,7 @@ HWND FASTCALL UserGetActiveWindow(VOID)
pti = PsGetCurrentThreadWin32Thread(); pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue; ThreadQueue = pti->MessageQueue;
return( ThreadQueue ? ThreadQueue->ActiveWindow : 0); return( ThreadQueue ? (ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : 0) : 0);
} }
HWND APIENTRY HWND APIENTRY
@ -568,6 +676,9 @@ co_UserSetCapture(HWND hWnd)
return hWndPrev; return hWndPrev;
} }
/*
API Call
*/
BOOL BOOL
FASTCALL FASTCALL
IntReleaseCapture(VOID) IntReleaseCapture(VOID)
@ -586,6 +697,91 @@ IntReleaseCapture(VOID)
return TRUE; 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 * @implemented
*/ */
@ -609,42 +805,33 @@ HWND APIENTRY
NtUserSetActiveWindow(HWND hWnd) NtUserSetActiveWindow(HWND hWnd)
{ {
USER_REFERENCE_ENTRY Ref; USER_REFERENCE_ENTRY Ref;
HWND hWndPrev;
PWND Window;
DECLARE_RETURN(HWND); DECLARE_RETURN(HWND);
TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd); TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd);
UserEnterExclusive(); UserEnterExclusive();
Window = NULL;
if (hWnd) if (hWnd)
{ {
PWND Window;
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE ThreadQueue;
HWND hWndPrev;
if (!(Window = UserGetWindowObject(hWnd))) if (!(Window = UserGetWindowObject(hWnd)))
{ {
RETURN( 0); RETURN( 0);
} }
pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue;
if (Window->head.pti->MessageQueue != ThreadQueue)
{
EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
RETURN( 0);
} }
UserRefObjectCo(Window, &Ref); if (!Window ||
hWndPrev = co_IntSetActiveWindow(Window); Window->head.pti->MessageQueue == gptiCurrent->MessageQueue)
UserDerefObjectCo(Window); {
if (Window) UserRefObjectCo(Window, &Ref);
RETURN( hWndPrev); if (!co_IntSetActiveWindow(Window, &hWndPrev, FALSE, TRUE)) hWndPrev = NULL;
if (Window) UserDerefObjectCo(Window);
} }
else else
{ hWndPrev = NULL;
RETURN( co_IntSetActiveWindow(0));
} RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 );
CLEANUP: CLEANUP:
TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_); TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_);

View file

@ -1,5 +1,8 @@
#pragma once #pragma once
extern PUSER_MESSAGE_QUEUE gpqForeground;
extern PUSER_MESSAGE_QUEUE gpqForegroundPrev;
/* /*
* These functions take the window handles from current message queue. * These functions take the window handles from current message queue.
*/ */
@ -12,8 +15,9 @@ BOOL FASTCALL IntReleaseCapture(VOID);
*/ */
HWND FASTCALL IntGetThreadFocusWindow(VOID); HWND FASTCALL IntGetThreadFocusWindow(VOID);
HWND APIENTRY IntGetCapture(VOID); HWND APIENTRY IntGetCapture(VOID);
HWND FASTCALL UserGetFocusWindow(VOID);
HWND FASTCALL UserGetActiveWindow(VOID); HWND FASTCALL UserGetActiveWindow(VOID);
BOOL FASTCALL co_IntMouseActivateWindow(PWND Window); BOOL FASTCALL co_IntMouseActivateWindow(PWND Window);
BOOL FASTCALL co_IntSetForegroundWindow(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 else
{ {
PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
if (ForegroundQueue && ForegroundQueue->ActiveWindow) if (ForegroundQueue && ForegroundQueue->spwndActive)
UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 1); // lParam 1 == Secure UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 1); // lParam 1 == Secure
else else
UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 0); 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 // 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, WM_INPUTLANGCHANGE,
(WPARAM)pKl->iBaseCharset, // FIXME: How to set it? (WPARAM)pKl->iBaseCharset, // FIXME: How to set it?
(LPARAM)pKl->hkl); // hkl (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_MENU) &&
!IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL)) !IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL))
{ {
SnapWindow(pFocusQueue->FocusWindow); SnapWindow(pFocusQueue->spwndFocus ? UserHMGetHandle(pFocusQueue->spwndFocus) : 0);
} }
else else
SnapWindow(NULL); SnapWindow(NULL);
@ -859,7 +859,7 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d
else if (pFocusQueue && bPostMsg) else if (pFocusQueue && bPostMsg)
{ {
/* Init message */ /* 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.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */
Msg.lParam = MAKELPARAM(1, wScanCode); Msg.lParam = MAKELPARAM(1, wScanCode);
Msg.time = dwTime; Msg.time = dwTime;
@ -903,6 +903,8 @@ UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
DWORD dwTime; DWORD dwTime;
BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE; BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
gppiInputProvider = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->ppi;
/* Find the target thread whose locale is in effect */ /* Find the target thread whose locale is in effect */
pFocusQueue = IntGetFocusMessageQueue(); 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 ) static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPARAM lparam )
{ {
LRESULT lRes; LRESULT lRes;
USER_REFERENCE_ENTRY Ref;
if (!pWnd || if (!pWnd ||
pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
pWnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
return 0; return 0;
ERR("Internal Event Msg %p\n",msg); 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); ExFreePoolWithTag(winpos, USERTAG_SWP);
return lRes; 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; return 0;
} }

View file

@ -164,7 +164,7 @@ NtUserGetThreadState(
GetW32ThreadInfo(); GetW32ThreadInfo();
break; break;
case THREADSTATE_FOCUSWINDOW: case THREADSTATE_FOCUSWINDOW:
ret = (DWORD_PTR)UserGetFocusWindow(); ret = (DWORD_PTR)IntGetThreadFocusWindow();
break; break;
case THREADSTATE_CAPTUREWINDOW: case THREADSTATE_CAPTUREWINDOW:
/* FIXME: Should use UserEnterShared */ /* FIXME: Should use UserEnterShared */
@ -350,8 +350,8 @@ NtUserGetGUIThreadInfo(
/* FIXME: Add flag GUI_16BITTASK */ /* FIXME: Add flag GUI_16BITTASK */
SafeGui.hwndActive = MsgQueue->ActiveWindow; SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0;
SafeGui.hwndFocus = MsgQueue->FocusWindow; SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0;
SafeGui.hwndCapture = MsgQueue->CaptureWindow; SafeGui.hwndCapture = MsgQueue->CaptureWindow;
SafeGui.hwndMenuOwner = MsgQueue->MenuOwner; SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
SafeGui.hwndMoveSize = MsgQueue->MoveSize; SafeGui.hwndMoveSize = MsgQueue->MoveSize;

View file

@ -178,6 +178,8 @@ UserSendMouseInput(MOUSEINPUT *pmi, BOOL bInjected)
ptCursor = gpsi->ptCursor; ptCursor = gpsi->ptCursor;
dwFlags = IntFixMouseInputButtons(pmi->dwFlags); dwFlags = IntFixMouseInputButtons(pmi->dwFlags);
gppiInputProvider = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->ppi;
if (pmi->dwFlags & MOUSEEVENTF_MOVE) if (pmi->dwFlags & MOUSEEVENTF_MOVE)
{ {
/* Mouse has changes position */ /* Mouse has changes position */

View file

@ -717,8 +717,8 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
(HHOOK)Message->Msg.lParam, (HHOOK)Message->Msg.lParam,
Message->Msg.wParam); Message->Msg.wParam);
} }
else if ((Message->CompletionCallback) else if ((Message->CompletionCallback) &&
&& (Message->CallBackSenderQueue == MessageQueue)) (Message->CallBackSenderQueue == MessageQueue))
{ /* Call the callback routine */ { /* Call the callback routine */
if (Message->QS_Flags & QS_SMRESULT) if (Message->QS_Flags & QS_SMRESULT)
{ {
@ -982,14 +982,6 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
PLIST_ENTRY Entry; PLIST_ENTRY Entry;
LRESULT Result = 0; //// Result could be trashed. //// 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(); pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue; ThreadQueue = pti->MessageQueue;
ptirec = MessageQueue->Thread->Tcb.Win32Thread; ptirec = MessageQueue->Thread->Tcb.Win32Thread;
@ -999,10 +991,45 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
/* Don't send from or to a dying thread */ /* Don't send from or to a dying thread */
if (pti->TIF_flags & TIF_INCLEANUP || ptirec->TIF_flags & TIF_INCLEANUP) if (pti->TIF_flags & TIF_INCLEANUP || ptirec->TIF_flags & TIF_INCLEANUP)
{ {
*uResult = -1; if (uResult) *uResult = -1;
return STATUS_TIMEOUT; 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; Timeout.QuadPart = (LONGLONG) uTimeout * (LONGLONG) -10000;
/* FIXME: Increase reference counter of sender's message queue here */ /* 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 ) 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 has to be in the client coordinates of the parent window */
pt.x += pwndDesktop->rcClient.left - pwnd->rcClient.left; pt.x += pwndDesktop->rcClient.left - pwnd->rcClient.left;
@ -1231,7 +1258,7 @@ FASTCALL
IntTrackMouseMove(PWND pwndTrack, PDESKTOP pDesk, PMSG msg, USHORT hittest) IntTrackMouseMove(PWND pwndTrack, PDESKTOP pDesk, PMSG msg, USHORT hittest)
{ {
// PWND pwndTrack = IntChildrenWindowFromPoint(pwndMsg, msg->pt.x, msg->pt.y); // 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 if ( pDesk->spwndTrack != pwndTrack || // Change with tracking window or
msg->message != WM_MOUSEMOVE || // Mouse click changes or msg->message != WM_MOUSEMOVE || // Mouse click changes or
@ -1836,7 +1863,7 @@ MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQu
MessageQueue->QuitExitCode = 0; MessageQueue->QuitExitCode = 0;
KeQueryTickCount(&LargeTickCount); KeQueryTickCount(&LargeTickCount);
MessageQueue->LastMsgRead = LargeTickCount.u.LowPart; MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
MessageQueue->FocusWindow = NULL; MessageQueue->spwndFocus = NULL;
MessageQueue->NewMessagesHandle = NULL; MessageQueue->NewMessagesHandle = NULL;
MessageQueue->ShowingCursor = 0; MessageQueue->ShowingCursor = 0;
MessageQueue->CursorObject = NULL; MessageQueue->CursorObject = NULL;
@ -2146,12 +2173,12 @@ MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd)
MessageQueue->CaptureWindow = hWnd; MessageQueue->CaptureWindow = hWnd;
return Prev; return Prev;
case MSQ_STATE_ACTIVE: case MSQ_STATE_ACTIVE:
Prev = MessageQueue->ActiveWindow; Prev = MessageQueue->spwndActive ? UserHMGetHandle(MessageQueue->spwndActive) : 0;
MessageQueue->ActiveWindow = hWnd; MessageQueue->spwndActive = UserGetWindowObject(hWnd);
return Prev; return Prev;
case MSQ_STATE_FOCUS: case MSQ_STATE_FOCUS:
Prev = MessageQueue->FocusWindow; Prev = MessageQueue->spwndFocus ? UserHMGetHandle(MessageQueue->spwndFocus) : 0;
MessageQueue->FocusWindow = hWnd; MessageQueue->spwndFocus = UserGetWindowObject(hWnd);
return Prev; return Prev;
case MSQ_STATE_MENUOWNER: case MSQ_STATE_MENUOWNER:
Prev = MessageQueue->MenuOwner; Prev = MessageQueue->MenuOwner;

View file

@ -78,10 +78,8 @@ typedef struct _USER_MESSAGE_QUEUE
HWND CaptureWindow; HWND CaptureWindow;
PWND spwndCapture; PWND spwndCapture;
/* Current window with focus (ie. receives keyboard input) for this queue. */ /* Current window with focus (ie. receives keyboard input) for this queue. */
HWND FocusWindow;
PWND spwndFocus; PWND spwndFocus;
/* Current active window for this queue. */ /* Current active window for this queue. */
HWND ActiveWindow;
PWND spwndActive; PWND spwndActive;
PWND spwndActivePrev; PWND spwndActivePrev;
/* Current move/size window for this queue */ /* Current move/size window for this queue */
@ -146,7 +144,8 @@ typedef struct _USER_MESSAGE_QUEUE
enum internal_event_message enum internal_event_message
{ {
WM_ASYNC_SHOWWINDOW = 0x80000000, WM_ASYNC_SHOWWINDOW = 0x80000000,
WM_ASYNC_SETWINDOWPOS WM_ASYNC_SETWINDOWPOS,
WM_ASYNC_SETACTIVEWINDOW
}; };
BOOL FASTCALL MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue); BOOL FASTCALL MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue);

View file

@ -380,6 +380,10 @@ NtUserCallOneParam(
/* TODO: Implement sound sentry */ /* TODO: Implement sound sentry */
case ONEPARAM_ROUTINE_CREATESYSTEMTHREADS: case ONEPARAM_ROUTINE_CREATESYSTEMTHREADS:
RETURN(CreateSystemThreads(Param)); 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", ERR("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n",
Routine, Param); Routine, Param);

View file

@ -17,6 +17,7 @@
#define W32PF_CLASSESREGISTERED 0x00002000 #define W32PF_CLASSESREGISTERED 0x00002000
#define W32PF_THREADCONNECTED 0x00004000 #define W32PF_THREADCONNECTED 0x00004000
#define W32PF_PROCESSCONNECTED 0x00008000 #define W32PF_PROCESSCONNECTED 0x00008000
#define W32PF_SETFOREGROUNDALLOWED 0x00008000
#define W32PF_WAKEWOWEXEC 0x00010000 #define W32PF_WAKEWOWEXEC 0x00010000
#define W32PF_WAITFORINPUTIDLE 0x00020000 #define W32PF_WAITFORINPUTIDLE 0x00020000
#define W32PF_IOWINSTA 0x00040000 #define W32PF_IOWINSTA 0x00040000

View file

@ -499,33 +499,6 @@ static LRESULT co_UserFreeWindow(PWND Window,
return 0; 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. // 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 PMENU_OBJECT FASTCALL
IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) 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) VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
{ {
if (hWndPrev == HWND_NOTOPMOST) if (hWndPrev == HWND_NOTOPMOST)
@ -1626,7 +1566,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
pWnd->spwndParent = ParentWindow; pWnd->spwndParent = ParentWindow;
pWnd->spwndOwner = OwnerWindow; pWnd->spwndOwner = OwnerWindow;
pWnd->fnid = 0; pWnd->fnid = 0;
pWnd->hWndLastActive = hWnd; pWnd->spwndLastActive = pWnd;
pWnd->state2 |= WNDS2_WIN40COMPAT; // FIXME!!! pWnd->state2 |= WNDS2_WIN40COMPAT; // FIXME!!!
pWnd->pcls = Class; pWnd->pcls = Class;
pWnd->hModule = Cs->hInstance; pWnd->hModule = Cs->hInstance;
@ -1754,14 +1694,15 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
} }
} }
/* /* WS_EX_WINDOWEDGE depends on some other styles */
* WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so if (pWnd->ExStyle & WS_EX_DLGMODALFRAME)
* 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; 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 else
pWnd->ExStyle &= ~WS_EX_WINDOWEDGE; pWnd->ExStyle &= ~WS_EX_WINDOWEDGE;
@ -2061,6 +2002,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
Window->rcWindow.bottom = Cs->y + Size.cy; Window->rcWindow.bottom = Cs->y + Size.cy;
if (0 != (Window->style & WS_CHILD) && ParentWindow) if (0 != (Window->style & WS_CHILD) && ParentWindow)
{ {
// ERR("co_UserCreateWindowEx(): Offset rcWindow\n");
RECTL_vOffsetRect(&Window->rcWindow, RECTL_vOffsetRect(&Window->rcWindow,
ParentWindow->rcClient.left, ParentWindow->rcClient.left,
ParentWindow->rcClient.top); ParentWindow->rcClient.top);
@ -2421,10 +2363,10 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
} }
} }
if (Window->head.pti->MessageQueue->ActiveWindow == Window->head.h) if (Window->head.pti->MessageQueue->spwndActive == Window)
Window->head.pti->MessageQueue->ActiveWindow = NULL; Window->head.pti->MessageQueue->spwndActive = NULL;
if (Window->head.pti->MessageQueue->FocusWindow == Window->head.h) if (Window->head.pti->MessageQueue->spwndFocus == Window)
Window->head.pti->MessageQueue->FocusWindow = NULL; Window->head.pti->MessageQueue->spwndFocus = NULL;
if (Window->head.pti->MessageQueue->CaptureWindow == Window->head.h) if (Window->head.pti->MessageQueue->CaptureWindow == Window->head.h)
Window->head.pti->MessageQueue->CaptureWindow = NULL; Window->head.pti->MessageQueue->CaptureWindow = NULL;
@ -3519,11 +3461,11 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
break; break;
case QUERY_WINDOW_ACTIVE: 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; break;
case QUERY_WINDOW_FOCUS: 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; break;
case QUERY_WINDOW_ISHUNG: case QUERY_WINDOW_ISHUNG:

View file

@ -45,6 +45,97 @@ IntGetClientOrigin(PWND Window OPTIONAL, LPPOINT Point)
return TRUE; 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 * can_activate_window
@ -80,7 +171,7 @@ VOID FASTCALL
co_WinPosActivateOtherWindow(PWND Wnd) co_WinPosActivateOtherWindow(PWND Wnd)
{ {
PWND WndTo = NULL; PWND WndTo = NULL;
HWND Fg; HWND Fg, previous;
USER_REFERENCE_ENTRY Ref; USER_REFERENCE_ENTRY Ref;
ASSERT_REFS_CO(Wnd); ASSERT_REFS_CO(Wnd);
@ -122,32 +213,13 @@ done:
} }
} }
if (!co_IntSetActiveWindow(WndTo)) /* Ok for WndTo to be NULL here */ if (!co_IntSetActiveWindow(WndTo,&previous,FALSE,TRUE) || /* Ok for WndTo to be NULL here */
co_IntSetActiveWindow(0); !previous)
co_IntSetActiveWindow(0,NULL,FALSE,TRUE);
if (WndTo) UserDerefObjectCo(WndTo); 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 UINT
FASTCALL FASTCALL
co_WinPosArrangeIconicWindows(PWND parent) co_WinPosArrangeIconicWindows(PWND parent)
@ -165,13 +237,14 @@ co_WinPosArrangeIconicWindows(PWND parent)
} }
IntGetClientRect( parent, &rectParent ); IntGetClientRect( parent, &rectParent );
// FIXME: Support gspv.mm.iArrange.
x = rectParent.left; x = rectParent.left;
y = rectParent.bottom; y = rectParent.bottom;
xspacing = (UserGetSystemMetrics(SM_CXMINSPACING)/2)+UserGetSystemMetrics(SM_CXBORDER); xspacing = (UserGetSystemMetrics(SM_CXMINSPACING)/2)+UserGetSystemMetrics(SM_CXBORDER);
yspacing = (UserGetSystemMetrics(SM_CYMINSPACING)/2)+UserGetSystemMetrics(SM_CYBORDER); 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++) for(i = 0; List[i]; i++)
{ {
@ -194,6 +267,7 @@ co_WinPosArrangeIconicWindows(PWND parent)
Child->InternalPos.IconPos.x = sx; Child->InternalPos.IconPos.x = sx;
Child->InternalPos.IconPos.y = sy; Child->InternalPos.IconPos.y = sy;
Child->InternalPos.flags |= WPF_MININIT; Child->InternalPos.flags |= WPF_MININIT;
Child->InternalPos.flags &= ~WPF_SETMINPOSITION;
UserDerefObjectCo(Child); UserDerefObjectCo(Child);
@ -204,7 +278,7 @@ co_WinPosArrangeIconicWindows(PWND parent)
x = rectParent.left; x = rectParent.left;
y -= yspacing; y -= yspacing;
} }
TRACE("X:%d Y:%d\n",x,y); //ERR("X:%d Y:%d\n",x,y);
} }
} }
ExFreePool(List); ExFreePool(List);
@ -214,67 +288,63 @@ co_WinPosArrangeIconicWindows(PWND parent)
static VOID FASTCALL static VOID FASTCALL
WinPosFindIconPos(PWND Window, POINT *Pos) WinPosFindIconPos(PWND Window, POINT *Pos)
{ {
RECT rect, rectParent; RECT rectParent;
PWND pwndChild, pwndParent; PWND pwndChild, pwndParent;
HRGN hrgn, tmp; int x, y, xspacing, yspacing;
int xspacing, yspacing;
pwndParent = Window->spwndParent; pwndParent = Window->spwndParent;
if (pwndParent == UserGetDesktopWindow()) if (pwndParent == UserGetDesktopWindow())
{ {
/* ReactOS doesn't support iconic minimize to desktop */ /* ReactOS doesn't support iconic minimize to desktop */
Pos->x = Pos->y = -32000; Pos->x = Pos->y = -32000;
Window->InternalPos.flags |= WPF_MININIT;
Window->InternalPos.IconPos.x = Pos->x;
Window->InternalPos.IconPos.y = Pos->y;
return; return;
} }
IntGetClientRect( pwndParent, &rectParent ); IntGetClientRect( pwndParent, &rectParent );
if ((Pos->x >= rectParent.left) && ((Pos->x + UserGetSystemMetrics(SM_CXICON)) < rectParent.right) && // FIXME: Support gspv.mm.iArrange.
(Pos->y >= rectParent.top) && ((Pos->y + UserGetSystemMetrics(SM_CYICON)) < rectParent.bottom)) x = rectParent.left;
return; /* The icon already has a suitable position */ y = rectParent.bottom;
xspacing = UserGetSystemMetrics(SM_CXICONSPACING); xspacing = (UserGetSystemMetrics(SM_CXMINSPACING)/2)+UserGetSystemMetrics(SM_CXBORDER);
yspacing = UserGetSystemMetrics(SM_CYICONSPACING); yspacing = (UserGetSystemMetrics(SM_CYMINSPACING)/2)+UserGetSystemMetrics(SM_CYBORDER);
/* Check if another icon already occupies this spot */ //ERR("X:%d Y:%d XS:%d YS:%d\n",Pos->x,Pos->y,xspacing,yspacing);
/* FIXME: this is completely inefficient */
// 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) for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext)
{ {
if (pwndChild == Window) continue; 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) if (pwndChild->style & WS_VISIBLE)
{ {
for (rect.left = rectParent.left; rect.left <= rectParent.right - xspacing; rect.left += xspacing) //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 )
{ {
rect.right = rect.left + xspacing; if (x <= rectParent.right - UserGetSystemMetrics(SM_CXMINSPACING))
rect.top = rect.bottom - yspacing; x += xspacing;
if (!IntRectInRegion( hrgn, &rect )) else
{ {
/* No window was found, so it's OK for us */ x = rectParent.left;
Pos->x = rect.left + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2; y -= yspacing;
Pos->y = rect.top + (yspacing - UserGetSystemMetrics(SM_CYICON)) / 2; }
GreDeleteObject( hrgn ); Pos->x = x + UserGetSystemMetrics(SM_CXBORDER);
return; Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER);
} }
} }
} Window->InternalPos.IconPos.x = Pos->x;
GreDeleteObject( hrgn ); Window->InternalPos.IconPos.y = Pos->y;
Pos->x = Pos->y = 0; Window->InternalPos.flags |= WPF_MININIT;
//ERR("Position is set! X:%d Y:%d\n",Pos->x,Pos->y);
return; return;
} }
@ -324,16 +394,27 @@ WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect)
{ {
RECTL WorkArea; RECTL WorkArea;
PMONITOR pmonitor = UserMonitorFromRect(&Rect, MONITOR_DEFAULTTOPRIMARY ); PMONITOR pmonitor = UserMonitorFromRect(&Rect, MONITOR_DEFAULTTOPRIMARY );
// FIXME: support DPI aware, rcWorkDPI/Real etc.. // FIXME: support DPI aware, rcWorkDPI/Real etc..
if (!(Wnd->style & WS_MAXIMIZEBOX) || (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen)
WorkArea = pmonitor->rcMonitor; WorkArea = pmonitor->rcMonitor;
else
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; WorkArea = pmonitor->rcWork;
//ERR("rcWork\n");
}
}
Wnd->InternalPos.MaxPos.x = Rect.left - WorkArea.left; Wnd->InternalPos.MaxPos.x = Rect.left - WorkArea.left;
Wnd->InternalPos.MaxPos.y = Rect.top - WorkArea.top; 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 else
@ -472,7 +553,7 @@ IntSetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *wpl, UINT Flags)
if (Wnd->style & WS_MINIMIZE ) if (Wnd->style & WS_MINIMIZE )
{ {
if (Flags & PLACE_MIN) if (Flags & PLACE_MIN || Wnd->InternalPos.flags & WPF_SETMINPOSITION)
{ {
co_WinPosSetWindowPos(Wnd, HWND_TOP, co_WinPosSetWindowPos(Wnd, HWND_TOP,
wpl->ptMinPosition.x, wpl->ptMinPosition.y, 0, 0, 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->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
Wnd->style &= ~WS_MAXIMIZE; Wnd->style &= ~WS_MAXIMIZE;
SwpFlags |= SWP_STATECHANGED;
} }
else else
{ {
@ -560,8 +642,16 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE |
RDW_NOINTERNALPAINT); RDW_NOINTERNALPAINT);
Wnd->style |= WS_MINIMIZE; Wnd->style |= WS_MINIMIZE;
if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION))
Wnd->InternalPos.flags &= ~WPF_MININIT;
WinPosFindIconPos(Wnd, &wpl.ptMinPosition); 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, 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_CXMINIMIZED),
UserGetSystemMetrics(SM_CYMINIMIZED)); UserGetSystemMetrics(SM_CYMINIMIZED));
SwpFlags |= SWP_NOCOPYBITS; SwpFlags |= SWP_NOCOPYBITS;
@ -572,14 +662,18 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
{ {
co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); 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); wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
*/
if (Wnd->style & WS_MINIMIZE) if (Wnd->style & WS_MINIMIZE)
{ {
SwpFlags |= SWP_STATECHANGED;
Wnd->style &= ~WS_MINIMIZE; Wnd->style &= ~WS_MINIMIZE;
} }
Wnd->style |= WS_MAXIMIZE; 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; break;
} }
@ -591,14 +685,22 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED) if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED)
{ {
co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
SwpFlags |= SWP_STATECHANGED;
Wnd->style |= WS_MAXIMIZE; 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; break;
} }
else else
{ {
*NewPos = wpl.rcNormalPosition; *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->right -= NewPos->left;
NewPos->bottom -= NewPos->top; NewPos->bottom -= NewPos->top;
break; break;
@ -611,15 +713,19 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
return 0; return 0;
} }
Wnd->style &= ~WS_MAXIMIZE; Wnd->style &= ~WS_MAXIMIZE;
SwpFlags |= SWP_STATECHANGED;
Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
*NewPos = wpl.rcNormalPosition; *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->right -= NewPos->left;
NewPos->bottom -= NewPos->top; NewPos->bottom -= NewPos->top;
break; break;
} }
} }
} }
return(SwpFlags); return SwpFlags;
} }
BOOL BOOL
@ -639,6 +745,33 @@ UserHasWindowEdge(DWORD Style, DWORD ExStyle)
return FALSE; 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 VOID
UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient) UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
{ {
@ -767,6 +900,11 @@ co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
MinMax.ptMaxPosition.x = rc_work.left - xinc; MinMax.ptMaxPosition.x = rc_work.left - xinc;
MinMax.ptMaxPosition.y = rc_work.top - yinc; 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) 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; return FALSE;
} }
else else
@ -1228,11 +1372,12 @@ co_WinPosSetWindowPos(
*/ */
if ( Window->head.h == IntGetDesktopWindow() && if ( Window->head.h == IntGetDesktopWindow() &&
Window->head.pti->pEThread->ThreadsProcess != PsGetCurrentProcess()) Window->head.pti->ppi != PsGetCurrentProcessWin32Process())
{ {
ERR("Desktop Window...\n"); ERR("Desktop Window...\n");
return FALSE; return FALSE;
} }
bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y); bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y);
WinPos.hwnd = Window->head.h; WinPos.hwnd = Window->head.h;
@ -1255,8 +1400,8 @@ co_WinPosSetWindowPos(
/* Fix up the flags. */ /* Fix up the flags. */
if (!WinPosFixupFlags(&WinPos, Window)) if (!WinPosFixupFlags(&WinPos, Window))
{ {
EngSetLastError(ERROR_INVALID_PARAMETER); // See Note.
return FALSE; return TRUE;
} }
Ancestor = UserGetAncestor(Window, GA_PARENT); Ancestor = UserGetAncestor(Window, GA_PARENT);
@ -1566,8 +1711,9 @@ co_WinPosSetWindowPos(
{ {
GreDeleteObject(VisAfter); 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)
{ {
@ -1575,10 +1721,10 @@ co_WinPosSetWindowPos(
} }
else else
{ {
TRACE("SetWindowPos Set FG Window!\n");
co_IntSetForegroundWindow(Window); co_IntSetForegroundWindow(Window);
} }
} }
}
if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
{ {
@ -1622,7 +1768,7 @@ co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect)
ASSERT_REFS_CO(Window); ASSERT_REFS_CO(Window);
*ClientRect = *WindowRect; *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); 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); lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top);
co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam); co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam);
IntEngWindowChanged(Wnd, WOC_RGN_CLIENT); IntEngWindowChanged(Wnd, WOC_RGN_CLIENT);
} }
@ -1667,6 +1814,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd)
RECTL NewPos; RECTL NewPos;
BOOLEAN ShowFlag; BOOLEAN ShowFlag;
LONG style; LONG style;
PWND Parent;
// HRGN VisibleRgn; // HRGN VisibleRgn;
ASSERT_REFS_CO(Wnd); ASSERT_REFS_CO(Wnd);
@ -1782,45 +1930,41 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd)
{ {
Swp |= SWP_NOACTIVATE | SWP_NOZORDER; Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
} }
#if 0 // Explorer issues with common controls. Someone does not know how CS_SAVEBITS works. #if 0 // Explorer issues with common controls. Someone does not know how CS_SAVEBITS works.
if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD && if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
Wnd->pcls->style & CS_SAVEBITS && Wnd->pcls->style & CS_SAVEBITS &&
((Cmd == SW_SHOW) || (Cmd == SW_NORMAL))) ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL)))
{ {
co_IntSetActiveWindow(Wnd); co_IntSetActiveWindow(Wnd,NULL,FALSE,TRUE);
Swp |= SWP_NOACTIVATE | SWP_NOZORDER; Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
} }
#endif #endif
co_WinPosSetWindowPos(Wnd, 0 != (Wnd->ExStyle & WS_EX_TOPMOST)
? HWND_TOPMOST : HWND_TOP, co_WinPosSetWindowPos( Wnd,
NewPos.left, NewPos.top, NewPos.right, NewPos.bottom, LOWORD(Swp)); 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)) if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE))
{ {
PWND ThreadFocusWindow; PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
/* FIXME: This will cause the window to be activated irrespective // and Rule #1.
* of whether it is owned by the same thread. Has to be done if (Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue())
* asynchronously.
*/
if (Wnd->head.h == UserGetActiveWindow())
{ {
co_WinPosActivateOtherWindow(Wnd); co_WinPosActivateOtherWindow(Wnd);
} }
// Temp HACK
ThreadFocusWindow = UserGetWindowObject(IntGetThreadFocusWindow());
/* Revert focus to parent */ /* Revert focus to parent */
/* if (ThreadFocusWindow && (Wnd == ThreadFocusWindow || if (Wnd == pti->MessageQueue->spwndFocus)
IntIsChildWindow(Wnd, ThreadFocusWindow)))
*/
if (Wnd == ThreadFocusWindow)
{ {
// FIXME: As long as we have ref on Window, we also, indirectly, have ref on parent... Parent = Wnd->spwndParent;
co_UserSetFocus(Wnd->spwndParent); if (Wnd->spwndParent == UserGetDesktopWindow()) Parent = 0;
co_UserSetFocus(Parent);
} }
} }
@ -2199,8 +2343,8 @@ NtUserDeferWindowPos(HDWP WinPosInfo,
pWnd = UserGetWindowObject(Wnd); pWnd = UserGetWindowObject(Wnd);
if ( !pWnd || // FIXME: if ( !pWnd || // FIXME:
pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
pWnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
goto Exit; goto Exit;
} }
@ -2212,8 +2356,8 @@ NtUserDeferWindowPos(HDWP WinPosInfo,
{ {
pWndIA = UserGetWindowObject(WndInsertAfter); pWndIA = UserGetWindowObject(WndInsertAfter);
if ( !pWndIA || if ( !pWndIA ||
pWndIA == IntGetDesktopWindow() || pWndIA == UserGetDesktopWindow() ||
pWndIA == IntGetMessageWindow() ) pWndIA == UserGetMessageWindow() )
{ {
goto Exit; goto Exit;
} }
@ -2365,8 +2509,8 @@ NtUserMinMaximize(
pWnd = UserGetWindowObject(hWnd); pWnd = UserGetWindowObject(hWnd);
if ( !pWnd || // FIXME: if ( !pWnd || // FIXME:
pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
pWnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
goto Exit; goto Exit;
} }
@ -2385,8 +2529,8 @@ NtUserMinMaximize(
NULL, NULL,
NewPos.left, NewPos.left,
NewPos.top, NewPos.top,
NewPos.right, NewPos.right, //NewPos.right - NewPos.left,
NewPos.bottom, NewPos.bottom, //NewPos.bottom - NewPos.top,
SwFlags); SwFlags);
co_WinPosShowWindow(pWnd, cmd); co_WinPosShowWindow(pWnd, cmd);
@ -2436,9 +2580,11 @@ NtUserSetWindowPos(
UserEnterExclusive(); UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP // Due to desktopbg.c
Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND // Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
ERR("NtUserSetWindowPos bad window handle!\n");
RETURN(FALSE); RETURN(FALSE);
} }
@ -2447,11 +2593,11 @@ NtUserSetWindowPos(
hWndInsertAfter != HWND_TOPMOST && hWndInsertAfter != HWND_TOPMOST &&
hWndInsertAfter != HWND_NOTOPMOST ) hWndInsertAfter != HWND_NOTOPMOST )
{ {
pWndIA = UserGetWindowObject(hWndInsertAfter); if (!(pWndIA = UserGetWindowObject(hWndInsertAfter)) ||
if ( !pWndIA || pWndIA == UserGetDesktopWindow() ||
pWndIA == IntGetDesktopWindow() || pWndIA == UserGetMessageWindow() )
pWndIA == IntGetMessageWindow() )
{ {
ERR("NtUserSetWindowPos bad insert window handle!\n");
RETURN(FALSE); RETURN(FALSE);
} }
} }
@ -2503,8 +2649,8 @@ NtUserSetWindowRgn(
UserEnterExclusive(); UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
RETURN( 0); RETURN( 0);
} }
@ -2572,8 +2718,8 @@ NtUserSetInternalWindowPos(
UserEnterExclusive(); UserEnterExclusive();
if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME: if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME:
Wnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP Wnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Wnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND Wnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
RETURN( FALSE); RETURN( FALSE);
} }
@ -2642,8 +2788,8 @@ NtUserSetWindowPlacement(HWND hWnd,
UserEnterExclusive(); UserEnterExclusive();
if (!(Wnd = UserGetWindowObject(hWnd)) || // FIXME: if (!(Wnd = UserGetWindowObject(hWnd)) || // FIXME:
Wnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP Wnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Wnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND Wnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
RETURN( FALSE); RETURN( FALSE);
} }
@ -2693,8 +2839,8 @@ NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow)
UserEnterExclusive(); UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
RETURN(FALSE); RETURN(FALSE);
} }
@ -2733,8 +2879,8 @@ NtUserShowWindow(HWND hWnd, LONG nCmdShow)
UserEnterExclusive(); UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
RETURN(FALSE); 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); 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); VOID MenuTrackKbdMenuBar(HWND hWnd, UINT wParam, WCHAR wChar);
/* misc definitions */ /* misc definitions */
void mirror_rect( const RECT *window_rect, RECT *rect );
BOOL FASTCALL DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi); BOOL FASTCALL DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi);
VOID FASTCALL ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt); VOID FASTCALL ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt);
HCURSOR CursorIconToCursor(HICON hIcon, BOOL SemiTransparent); HCURSOR CursorIconToCursor(HICON hIcon, BOOL SemiTransparent);

View file

@ -44,18 +44,12 @@ User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength)
/* /*
* @unimplemented * @implemented
*/ */
BOOL WINAPI BOOL WINAPI
AllowSetForegroundWindow(DWORD dwProcessId) AllowSetForegroundWindow(DWORD dwProcessId)
{ {
static BOOL show_message = TRUE; return NtUserxAllowSetForegroundWindow(dwProcessId);
if (show_message)
{
UNIMPLEMENTED;
show_message = FALSE;
}
return TRUE;
} }
@ -1002,8 +996,11 @@ GetLastActivePopup(HWND hWnd)
{ {
_SEH2_TRY _SEH2_TRY
{ {
if (Wnd->hWndLastActive) if (Wnd->spwndLastActive)
Ret = Wnd->hWndLastActive; {
PWND LastActive = DesktopPtrToUser(Wnd->spwndLastActive);
Ret = UserHMGetHandle(LastActive);
}
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -1627,13 +1624,12 @@ IsZoomed(HWND hWnd)
/* /*
* @unimplemented * @implemented
*/ */
BOOL WINAPI BOOL WINAPI
LockSetForegroundWindow(UINT uLockCode) LockSetForegroundWindow(UINT uLockCode)
{ {
UNIMPLEMENTED; return NtUserxLockSetForegroundWindow(uLockCode);
return TRUE;
} }

View file

@ -15,6 +15,14 @@
#include <wine/debug.h> #include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(user32); 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 *****************************************************************/ /* FUNCTIONS *****************************************************************/
/******************************************************************* /*******************************************************************
@ -206,7 +214,6 @@ WindowFromPoint(POINT Point)
return NtUserWindowFromPoint(Point.x, Point.y); return NtUserWindowFromPoint(Point.x, Point.y);
} }
/* /*
* @implemented * @implemented
*/ */
@ -217,6 +224,7 @@ MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints)
BOOL mirror_from, mirror_to; BOOL mirror_from, mirror_to;
POINT Delta; POINT Delta;
UINT i; UINT i;
int Change = 1;
if (hWndFrom) if (hWndFrom)
{ {
@ -240,7 +248,8 @@ MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints)
if (FromWnd->ExStyle & WS_EX_LAYOUTRTL) if (FromWnd->ExStyle & WS_EX_LAYOUTRTL)
{ {
mirror_from = TRUE; mirror_from = TRUE;
Delta.x = FromWnd->rcClient.right - FromWnd->rcClient.left; Change = -Change;
Delta.x = -FromWnd->rcClient.right;
} }
else else
Delta.x = FromWnd->rcClient.left; Delta.x = FromWnd->rcClient.left;
@ -252,10 +261,11 @@ MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints)
if (ToWnd->ExStyle & WS_EX_LAYOUTRTL) if (ToWnd->ExStyle & WS_EX_LAYOUTRTL)
{ {
mirror_to = TRUE; mirror_to = TRUE;
Delta.x -= ToWnd->rcClient.right - ToWnd->rcClient.left; Change = -Change;
Delta.x += Change * ToWnd->rcClient.right;
} }
else else
Delta.x -= ToWnd->rcClient.left; Delta.x -= Change * ToWnd->rcClient.left;
Delta.y -= ToWnd->rcClient.top; Delta.y -= ToWnd->rcClient.top;
} }
@ -264,21 +274,20 @@ MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints)
for (i = 0; i != cPoints; i++) for (i = 0; i != cPoints; i++)
{ {
lpPoints[i].x += Delta.x; lpPoints[i].x += Delta.x;
lpPoints[i].x *= Change;
lpPoints[i].y += Delta.y; 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 */ if ((mirror_from || mirror_to) && cPoints == 2) /* special case for rectangle */
{ {
int tmp = lpPoints[0].x; int tmp = min(lpPoints[0].x, lpPoints[1].x);
lpPoints[0].x = lpPoints[1].x; lpPoints[1].x = max(lpPoints[0].x, lpPoints[1].x);
lpPoints[1].x = tmp; lpPoints[0].x = tmp;
} }
return MAKELONG(LOWORD(Delta.x), LOWORD(Delta.y)); return MAKELONG(LOWORD(Delta.x), LOWORD(Delta.y));
} }
/* /*
* @implemented * @implemented
*/ */
@ -302,7 +311,6 @@ ScreenToClient(HWND hWnd, LPPOINT lpPoint)
return TRUE; return TRUE;
} }
/* /*
* @implemented * @implemented
*/ */
@ -325,4 +333,3 @@ ClientToScreen(HWND hWnd, LPPOINT lpPoint)
} }
return TRUE; return TRUE;
} }