diff --git a/reactos/win32ss/gdi/ntgdi/device.c b/reactos/win32ss/gdi/ntgdi/device.c index cb17ac8c472..58362251e3b 100644 --- a/reactos/win32ss/gdi/ntgdi/device.c +++ b/reactos/win32ss/gdi/ntgdi/device.c @@ -30,6 +30,7 @@ IntCreatePrimarySurface() { SIZEL SurfSize; SURFOBJ *pso; + PDESKTOP rpDesk; /* Attach monitor */ UserAttachMonitor((HDEV)gppdevPrimary); @@ -45,7 +46,18 @@ IntCreatePrimarySurface() gpsi->ptCursor.x = pso->sizlBitmap.cx / 2; gpsi->ptCursor.y = pso->sizlBitmap.cy / 2; - co_IntShowDesktop(IntGetActiveDesktop(), SurfSize.cx, SurfSize.cy); + rpDesk = IntGetActiveDesktop(); + if (!rpDesk) + { /* First time going in from winlogon and starting up application desktop and + haven't switch to winlogon desktop. Also still in WM_CREATE. */ + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); + rpDesk = pti->rpdesk; + if (!rpDesk) + { + DPRINT1("No DESKTOP Window!!!!!\n"); + } + } + co_IntShowDesktop(rpDesk, SurfSize.cx, SurfSize.cy); // Init Primary Displays Device Capabilities. PDEVOBJ_vGetDeviceCaps(gppdevPrimary, &GdiHandleTable->DevCaps); diff --git a/reactos/win32ss/user/ntuser/caret.c b/reactos/win32ss/user/ntuser/caret.c index 0b928c95a9f..5c7ecb2db13 100644 --- a/reactos/win32ss/user/ntuser/caret.c +++ b/reactos/win32ss/user/ntuser/caret.c @@ -202,11 +202,11 @@ BOOL FASTCALL co_UserShowCaret(PWND Window OPTIONAL) return FALSE; } - if(!ThreadQueue->CaretInfo->Visible && ThreadQueue->CaretInfo->hWnd) + if (!ThreadQueue->CaretInfo->Visible) { ThreadQueue->CaretInfo->Visible = 1; - pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd); - if (!ThreadQueue->CaretInfo->Showing) + pWnd = ValidateHwndNoErr(ThreadQueue->CaretInfo->hWnd); + if (!ThreadQueue->CaretInfo->Showing && pWnd) { co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0); IntNotifyWinEvent(EVENT_OBJECT_SHOW, pWnd, OBJID_CARET, OBJID_CARET, 0); diff --git a/reactos/win32ss/user/ntuser/desktop.c b/reactos/win32ss/user/ntuser/desktop.c index 6c06f740121..af75c46299f 100644 --- a/reactos/win32ss/user/ntuser/desktop.c +++ b/reactos/win32ss/user/ntuser/desktop.c @@ -550,6 +550,8 @@ HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID) LRESULT FASTCALL DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) { + ULONG Value; + //ERR("DesktopWindowProc\n"); switch (Msg) { case WM_NCCREATE: @@ -558,6 +560,20 @@ DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) Wnd->fnid = FNID_DESKTOP; } return (LRESULT)TRUE; + + case WM_CREATE: + Value = HandleToULong(PsGetCurrentProcessId()); + // Save Process ID + co_UserSetWindowLong(UserHMGetHandle(Wnd), DT_GWL_PROCESSID, Value, FALSE); + Value = HandleToULong(PsGetCurrentThreadId()); + // Save Thread ID + co_UserSetWindowLong(UserHMGetHandle(Wnd), DT_GWL_THREADID, Value, FALSE); + case WM_CLOSE: + return 0; + + case WM_DISPLAYCHANGE: + co_WinPosSetWindowPos(Wnd, 0, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER | SWP_NOACTIVATE); + break; } return 0; } @@ -605,17 +621,6 @@ UserRedrawDesktop() NTSTATUS FASTCALL co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height) { -//#if 0 - CSR_API_MESSAGE Request; - - Request.Type = MAKE_CSR_API(SHOW_DESKTOP, CSR_GUI); - Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow; - Request.Data.ShowDesktopRequest.Width = Width; - Request.Data.ShowDesktopRequest.Height = Height; - - return co_CsrNotify(&Request); -//#endif -#if 0 // DESKTOPWNDPROC PWND Window; Window = IntGetWindowObject(Desktop->DesktopWindow); @@ -629,7 +634,6 @@ co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height) co_UserRedrawWindow( Window, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN); return STATUS_SUCCESS; -#endif } NTSTATUS FASTCALL @@ -680,7 +684,7 @@ UserBuildShellHookHwndList(PDESKTOP Desktop) * notifications. The lParam contents depend on the Message. See * MSDN for more details (RegisterShellHookWindow) */ -VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam) +VOID co_IntShellHookNotify(WPARAM Message, WPARAM wParam, LPARAM lParam) { PDESKTOP Desktop = IntGetActiveDesktop(); HWND* HwndList; @@ -700,6 +704,8 @@ VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam) return; } + // FIXME: System Tray Support. + HwndList = UserBuildShellHookHwndList(Desktop); if (HwndList) { @@ -711,12 +717,16 @@ VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam) co_IntPostOrSendMessage(*cursor, gpsi->uiShellMsg, Message, - lParam); + (Message == HSHELL_LANGUAGE ? lParam : (LPARAM)wParam) ); } ExFreePool(HwndList); } + if (ISITHOOKED(WH_SHELL)) + { + co_HOOK_CallHooks(WH_SHELL, Message, wParam, lParam); + } } /* @@ -996,7 +1006,6 @@ IntPaintDesktop(HDC hDC) return TRUE; } - /* SYSCALLS *******************************************************************/ /* @@ -1069,6 +1078,8 @@ NtUserCreateDesktop( ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS; ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; } + /*else + {ERR("NtUserCreateDesktop: No ptiCurrent\n");}*/ DesktopName.Buffer = NULL; /* @@ -1169,9 +1180,9 @@ NtUserCreateDesktop( { InitializeListHead(&DesktopObject->pDeskInfo->aphkStart[i]); } -//#if 0 + /* - * Create a handle for CSRSS and notify CSRSS for Creating Desktop Background Window. + * Create a handle for CSRSS and notify CSRSS for Creating Desktop Background Windows and Threads. */ Request.Type = MAKE_CSR_API(CREATE_DESKTOP, CSR_GUI); Status = CsrInsertObject(Desktop, @@ -1194,51 +1205,9 @@ NtUserCreateDesktop( SetLastNtError(Status); RETURN( NULL); } -//#endif + if (ptiCurrent && !ptiCurrent->rpdesk) IntSetThreadDesktop(Desktop,FALSE); - /* - Based on wine/server/window.c in get_desktop_window. - */ - -#if 0 // DESKTOPWNDPROC from Revision 6908 Dedicated to GvG! - // Turn on when server side proc is ready. - // - // Create desktop window. - // - /* - Currently this works but it hangs in - co_IntShowDesktop->co_UserRedrawWindow->co_IntPaintWindows->co_IntSendMessage - Commenting out co_UserRedrawWindow will allow it to run with gui issues. - */ - ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_DESKTOP]))); - ClassName.Length = 0; - RtlZeroMemory(&WindowName, sizeof(WindowName)); - - RtlZeroMemory(&Cs, sizeof(Cs)); - Cs.x = UserGetSystemMetrics(SM_XVIRTUALSCREEN); - Cs.y = UserGetSystemMetrics(SM_YVIRTUALSCREEN); - Cs.cx = UserGetSystemMetrics(SM_CXVIRTUALSCREEN); - Cs.cy = UserGetSystemMetrics(SM_CYVIRTUALSCREEN); - Cs.style = WS_POPUP|WS_CLIPCHILDREN; - Cs.hInstance = hModClient; // Experimental mode... hModuleWin; // Server side winproc! - Cs.lpszName = (LPCWSTR) &WindowName; - Cs.lpszClass = (LPCWSTR) &ClassName; - - pWnd = co_UserCreateWindowEx(&Cs, &ClassName, &WindowName, NULL); - if (!pWnd) - { - ERR("Failed to create Desktop window handle\n"); - } - else - { // Should be set in window.c, Justin Case, - if (!DesktopObject->DesktopWindow) - { - DesktopObject->pDeskInfo->spwnd = pWnd; - DesktopObject->DesktopWindow = UserHMGetHandle(pWnd); - } - } -#endif ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_HWNDMESSAGE]))); ClassName.Length = 0; RtlZeroMemory(&WindowName, sizeof(WindowName)); diff --git a/reactos/win32ss/user/ntuser/desktop.h b/reactos/win32ss/user/ntuser/desktop.h index 8f5d86fa087..caac8bdf607 100644 --- a/reactos/win32ss/user/ntuser/desktop.h +++ b/reactos/win32ss/user/ntuser/desktop.h @@ -39,6 +39,10 @@ typedef struct _DESKTOP #define DF_DESKWNDDESTROYED 0x00010000 #define DF_DYING 0x00020000 +// Index offset for Desktop data. Should these be global? +#define DT_GWL_PROCESSID 0 +#define DT_GWL_THREADID 4 + #define DESKTOP_READ STANDARD_RIGHTS_READ | \ DESKTOP_ENUMERATE | \ DESKTOP_READOBJECTS @@ -146,7 +150,7 @@ IntParseDesktopPath(PEPROCESS Process, VOID APIENTRY UserRedrawDesktop(VOID); BOOL IntRegisterShellHookWindow(HWND hWnd); BOOL IntDeRegisterShellHookWindow(HWND hWnd); -VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam); +VOID co_IntShellHookNotify(WPARAM Message, WPARAM wParam, LPARAM lParam); HDC FASTCALL UserGetDesktopDC(ULONG,BOOL,BOOL); #define IntIsActiveDesktop(Desktop) \ @@ -277,6 +281,6 @@ DesktopHeapAddressToUser(PVOID lpMem) PWND FASTCALL IntGetThreadDesktopWindow(PTHREADINFO); PWND FASTCALL co_GetDesktopWindow(PWND); - +BOOL FASTCALL IntPaintDesktop(HDC); LRESULT FASTCALL DesktopWindowProc(PWND, UINT, WPARAM, LPARAM); /* EOF */ diff --git a/reactos/win32ss/user/ntuser/focus.c b/reactos/win32ss/user/ntuser/focus.c index 59eb49e2669..5a5ab0401f5 100644 --- a/reactos/win32ss/user/ntuser/focus.c +++ b/reactos/win32ss/user/ntuser/focus.c @@ -45,18 +45,35 @@ IntGetThreadFocusWindow(VOID) return ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; } -VOID FASTCALL +BOOL FASTCALL co_IntSendDeactivateMessages(HWND hWndPrev, HWND hWnd) { - PWND WndPrev ; + USER_REFERENCE_ENTRY RefPrev; + PWND WndPrev; + BOOL Ret = TRUE; - if (hWndPrev && (WndPrev = UserGetWindowObject(hWndPrev))) + if (hWndPrev && (WndPrev = ValidateHwndNoErr(hWndPrev))) { - co_IntSendMessageNoWait(hWndPrev, WM_NCACTIVATE, FALSE, 0); - co_IntSendMessageNoWait(hWndPrev, WM_ACTIVATE, - MAKEWPARAM(WA_INACTIVE, WndPrev->style & WS_MINIMIZE), - (LPARAM)hWnd); + UserRefObjectCo(WndPrev, &RefPrev); + + if (co_IntSendMessageNoWait(hWndPrev, WM_NCACTIVATE, FALSE, 0)) //(LPARAM)hWnd)) + { + co_IntSendMessageNoWait(hWndPrev, WM_ACTIVATE, + MAKEWPARAM(WA_INACTIVE, WndPrev->style & WS_MINIMIZE), + (LPARAM)hWnd); + + if (WndPrev) + WndPrev->state &= ~WNDS_ACTIVEFRAME; + } + else + { + ERR("Application is keeping itself Active to prevent the change!\n"); + Ret = FALSE; + } + + UserDerefObjectCo(WndPrev); } + return Ret; } BOOL FASTCALL @@ -65,99 +82,103 @@ 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 = Window; + while (spwndOwner->spwndOwner) { - spwndOwner->spwndLastActive = Window; spwndOwner = spwndOwner->spwndOwner; } + spwndOwner->spwndLastActive = Window; return TRUE; } ERR("MakeWindowActive Failed!\n"); return FALSE; } -VOID FASTCALL -co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate) +BOOL FASTCALL +co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOOL Async) { USER_REFERENCE_ENTRY Ref, RefPrev; - PWND Window, WindowPrev = NULL; HANDLE OldTID, NewTID; - PTHREADINFO ptiOld, ptiNew; + PTHREADINFO pti, ptiOld, ptiNew; + BOOL InAAPM = FALSE; + + if (Window) + { + pti = PsGetCurrentThreadWin32Thread(); - if ((Window = UserGetWindowObject(hWnd))) - { UserRefObjectCo(Window, &Ref); - WindowPrev = UserGetWindowObject(hWndPrev); - if (WindowPrev) UserRefObjectCo(WindowPrev, &RefPrev); /* Send palette messages */ if (gpsi->PUSIFlags & PUSIF_PALETTEDISPLAY && - co_IntPostOrSendMessage(hWnd, WM_QUERYNEWPALETTE, 0, 0)) + co_IntPostOrSendMessage(UserHMGetHandle(Window), WM_QUERYNEWPALETTE, 0, 0)) { UserSendNotifyMessage( HWND_BROADCAST, WM_PALETTEISCHANGING, - (WPARAM)hWnd, + (WPARAM)UserHMGetHandle(Window), 0); } - - if (Window->spwndPrev != NULL) - co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE); - - if (!Window->spwndOwner && !IntGetParent(Window)) + //// Fixes bug 7089. + if (!(Window->style & WS_CHILD)) { - co_IntShellHookNotify(HSHELL_WINDOWACTIVATED, (LPARAM) hWnd); - } + PWND pwndTemp = co_GetDesktopWindow(Window)->spwndChild; - if (Window) - { - Window->state |= WNDS_ACTIVEFRAME; + while (pwndTemp && !(pwndTemp->style & WS_VISIBLE)) pwndTemp = pwndTemp->spwndNext; - if (Window->style & WS_MINIMIZE) + if (Window != pwndTemp || (WindowPrev && !IntIsWindowVisible(WindowPrev))) { - TRACE("Widow was minimized\n"); + if (!Async || pti->MessageQueue == gpqForeground) + { + UINT flags = SWP_NOSIZE | SWP_NOMOVE; + if (Window == pwndTemp) flags |= SWP_NOACTIVATE; + co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, flags); + } } } - - if (WindowPrev) - WindowPrev->state &= ~WNDS_ACTIVEFRAME; - + //// OldTID = WindowPrev ? IntGetWndThreadId(WindowPrev) : NULL; - NewTID = Window ? IntGetWndThreadId(Window) : NULL; + NewTID = IntGetWndThreadId(Window); ptiOld = WindowPrev ? WindowPrev->head.pti : NULL; - ptiNew = Window ? Window->head.pti : NULL; + ptiNew = Window->head.pti; - TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID); + //ERR("SendActivateMessage Old -> %x, New -> %x\n", OldTID, NewTID); - if (OldTID != NewTID) + if (!(pti->TIF_flags & TIF_INACTIVATEAPPMSG) && + (!WindowPrev || OldTID != NewTID) ) { PWND cWindow; HWND *List, *phWnd; - List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow())); + List = IntWinListChildren(UserGetDesktopWindow()); if ( List ) { - if ( OldTID ) + if ( OldTID ) { + ptiOld->TIF_flags |= TIF_INACTIVATEAPPMSG; + ptiOld->pClientInfo->dwTIFlags = ptiOld->TIF_flags; + for (phWnd = List; *phWnd; ++phWnd) { - cWindow = UserGetWindowObject(*phWnd); + cWindow = ValidateHwndNoErr(*phWnd); if (cWindow && cWindow->head.pti == ptiOld) { // FALSE if the window is being deactivated, // ThreadId that owns the window being activated. co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID); } } + ptiOld->TIF_flags &= ~TIF_INACTIVATEAPPMSG; + ptiOld->pClientInfo->dwTIFlags = ptiOld->TIF_flags; } if ( NewTID ) - { + { //// Prevents a resource crash due to reentrance! + InAAPM = TRUE; + pti->TIF_flags |= TIF_INACTIVATEAPPMSG; + pti->pClientInfo->dwTIFlags = pti->TIF_flags; + //// for (phWnd = List; *phWnd; ++phWnd) { - cWindow = UserGetWindowObject(*phWnd); + cWindow = ValidateHwndNoErr(*phWnd); if (cWindow && cWindow->head.pti == ptiNew) { // TRUE if the window is being activated, // ThreadId that owns the window being deactivated. @@ -171,38 +192,81 @@ co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate) if (WindowPrev) UserDerefObjectCo(WindowPrev); // Now allow the previous window to die. + if (Window->state & WNDS_ACTIVEFRAME) + { // If already active frame do not allow NCPaint. + //ERR("SendActivateMessage Is Active Frame!\n"); + Window->state |= WNDS_NONCPAINT; + } + + if (Window->style & WS_MINIMIZE) + { + TRACE("Widow was minimized\n"); + } + + co_IntMakeWindowActive(Window); + UserDerefObjectCo(Window); /* FIXME: IntIsWindow */ - co_IntSendMessageNoWait(hWnd, WM_NCACTIVATE, (WPARAM)(hWnd == UserGetForegroundWindow()), 0); - /* FIXME: WA_CLICKACTIVE */ - co_IntSendMessageNoWait(hWnd, WM_ACTIVATE, - MAKEWPARAM(MouseActivate ? WA_CLICKACTIVE : WA_ACTIVE, - Window->style & WS_MINIMIZE), - (LPARAM)hWndPrev); + co_IntSendMessageNoWait( UserHMGetHandle(Window), + WM_NCACTIVATE, + (WPARAM)(Window == gpqForeground->spwndActive), + 0); //(LPARAM)hWndPrev); + + co_IntSendMessageNoWait( UserHMGetHandle(Window), + WM_ACTIVATE, + MAKEWPARAM(MouseActivate ? WA_CLICKACTIVE : WA_ACTIVE, Window->style & WS_MINIMIZE), + (LPARAM)(WindowPrev ? UserHMGetHandle(WindowPrev) : 0)); + + if (!Window->spwndOwner && !IntGetParent(Window)) + { + // FIXME lParam; The value is TRUE if the window is in full-screen mode, or FALSE otherwise. + co_IntShellHookNotify(HSHELL_WINDOWACTIVATED, (WPARAM) UserHMGetHandle(Window), FALSE); + } + + Window->state &= ~WNDS_NONCPAINT; + } + return InAAPM; } VOID FASTCALL -co_IntSendKillFocusMessages(HWND hWndPrev, HWND hWnd) +IntSendFocusMessages( PTHREADINFO pti, PWND pWnd) { - if (hWndPrev) - { - IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); - co_IntPostOrSendMessage(hWndPrev, WM_KILLFOCUS, (WPARAM)hWnd, 0); - } -} + PWND pWndPrev; + PUSER_MESSAGE_QUEUE ThreadQueue = pti->MessageQueue; // Queue can change... -VOID FASTCALL -co_IntSendSetFocusMessages(HWND hWndPrev, HWND hWnd) -{ - if (hWnd) + ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; + if (!pWnd && ThreadQueue->spwndActive) { - PWND pWnd = UserGetWindowObject(hWnd); - if (pWnd) + ThreadQueue->QF_flags |= QF_FOCUSNULLSINCEACTIVE; + } + + pWndPrev = ThreadQueue->spwndFocus; + + /* check if the specified window can be set in the input data of a given queue */ + if (!pWnd || ThreadQueue == pWnd->head.pti->MessageQueue) + /* set the current thread focus window */ + ThreadQueue->spwndFocus = pWnd; + + if (pWnd) + { + if (pWndPrev) + { + co_IntPostOrSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, (WPARAM)UserHMGetHandle(pWnd), 0); + } + if (ThreadQueue->spwndFocus == pWnd) { IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0); - co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0); + co_IntPostOrSendMessage(UserHMGetHandle(pWnd), WM_SETFOCUS, (WPARAM)(pWndPrev ? UserHMGetHandle(pWndPrev) : NULL), 0); + } + } + else + { + if (pWndPrev) + { + IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); + co_IntPostOrSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, 0, 0); } } } @@ -304,25 +368,29 @@ co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate) ASSERT_REFS_CO(Wnd); - TRACE("SetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, MouseActivate ? "TRUE" : "FALSE"); + TRACE("SetForegroundAndFocusWindow(%x, %s)\n", hWnd, (MouseActivate ? "TRUE" : "FALSE")); PrevForegroundQueue = IntGetFocusMessageQueue(); // Use this active desktop. pti = PsGetCurrentThreadWin32Thread(); if (PrevForegroundQueue) { // Same Window Q as foreground just do active. + //ERR("Same Window Q as foreground just do active.\n"); if (Wnd && Wnd->head.pti->MessageQueue == PrevForegroundQueue) { if (pti->MessageQueue == PrevForegroundQueue) { // Same WQ and TQ go active. - Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE); + //ERR("Same WQ and TQ go active.\n"); + Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE, FALSE); } else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) { // Same WQ and it is active. + //ERR("Same WQ and it is active.\n"); Ret = TRUE; } else { // Same WQ as FG but not the same TQ send active. + //ERR("Same WQ as FG but not the same TQ send active.\n"); co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate ); Ret = TRUE; } @@ -339,6 +407,7 @@ co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate) { IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue); gptiForeground = Wnd->head.pti; + TRACE("Set Foreground pti 0x%p Q 0x%p\n",Wnd->head.pti, Wnd->head.pti->MessageQueue); /* Henri Verbeet, What happens is that we get the WM_WINE_SETACTIVEWINDOW message sent by the @@ -361,7 +430,7 @@ co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate) if (pti->MessageQueue == PrevForegroundQueue) { //ERR("SFGW: TI same as Prev TI\n"); - co_IntSetActiveWindow(NULL, NULL, FALSE, TRUE); + co_IntSetActiveWindow(NULL, NULL, FALSE, TRUE, FALSE); } else co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 ); @@ -370,7 +439,7 @@ co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate) if (pti->MessageQueue == Wnd->head.pti->MessageQueue) { - Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE); + Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE, FALSE); } else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) { @@ -398,11 +467,11 @@ co_IntMouseActivateWindow(PWND Wnd) { BOOL Ret; PWND TopWnd; - PWND DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); + PWND DesktopWindow = UserGetDesktopWindow(); if (DesktopWindow) { Top = IntFindChildWindowToOwner(DesktopWindow, Wnd); - if ((TopWnd = UserGetWindowObject(Top))) + if ((TopWnd = ValidateHwndNoErr(Top))) { UserRefObjectCo(TopWnd, &Ref); Ret = co_IntMouseActivateWindow(TopWnd); @@ -415,31 +484,33 @@ co_IntMouseActivateWindow(PWND Wnd) } TopWindow = UserGetAncestor(Wnd, GA_ROOT); + //if (TopWindow) {ERR("MAW 2 pWnd %p hWnd %p\n",TopWindow,TopWindow->head.h);} if (!TopWindow) return FALSE; - /* TMN: Check return valud from this function? */ + /* TMN: Check return value from this function? */ UserRefObjectCo(TopWindow, &Ref); - co_IntSetForegroundAndFocusWindow(TopWindow, TRUE); - UserDerefObjectCo(TopWindow); - return TRUE; } BOOL FASTCALL -co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus) +co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, BOOL Async) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; + PWND pWndChg, WndPrev; // State changes. HWND hWndPrev; HWND hWnd = 0; + BOOL InAAPM; CBTACTIVATESTRUCT cbt; if (Wnd) { ASSERT_REFS_CO(Wnd); hWnd = UserHMGetHandle(Wnd); + if ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; + if (Wnd == UserGetDesktopWindow()) return FALSE; } pti = PsGetCurrentThreadWin32Thread(); @@ -450,6 +521,8 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus) if (Prev) *Prev = hWndPrev; if (hWndPrev == hWnd) return TRUE; + pWndChg = ThreadQueue->spwndActive; // Keep to notify of a preemptive switch. + if (Wnd) { if (ThreadQueue != Wnd->head.pti->MessageQueue) @@ -470,11 +543,36 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus) cbt.hWndActive = hWndPrev; 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 FALSE; } - co_IntSendDeactivateMessages(hWndPrev, hWnd); + if ( ThreadQueue->spwndActive && ThreadQueue->spwndActive->state & WNDS_DESTROYED ) + ThreadQueue->spwndActive = NULL; + else + ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive; + + WndPrev = ThreadQueue->spwndActive; // Keep to save changing active. + + if (WndPrev) + { + if (ThreadQueue == gpqForeground) gpqForegroundPrev = ThreadQueue; + if (!co_IntSendDeactivateMessages(hWndPrev, hWnd)) return FALSE; + } + + // While in calling message proc or hook: + // Fail if a preemptive switch was made, current active not made previous, + // focus window is dead or no longer the same thread queue. + if ( ThreadQueue->spwndActivePrev != ThreadQueue->spwndActive || + pWndChg != ThreadQueue->spwndActive || + (Wnd && !VerifyWnd(Wnd)) || + ThreadQueue != pti->MessageQueue ) + { + ERR("SetActiveWindow: Summery ERROR, active state changed!\n"); + return FALSE; + } + + if (!WndPrev) ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED; @@ -484,32 +582,36 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus) if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue) { /* set the current thread active window */ - if (!Wnd || co_IntMakeWindowActive(Wnd)) - { - ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive; - ThreadQueue->spwndActive = Wnd; - } + ThreadQueue->spwndActive = Wnd; } - co_IntSendActivateMessages(hWndPrev, hWnd, bMouse); + InAAPM = co_IntSendActivateMessages(WndPrev, Wnd, bMouse, Async); /* now change focus if necessary */ - if (bFocus) + if (bFocus && !(ThreadQueue->QF_flags & QF_FOCUSNULLSINCEACTIVE)) { /* Do not change focus if the window is no longer active */ - if (ThreadQueue->spwndActive == Wnd) + if ( !Wnd || IntGetNonChildAncestor(ThreadQueue->spwndFocus) != ThreadQueue->spwndActive) { - if (!ThreadQueue->spwndFocus || - !Wnd || - UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd) - { - co_UserSetFocus(Wnd); - } + PWND pWndTemp = Wnd; + if (ThreadQueue->spwndActive && ThreadQueue->spwndActive->style & WS_MINIMIZE) + pWndTemp = NULL; + TRACE("SAW is setting Focus! 0x%p Temp 0x%p\n",Wnd, pWndTemp); + IntSendFocusMessages(pti, pWndTemp); } } + if (InAAPM) + { + pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG; + pti->pClientInfo->dwTIFlags = pti->TIF_flags; + } + + // FIXME: Used in the menu loop!!! + //ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE; + if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED; - return TRUE; + return (ThreadQueue->spwndActive == Wnd); } HWND FASTCALL @@ -527,13 +629,15 @@ co_UserSetFocus(PWND Window) ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); + TRACE("Enter SetFocus hWnd 0x%p pti 0x%p\n",Window ? UserHMGetHandle(Window) : 0, pti ); + hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; if (Window != 0) { if (hWndPrev == UserHMGetHandle(Window)) { - return hWndPrev; /* Nothing to do */ + return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; /* Nothing to do */ } if (Window->head.pti->MessageQueue != ThreadQueue) @@ -570,7 +674,7 @@ co_UserSetFocus(PWND Window) { if (!co_IntSetForegroundAndFocusWindow(pwndTop, FALSE)) { - ERR("SetFocus Set Foreground and Focus Failed!\n"); + ERR("SetFocus: Set Foreground and Focus Failed!\n"); return 0; } } @@ -578,9 +682,9 @@ co_UserSetFocus(PWND Window) /* Set Active when it is needed. */ if (pwndTop != ThreadQueue->spwndActive) { - if (!co_IntSetActiveWindow(pwndTop, NULL, FALSE, FALSE)) + if (!co_IntSetActiveWindow(pwndTop, NULL, FALSE, FALSE, FALSE)) { - ERR("SetFocus Set Active Failed!\n"); + ERR("SetFocus: Set Active Failed!\n"); return 0; } } @@ -590,7 +694,7 @@ co_UserSetFocus(PWND Window) /* Do not change focus if the window is no longer active */ if (pwndTop != ThreadQueue->spwndActive) { - ERR("SetFocus Top window did not go active!\n"); + ERR("SetFocus: Top window did not go active!\n"); return 0; } } @@ -598,29 +702,22 @@ co_UserSetFocus(PWND Window) // Check again! SetActiveWindow could have set the focus via WM_ACTIVATE. hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; - /* check if the specified window can be set in the input data of a given queue */ - if (ThreadQueue == Window->head.pti->MessageQueue) - /* set the current thread focus window */ - ThreadQueue->spwndFocus = Window; + IntSendFocusMessages( pti, Window); TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h); - - co_IntSendKillFocusMessages(hWndPrev, Window->head.h); - co_IntSendSetFocusMessages(hWndPrev, Window->head.h); } else /* NULL hwnd passed in */ { - if (!hWndPrev) return 0; /* nothing to do */ +// if (!hWndPrev) return 0; /* nothing to do */ + if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) { - ERR("SetFocusWindow 2 WH_CBT Call Hook return!\n"); + ERR("SetFocus: 2 WH_CBT Call Hook return!\n"); return 0; } /* set the current thread focus window null */ - ThreadQueue->spwndFocus = 0; - - co_IntSendKillFocusMessages(hWndPrev, 0); + IntSendFocusMessages( pti, NULL); } return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; } @@ -667,7 +764,7 @@ co_UserSetCapture(HWND hWnd) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; - PWND Window, pWnd; + PWND pWnd, Window = NULL; HWND hWndPrev; pti = PsGetCurrentThreadWin32Thread(); @@ -676,7 +773,7 @@ co_UserSetCapture(HWND hWnd) if (ThreadQueue->QF_flags & QF_CAPTURELOCKED) return NULL; - if ((Window = UserGetWindowObject(hWnd))) + if (hWnd && (Window = UserGetWindowObject(hWnd))) { if (Window->head.pti->MessageQueue != ThreadQueue) { @@ -868,24 +965,24 @@ NtUserSetActiveWindow(HWND hWnd) { if (!(Window = UserGetWindowObject(hWnd))) { - RETURN( 0); + ERR("NtUserSetActiveWindow: Invalid handle 0x%p!\n",hWnd); + RETURN( NULL); } } if (!Window || Window->head.pti->MessageQueue == gptiCurrent->MessageQueue) { + hWndPrev = gptiCurrent->MessageQueue->spwndActive ? UserHMGetHandle(gptiCurrent->MessageQueue->spwndActive) : NULL; if (Window) UserRefObjectCo(Window, &Ref); - if (!co_IntSetActiveWindow(Window, &hWndPrev, FALSE, TRUE)) hWndPrev = NULL; + co_IntSetActiveWindow(Window, NULL, FALSE, TRUE, FALSE); if (Window) UserDerefObjectCo(Window); + RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 ); } - else - hWndPrev = NULL; - - RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 ); + RETURN( NULL); CLEANUP: - TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_); + TRACE("Leave NtUserSetActiveWindow, ret=%p\n",_ret_); UserLeave(); END_CLEANUP; } @@ -927,6 +1024,7 @@ NtUserSetFocus(HWND hWnd) { if (!(Window = UserGetWindowObject(hWnd))) { + ERR("NtUserSetFocus: Invalid handle 0x%p!\n",hWnd); RETURN(NULL); } @@ -942,7 +1040,7 @@ NtUserSetFocus(HWND hWnd) } CLEANUP: - TRACE("Leave NtUserSetFocus, ret=%i\n",_ret_); + TRACE("Leave NtUserSetFocus, ret=%p\n",_ret_); UserLeave(); END_CLEANUP; } diff --git a/reactos/win32ss/user/ntuser/focus.h b/reactos/win32ss/user/ntuser/focus.h index f0f2c97a577..e2fc7ad0253 100644 --- a/reactos/win32ss/user/ntuser/focus.h +++ b/reactos/win32ss/user/ntuser/focus.h @@ -18,6 +18,6 @@ HWND APIENTRY IntGetCapture(VOID); HWND FASTCALL UserGetActiveWindow(VOID); BOOL FASTCALL co_IntMouseActivateWindow(PWND Window); BOOL FASTCALL co_IntSetForegroundWindow(PWND Window); -BOOL FASTCALL co_IntSetActiveWindow(PWND Window,HWND * Prev,BOOL bMouse,BOOL bFocus); +BOOL FASTCALL co_IntSetActiveWindow(PWND,HWND *,BOOL,BOOL,BOOL); BOOL FASTCALL IntLockSetForegroundWindow(UINT uLockCode); BOOL FASTCALL IntAllowSetForegroundWindow(DWORD dwProcessId); diff --git a/reactos/win32ss/user/ntuser/kbdlayout.c b/reactos/win32ss/user/ntuser/kbdlayout.c index 3813aef03ef..256ddea78e7 100644 --- a/reactos/win32ss/user/ntuser/kbdlayout.c +++ b/reactos/win32ss/user/ntuser/kbdlayout.c @@ -644,7 +644,7 @@ NtUserLoadKeyboardLayoutEx( /* Send shell message */ if (!(Flags & KLF_NOTELLSHELL)) - co_IntShellHookNotify(HSHELL_LANGUAGE, (LPARAM)hkl); + co_IntShellHookNotify(HSHELL_LANGUAGE, 0, (LPARAM)hkl); /* Return hkl on success */ hklRet = (HKL)hkl; @@ -713,7 +713,7 @@ NtUserActivateKeyboardLayout( /* Send shell message */ if (!(Flags & KLF_NOTELLSHELL)) - co_IntShellHookNotify(HSHELL_LANGUAGE, (LPARAM)hkl); + co_IntShellHookNotify(HSHELL_LANGUAGE, 0, (LPARAM)hkl); } cleanup: diff --git a/reactos/win32ss/user/ntuser/message.c b/reactos/win32ss/user/ntuser/message.c index 479e9510810..380e3ae2d20 100644 --- a/reactos/win32ss/user/ntuser/message.c +++ b/reactos/win32ss/user/ntuser/message.c @@ -632,7 +632,7 @@ static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPAR { PWND Window = (PWND)wparam; if (wparam) UserRefObjectCo(Window, &Ref); - lRes = (LRESULT)co_IntSetActiveWindow(Window,NULL,(BOOL)lparam,TRUE); + lRes = (LRESULT)co_IntSetActiveWindow(Window,NULL,(BOOL)lparam,TRUE,TRUE); if (wparam) UserDerefObjectCo(Window); return lRes; } @@ -1807,11 +1807,9 @@ DWORD APIENTRY IntGetQueueStatus(DWORD Changes) { PTHREADINFO pti; - //PUSER_MESSAGE_QUEUE Queue; DWORD Result; pti = PsGetCurrentThreadWin32Thread(); - //Queue = pti->MessageQueue; // wine: Changes &= (QS_ALLINPUT|QS_ALLPOSTMESSAGE|QS_SMRESULT); @@ -2159,7 +2157,7 @@ NtUserTranslateMessage(LPMSG lpMsg, UINT flags) } else { - ERR("No Window for Translate. hwnd 0x%p Msg %d\n",SafeMsg.hwnd,SafeMsg.message); + TRACE("No Window for Translate. hwnd 0x%p Msg %d\n",SafeMsg.hwnd,SafeMsg.message); Ret = FALSE; } UserLeave(); @@ -2192,6 +2190,12 @@ NtUserMessageCall( HWND hWnd, lResult = ScrollBarWndProc(hWnd, Msg, wParam, lParam); break; } + case FNID_DESKTOP: + { + Window = UserGetWindowObject(hWnd); + if (Window) lResult = DesktopWindowProc(Window, Msg, wParam, lParam); + break; + } case FNID_DEFWINDOWPROC: /* Validate input */ if (hWnd) @@ -2676,6 +2680,7 @@ NtUserMessageCall( HWND hWnd, case FNID_CALLWNDPROC: case FNID_CALLWNDPROCRET: case FNID_SCROLLBAR: + case FNID_DESKTOP: if (ResultInfo) { _SEH2_TRY diff --git a/reactos/win32ss/user/ntuser/msgqueue.c b/reactos/win32ss/user/ntuser/msgqueue.c index d7ef793c112..35c5ca49255 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.c +++ b/reactos/win32ss/user/ntuser/msgqueue.c @@ -997,6 +997,7 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, PUSER_MESSAGE_QUEUE ThreadQueue; LARGE_INTEGER Timeout; PLIST_ENTRY Entry; + PWND pWnd; LRESULT Result = 0; //// Result could be trashed. //// pti = PsGetCurrentThreadWin32Thread(); @@ -1015,14 +1016,27 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, if ( HookMessage == MSQ_NORMAL ) { + pWnd = ValidateHwndNoErr(Wnd); + // These can not cross International Border lines! - if ( pti->ppi != ptirec->ppi ) + if ( pti->ppi != ptirec->ppi && pWnd ) { switch(Msg) { + // Handle the special case when working with password transfers across bordering processes. case EM_GETLINE: case EM_SETPASSWORDCHAR: case WM_GETTEXT: + // Look for edit controls setup for passwords. + if ( gpsi->atomSysClass[ICLS_EDIT] == pWnd->pcls->atomClassName && // Use atomNVClassName. + pWnd->style & ES_PASSWORD ) + { + if (uResult) *uResult = -1; + ERR("Running across the border without a passport!\n"); + EngSetLastError(ERROR_ACCESS_DENIED); + return STATUS_UNSUCCESSFUL; + } + break; case WM_NOTIFY: if (uResult) *uResult = -1; ERR("Running across the border without a passport!\n"); @@ -1551,13 +1565,12 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT /* Activate the window if needed */ - if (pwndMsg != pti->MessageQueue->spwndActive) //msg->hwnd != UserGetForegroundWindow()) + if (pwndMsg != MessageQueue->spwndActive) { PWND pwndTop = pwndMsg; - while (pwndTop) + while (pwndTop && ((pwndTop->style & (WS_POPUP|WS_CHILD)) == WS_CHILD)) { - if ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break; - pwndTop = IntGetParent( pwndTop ); + pwndTop = pwndTop->spwndParent; } if (pwndTop && pwndTop != pwndDesktop) @@ -1673,10 +1686,23 @@ co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue, { BOOL AcceptMessage; MSG msg; + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); if(!(MessageQueue->MouseMoved)) return FALSE; + if (!MessageQueue->ptiSysLock) + { + MessageQueue->ptiSysLock = pti; + pti->pcti->CTI_flags |= CTI_THREADSYSLOCK; + } + + if (MessageQueue->ptiSysLock != pti) + { + ERR("MsqPeekMouseMove: Thread Q is locked to another pti!\n"); + return FALSE; + } + msg = MessageQueue->MouseMoveMsg; AcceptMessage = co_IntProcessMouseMessage(&msg, &Remove, MsgFilterLow, MsgFilterHigh); @@ -1690,7 +1716,9 @@ co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue, MessageQueue->MouseMoved = FALSE; } - return AcceptMessage; + MessageQueue->ptiSysLock = NULL; + pti->pcti->CTI_flags &= ~CTI_THREADSYSLOCK; + return AcceptMessage; } /* check whether a message filter contains at least one potential hardware message */ @@ -1724,6 +1752,8 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, PUSER_MESSAGE CurrentMessage; PLIST_ENTRY ListHead, CurrentEntry = NULL; MSG msg; + BOOL Ret = FALSE; + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); if (!filter_contains_hw_range( MsgFilterLow, MsgFilterHigh )) return FALSE; @@ -1732,6 +1762,18 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, if (IsListEmpty(CurrentEntry)) return FALSE; + if (!MessageQueue->ptiSysLock) + { + MessageQueue->ptiSysLock = pti; + pti->pcti->CTI_flags |= CTI_THREADSYSLOCK; + } + + if (MessageQueue->ptiSysLock != pti) + { + ERR("MsqPeekHardwareMessage: Thread Q is locked to another pti!\n"); + return FALSE; + } + CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); do @@ -1766,7 +1808,8 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, if (AcceptMessage) { *pMsg = msg; - return TRUE; + Ret = TRUE; + break; } } CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, @@ -1774,7 +1817,9 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, } while(CurrentEntry != ListHead); - return FALSE; + MessageQueue->ptiSysLock = NULL; + pti->pcti->CTI_flags &= ~CTI_THREADSYSLOCK; + return Ret; } BOOLEAN APIENTRY @@ -1789,12 +1834,26 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, PLIST_ENTRY CurrentEntry; PUSER_MESSAGE CurrentMessage; PLIST_ENTRY ListHead; + BOOL Ret = FALSE; + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); CurrentEntry = MessageQueue->PostedMessagesListHead.Flink; ListHead = &MessageQueue->PostedMessagesListHead; if (IsListEmpty(CurrentEntry)) return FALSE; + if (!MessageQueue->ptiSysLock) + { + MessageQueue->ptiSysLock = pti; + pti->pcti->CTI_flags |= CTI_THREADSYSLOCK; + } + + if (MessageQueue->ptiSysLock != pti) + { + ERR("MsqPeekMessage: Thread Q is locked to another pti!\n"); + return FALSE; + } + CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); do @@ -1822,14 +1881,17 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags); MsqDestroyMessage(CurrentMessage); } - return(TRUE); + Ret = TRUE; + break; } CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); } while (CurrentEntry != ListHead); - return(FALSE); + MessageQueue->ptiSysLock = NULL; + pti->pcti->CTI_flags &= ~CTI_THREADSYSLOCK; + return Ret; } NTSTATUS FASTCALL @@ -2190,15 +2252,15 @@ MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd) { case MSQ_STATE_CAPTURE: Prev = MessageQueue->spwndCapture ? UserHMGetHandle(MessageQueue->spwndCapture) : 0; - MessageQueue->spwndCapture = UserGetWindowObject(hWnd); + MessageQueue->spwndCapture = ValidateHwndNoErr(hWnd); return Prev; case MSQ_STATE_ACTIVE: Prev = MessageQueue->spwndActive ? UserHMGetHandle(MessageQueue->spwndActive) : 0; - MessageQueue->spwndActive = UserGetWindowObject(hWnd); + MessageQueue->spwndActive = ValidateHwndNoErr(hWnd); return Prev; case MSQ_STATE_FOCUS: Prev = MessageQueue->spwndFocus ? UserHMGetHandle(MessageQueue->spwndFocus) : 0; - MessageQueue->spwndFocus = UserGetWindowObject(hWnd); + MessageQueue->spwndFocus = ValidateHwndNoErr(hWnd); return Prev; case MSQ_STATE_MENUOWNER: Prev = MessageQueue->MenuOwner; diff --git a/reactos/win32ss/user/ntuser/painting.c b/reactos/win32ss/user/ntuser/painting.c index b26111b5132..446c3c57cf7 100644 --- a/reactos/win32ss/user/ntuser/painting.c +++ b/reactos/win32ss/user/ntuser/painting.c @@ -810,7 +810,7 @@ co_IntFixCaret(PWND Window, RECTL *lprc, UINT flags) CaretInfo = ActiveMessageQueue->CaretInfo; hWndCaret = CaretInfo->hWnd; - WndCaret = UserGetWindowObject(hWndCaret); + WndCaret = ValidateHwndNoErr(hWndCaret); // FIXME: Check for WndCaret can be NULL if (WndCaret == Window || @@ -1720,7 +1720,7 @@ NtUserScrollWindowEx( ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0)); } - if ((CaretWnd = UserGetWindowObject(hwndCaret))) + if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret))) { UserRefObjectCo(CaretWnd, &CaretRef); @@ -1975,8 +1975,6 @@ cleanup: return Ret; } -BOOL FASTCALL IntPaintDesktop(HDC hDC); - INT FASTCALL UserRealizePalette(HDC hdc) diff --git a/reactos/win32ss/user/ntuser/simplecall.c b/reactos/win32ss/user/ntuser/simplecall.c index 9dfe1ec601e..da3041ad97f 100644 --- a/reactos/win32ss/user/ntuser/simplecall.c +++ b/reactos/win32ss/user/ntuser/simplecall.c @@ -123,7 +123,7 @@ NtUserCallNoParam(DWORD Routine) case NOPARAM_ROUTINE_ZAPACTIVEANDFOUS: { PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); - ERR("Zapping the Active and Focus window out of the Queue!\n"); + TRACE("Zapping the Active and Focus window out of the Queue!\n"); pti->MessageQueue->spwndFocus = NULL; pti->MessageQueue->spwndActive = NULL; RETURN(0); @@ -572,7 +572,7 @@ NtUserCallHwndLock( SWP_FRAMECHANGED ); if (!Window->spwndOwner && !IntGetParent(Window)) { - co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) hWnd); + co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) hWnd, FALSE); // FIXME Flashing? } Ret = TRUE; break; diff --git a/reactos/win32ss/user/ntuser/win32.h b/reactos/win32ss/user/ntuser/win32.h index 2f23fbb9975..a6290e62b81 100644 --- a/reactos/win32ss/user/ntuser/win32.h +++ b/reactos/win32ss/user/ntuser/win32.h @@ -32,7 +32,19 @@ #define W32PF_MANUALGUICHECK (0x02000000) #define W32PF_CREATEDWINORDC (0x04000000) #define W32PF_APIHOOKLOADED (0x08000000) +/* +#define QSIDCOUNTS 6 +typedef enum _QS_ROS_TYPES +{ + QSRosKey = 0, + QSRosMouseMove, + QSRosMouseButton, + QSRosPostMessage, + QSRosSendMessage, + QSRosHotKey, +}QS_ROS_TYPES,*PQS_ROS_TYPES; +*/ extern BOOL ClientPfnInit; extern HINSTANCE hModClient; extern HANDLE hModuleWin; // This Win32k Instance. @@ -77,10 +89,13 @@ typedef struct _THREADINFO PCLIENTINFO pClientInfo; FLONG TIF_flags; PUNICODE_STRING pstrAppName; + LIST_ENTRY psmsSent; // DispatchingMessagesHead struct _USER_SENT_MESSAGE *pusmCurrent; + LIST_ENTRY psmsReceiveList; // SentMessagesListHead LONG timeLast; ULONG_PTR idLast; - INT exitCode; + BOOLEAN QuitPosted; + INT exitCode; // QuitExitCode HDESK hdesk; UINT cPaintsReady; /* Count of paints pending. */ UINT cTimersReady; /* Count of timers pending. */ @@ -94,16 +109,27 @@ typedef struct _THREADINFO LPARAM lParamHkCurrent; WPARAM wParamHkCurrent; struct tagSBTRACK* pSBTrack; - HANDLE hEventQueueClient; - PKEVENT pEventQueueServer; + HANDLE hEventQueueClient; // NewMessagesHandle + PKEVENT pEventQueueServer; // NewMessages LIST_ENTRY PtiLink; INT iCursorLevel; POINT ptLast; + LIST_ENTRY mlPost; // PostedMessagesListHead + LIST_ENTRY aphkStart[NB_HOOKS]; CLIENTTHREADINFO cti; // Used only when no Desktop or pcti NULL. /* ReactOS */ + + /* Queue state tracking */ + // Send list QS_SENDMESSAGE + // Post list QS_POSTMESSAGE|QS_HOTKEY|QS_PAINT|QS_TIMER|QS_KEY + // Hard list QS_MOUSE|QS_KEY only + // Accounting of queue bit sets, the rest are flags. QS_TIMER QS_PAINT counts are handled in thread information. + //DWORD nCntsQBits[QSIDCOUNTS]; // QS_KEY QS_MOUSEMOVE QS_MOUSEBUTTON QS_POSTMESSAGE QS_SENDMESSAGE QS_HOTKEY + + LIST_ENTRY LocalDispatchingMessagesHead; LIST_ENTRY WindowListHead; LIST_ENTRY W32CallbackListHead; SINGLE_LIST_ENTRY ReferencesList; diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 9f2cea73253..ba250362dcf 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -9,6 +9,8 @@ #include DBG_DEFAULT_CHANNEL(UserWnd); +INT gNestedWindowLimit = 50; + /* HELPER FUNCTIONS ***********************************************************/ BOOL FASTCALL UserUpdateUiState(PWND Wnd, WPARAM wParam) @@ -147,7 +149,9 @@ IntIsWindow(HWND hWnd) PWND Window; if (!(Window = UserGetWindowObject(hWnd))) + { return FALSE; + } return TRUE; } @@ -217,6 +221,7 @@ IntEnableWindow( HWND hWnd, BOOL bEnable ) /* Remove keyboard focus from that window if it had focus */ if (hWnd == IntGetThreadFocusWindow()) { + TRACE("IntEnableWindow SF NULL\n"); co_UserSetFocus(NULL); } IntSetStyle( pWnd, WS_DISABLED, 0 ); @@ -269,6 +274,39 @@ IntWinListChildren(PWND Window) return List; } +PWND FASTCALL +IntGetNonChildAncestor(PWND pWnd) +{ + if (pWnd) + { + while(pWnd && ((pWnd->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)) + pWnd = pWnd->spwndParent; + } + return pWnd; +} + +BOOL FASTCALL +IntIsTopLevelWindow(PWND pWnd) +{ + if ( pWnd->spwndParent && + pWnd->spwndParent == co_GetDesktopWindow(pWnd) ) return TRUE; + return FALSE; +} + +BOOL FASTCALL +IntValidateOwnerDepth(PWND Wnd, PWND Owner) +{ + INT Depth = 1; + for (;;) + { + if ( !Owner ) return gNestedWindowLimit >= Depth; + if (Owner == Wnd) break; + Owner = Owner->spwndOwner; + Depth++; + } + return FALSE; +} + /*********************************************************************** * IntSendDestroyMsg */ @@ -297,7 +335,7 @@ static void IntSendDestroyMsg(HWND hWnd) if (!Window->spwndOwner && !IntGetParent(Window)) { - co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (LPARAM) hWnd); + co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM) hWnd, 0); } // UserDerefObjectCo(Window); @@ -696,6 +734,7 @@ IntSetMenu( if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) { + ERR("SetMenu: Invalid handle 0x%p!\n",UserHMGetHandle(Wnd)); EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); return FALSE; } @@ -1037,6 +1076,36 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev) } } } + Wnd->ExStyle2 |= WS_EX2_LINKED; +} + +VOID FASTCALL +IntProcessOwnerSwap(PWND Wnd, PWND WndNewOwner, PWND WndOldOwner) +{ + if (WndOldOwner) + { + if (Wnd->head.pti != WndOldOwner->head.pti) + { + if (!WndNewOwner || + Wnd->head.pti == WndNewOwner->head.pti || + WndOldOwner->head.pti != WndNewOwner->head.pti ) + { + UserAttachThreadInput(Wnd->head.pti, WndOldOwner->head.pti, FALSE); + } + } + } + if (WndNewOwner) + { + if (Wnd->head.pti != WndNewOwner->head.pti) + { + if (!WndOldOwner || + WndOldOwner->head.pti != WndNewOwner->head.pti ) + { + UserAttachThreadInput(Wnd->head.pti, WndNewOwner->head.pti, TRUE); + } + } + } + // FIXME: System Tray checks. } HWND FASTCALL @@ -1051,17 +1120,36 @@ IntSetOwner(HWND hWnd, HWND hWndNewOwner) WndOldOwner = Wnd->spwndOwner; - ret = WndOldOwner ? WndOldOwner->head.h : 0; + ret = WndOldOwner ? UserHMGetHandle(WndOldOwner) : 0; + WndNewOwner = UserGetWindowObject(hWndNewOwner); - if((WndNewOwner = UserGetWindowObject(hWndNewOwner))) + if (!WndNewOwner && hWndNewOwner) { - Wnd->spwndOwner= WndNewOwner; + EngSetLastError(ERROR_INVALID_PARAMETER); + ret = NULL; + goto Error; + } + + IntProcessOwnerSwap(Wnd, WndNewOwner, WndOldOwner); + + if (IntValidateOwnerDepth(Wnd, WndNewOwner)) + { + if (WndNewOwner) + { + Wnd->spwndOwner= WndNewOwner; + } + else + { + Wnd->spwndOwner = NULL; + } } else { - Wnd->spwndOwner = NULL; + IntProcessOwnerSwap(Wnd, WndOldOwner, WndNewOwner); + EngSetLastError(ERROR_INVALID_PARAMETER); + ret = NULL; } - +Error: UserDereferenceObject(Wnd); return ret; } @@ -1129,6 +1217,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) { /* Unlink the window from the siblings list */ IntUnlinkWindow(Wnd); + Wnd->ExStyle2 &= ~WS_EX2_LINKED; /* Set the new parent */ Wnd->spwndParent = WndNewParent; @@ -1148,6 +1237,24 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) } + if ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) + { + if ( Wnd->spwndParent != co_GetDesktopWindow(Wnd)) + { + if (Wnd->head.pti != WndOldParent->head.pti) + { + UserAttachThreadInput(Wnd->head.pti, WndOldParent->head.pti, FALSE); + } + } + if ( WndNewParent != co_GetDesktopWindow(Wnd)) + { + if (Wnd->head.pti != WndNewParent->head.pti) + { + UserAttachThreadInput(Wnd->head.pti, WndNewParent->head.pti, TRUE); + } + } + } + if (WndOldParent == UserGetMessageWindow() || WndNewParent == UserGetMessageWindow()) swFlags |= SWP_NOACTIVATE; @@ -1617,6 +1724,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, if (NULL == pti->rpdesk->DesktopWindow) { /* HACK: Helper for win32csr/desktopbg.c */ /* If there is no desktop window yet, we must be creating it */ + TRACE("CreateWindow setting desktop.\n"); pti->rpdesk->DesktopWindow = hWnd; pti->rpdesk->pDeskInfo->spwnd = pWnd; } @@ -1809,6 +1917,31 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, else // Not a child pWnd->IDMenu = (UINT) Cs->hMenu; + + if ( ParentWindow && + ParentWindow != ParentWindow->head.rpdesk->spwndMessage && + ParentWindow != ParentWindow->head.rpdesk->pDeskInfo->spwnd ) + { + PWND Owner = IntGetNonChildAncestor(ParentWindow); + + if (!IntValidateOwnerDepth(pWnd, Owner)) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto Error; + } + if ( pWnd->spwndOwner && + pWnd->spwndOwner->ExStyle & WS_EX_TOPMOST ) + { + pWnd->ExStyle |= WS_EX_TOPMOST; + } + if ( pWnd->spwndOwner && + Class->atomClassName != gpsi->atomSysClass[ICLS_IME] && + pti != pWnd->spwndOwner->head.pti) + { + UserAttachThreadInput(pti, pWnd->spwndOwner->head.pti, TRUE); + } + } + /* Insert the window into the thread's window list. */ InsertTailList (&pti->WindowListHead, &pWnd->ThreadListEntry); @@ -1826,10 +1959,10 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, AllocError: ERR("IntCreateWindow Allocation Error.\n"); + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); +Error: if(pWnd) UserDereferenceObject(pWnd); - - SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); return NULL; } @@ -2082,6 +2215,17 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, IntLinkHwnd(Window, hwndInsertAfter); } + if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) + { + if ( !IntIsTopLevelWindow(Window) ) + { + if (pti != Window->spwndParent->head.pti) + { + UserAttachThreadInput(pti, Window->spwndParent->head.pti, TRUE); + } + } + } + /* Send the NCCREATE message */ Result = co_IntSendMessage(UserHMGetHandle(Window), WM_NCCREATE, 0, (LPARAM) Cs); if (!Result) @@ -2143,7 +2287,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, /* Notify the shell that a new window was created */ if ((!hWndParent) && (!hWndOwner)) { - co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)hWnd); + co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)hWnd, 0); } /* Initialize and show the window's scrollbars */ @@ -2379,6 +2523,7 @@ cleanup: BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) { HWND hWnd; + PWND pwndTemp; PTHREADINFO ti; MSG msg; @@ -2407,6 +2552,17 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) } } + if (Window->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME]) + { + if ((Window->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) + { + if (Window->spwndOwner) + { + UserAttachThreadInput(Window->head.pti, Window->spwndOwner->head.pti, FALSE); + } + } + } + /* Inform the parent */ if (Window->style & WS_CHILD) { @@ -2419,11 +2575,32 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) if (!co_WinPosShowWindow(Window, SW_HIDE)) { // Rule #1. if (ti->MessageQueue->spwndActive == Window && ti->MessageQueue == IntGetFocusMessageQueue()) - { //ERR("DestroyWindow AOW\n"); + { co_WinPosActivateOtherWindow(Window); } } + // Adjust last active. + if ((pwndTemp = Window->spwndOwner)) + { + while (pwndTemp->spwndOwner) + pwndTemp = pwndTemp->spwndOwner; + + if (pwndTemp->spwndLastActive == Window) + pwndTemp->spwndLastActive = Window->spwndOwner; + } + + if (Window->spwndParent && IntIsWindow(Window->head.h)) + { + if ((Window->style & (WS_POPUP | WS_CHILD)) == WS_CHILD) + { + if (!IntIsTopLevelWindow(Window)) + { + UserAttachThreadInput(Window->head.pti, Window->spwndParent->head.pti, FALSE); + } + } + } + if (Window->head.pti->MessageQueue->spwndActive == Window) Window->head.pti->MessageQueue->spwndActive = NULL; if (Window->head.pti->MessageQueue->spwndFocus == Window) @@ -3298,12 +3475,6 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi) LONG OldValue; STYLESTRUCT Style; - if (hWnd == IntGetDesktopWindow()) - { - EngSetLastError(STATUS_ACCESS_DENIED); - return( 0); - } - if (!(Window = UserGetWindowObject(hWnd))) { return( 0); @@ -3444,6 +3615,12 @@ NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi) TRACE("Enter NtUserSetWindowLong\n"); UserEnterExclusive(); + if (hWnd == IntGetDesktopWindow()) + { + EngSetLastError(STATUS_ACCESS_DENIED); + RETURN( 0); + } + RETURN( co_UserSetWindowLong(hWnd, Index, NewValue, Ansi)); CLEANUP: @@ -3471,6 +3648,12 @@ NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue) TRACE("Enter NtUserSetWindowWord\n"); UserEnterExclusive(); + if (hWnd == IntGetDesktopWindow()) + { + EngSetLastError(STATUS_ACCESS_DENIED); + RETURN( 0); + } + if (!(Window = UserGetWindowObject(hWnd))) { RETURN( 0); @@ -3481,7 +3664,7 @@ NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue) case GWL_ID: case GWL_HINSTANCE: case GWL_HWNDPARENT: - RETURN( (WORD)co_UserSetWindowLong(Window->head.h, Index, (UINT)NewValue, TRUE)); + RETURN( (WORD)co_UserSetWindowLong(UserHMGetHandle(Window), Index, (UINT)NewValue, TRUE)); default: if (Index < 0) { @@ -3836,7 +4019,7 @@ NtUserDefSetText(HWND hWnd, PLARGE_STRING WindowText) /* Send shell notifications */ if (!Wnd->spwndOwner && !IntGetParent(Wnd)) { - co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) hWnd); + co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) hWnd, FALSE); // FIXME Flashing? } Ret = TRUE; @@ -3913,7 +4096,9 @@ CLEANUP: END_CLEANUP; } - +/* + API Call +*/ BOOL FASTCALL IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow ) @@ -3924,7 +4109,8 @@ IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow ) // ASSERT(OwnerWnd); - win_array = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow())); + TRACE("Enter ShowOwnedPopups Show: %s\n", (fShow ? "TRUE" : "FALSE")); + win_array = IntWinListChildren(OwnerWnd); if (!win_array) return TRUE; @@ -3933,7 +4119,7 @@ IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow ) count++; while (--count >= 0) { - if (!(pWnd = UserGetWindowObject( win_array[count] ))) + if (!(pWnd = ValidateHwndNoErr( win_array[count] ))) continue; if (pWnd->spwndOwner != OwnerWnd) continue; @@ -3965,6 +4151,7 @@ IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow ) } ExFreePool( win_array ); + TRACE("Leave ShowOwnedPopups\n"); return TRUE; } diff --git a/reactos/win32ss/user/ntuser/window.h b/reactos/win32ss/user/ntuser/window.h index 2d355692757..d6931646564 100644 --- a/reactos/win32ss/user/ntuser/window.h +++ b/reactos/win32ss/user/ntuser/window.h @@ -49,8 +49,11 @@ LRESULT FASTCALL IntDefWindowProc( PWND Window, UINT Msg, WPARAM wParam, LPARAM VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG, DWORD); PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW*, PUNICODE_STRING, PLARGE_STRING, PVOID); BOOL FASTCALL IntEnableWindow(HWND,BOOL); +BOOL FASTCALL IntIsWindowVisible(PWND); DWORD FASTCALL GetNCHitEx(PWND,POINT); ULONG FASTCALL IntSetStyle(PWND,ULONG,ULONG); PWND FASTCALL VerifyWnd(PWND); +PWND FASTCALL IntGetNonChildAncestor(PWND); +LONG FASTCALL co_UserSetWindowLong(HWND,DWORD,LONG,BOOL); /* EOF */ diff --git a/reactos/win32ss/user/ntuser/winpos.c b/reactos/win32ss/user/ntuser/winpos.c index 4846f6a10e1..f25108881ec 100644 --- a/reactos/win32ss/user/ntuser/winpos.c +++ b/reactos/win32ss/user/ntuser/winpos.c @@ -139,6 +139,121 @@ IntMapWindowPoints(PWND FromWnd, PWND ToWnd, LPPOINT lpPoints, UINT cPoints) return MAKELONG(LOWORD(Delta.x), LOWORD(Delta.y)); } +BOOL FASTCALL IsChildVisible(PWND pWnd) +{ + do + { + if ( (pWnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD || + !(pWnd = pWnd->spwndParent) ) + return TRUE; + } + while (pWnd->style & WS_VISIBLE); + return FALSE; +} + +PWND FASTCALL IntGetLastTopMostWindow(VOID) +{ + PWND pWnd; + PDESKTOP rpdesk = gptiCurrent->rpdesk; + + if ( rpdesk && + (pWnd = rpdesk->pDeskInfo->spwnd->spwndChild) && + pWnd->ExStyle & WS_EX_TOPMOST) + { + for (;;) + { + if (!pWnd->spwndNext) break; + if (!(pWnd->spwndNext->ExStyle & WS_EX_TOPMOST)) break; + pWnd = pWnd->spwndNext; + } + return pWnd; + } + return NULL; +} + +// +// This helps with bug 6751 forcing modal dialog active when another app is minimized or closed. +// +BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd) +{ + BOOL ActivePrev, FindTopWnd; + PWND pWndTopMost, pWndChild, pWndSetActive, pWndTemp, pWndDesk; + USER_REFERENCE_ENTRY Ref; + PTHREADINFO pti = gptiCurrent; + + //ERR("AOWM 1\n"); + ActivePrev = (pti->MessageQueue->spwndActivePrev != NULL); + FindTopWnd = TRUE; + + if ((pWndTopMost = IntGetLastTopMostWindow())) + pWndChild = pWndTopMost->spwndNext; + else + pWndChild = Wnd->spwndParent->spwndChild; + + for (;;) + { + if ( ActivePrev ) + pWndSetActive = pti->MessageQueue->spwndActivePrev; + else + pWndSetActive = pWndChild; + + pWndTemp = NULL; + + while(pWndSetActive) + { + if ( VerifyWnd(pWndSetActive) && + !(pWndSetActive->ExStyle & WS_EX_NOACTIVATE) && + (pWndSetActive->style & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE && + (!(pWndSetActive->style & WS_ICONIC) /* FIXME MinMax pos? */ ) ) + { + if (!(pWndSetActive->ExStyle & WS_EX_TOOLWINDOW) ) + { + UserRefObjectCo(pWndSetActive, &Ref); + co_IntSetForegroundWindow(pWndSetActive); + UserDerefObjectCo(pWndSetActive); + //ERR("AOWM 2 Exit Good\n"); + return TRUE; + } + if (!pWndTemp ) pWndTemp = pWndSetActive; + } + if ( ActivePrev ) + { + ActivePrev = FALSE; + pWndSetActive = pWndChild; + } + else + pWndSetActive = pWndSetActive->spwndNext; + } + + if ( !FindTopWnd ) break; + FindTopWnd = FALSE; + + if ( pWndChild ) + { + pWndChild = pWndChild->spwndParent->spwndChild; + continue; + } + + if (!(pWndDesk = IntGetThreadDesktopWindow(pti))) + { + pWndChild = NULL; + continue; + } + pWndChild = pWndDesk->spwndChild; + } + + if ((pWndSetActive = pWndTemp)) + { + UserRefObjectCo(pWndSetActive, &Ref); + co_IntSetForegroundWindow(pWndSetActive); + UserDerefObjectCo(pWndSetActive); + //ERR("AOWM 3 Exit Good\n"); + return TRUE; + } + //ERR("AOWM 4 Bad\n"); + return FALSE; +} + /******************************************************************* * can_activate_window * @@ -203,7 +318,7 @@ done: if (WndTo) UserRefObjectCo(WndTo, &Ref); Fg = UserGetForegroundWindow(); - if ((!Fg || Wnd->head.h == Fg) && WndTo) // FIXME: Ok if WndTo is NULL?? + if ((!Fg || Wnd->head.h == Fg) && WndTo) // FIXME: Ok if WndTo is NULL?? No, rule #4. { /* FIXME: Wine can pass WndTo = NULL to co_IntSetForegroundWindow. Hmm... */ if (co_IntSetForegroundWindow(WndTo)) @@ -213,13 +328,15 @@ done: } } - if (!co_IntSetActiveWindow(WndTo,&previous,FALSE,TRUE) || /* Ok for WndTo to be NULL here */ + if (!co_IntSetActiveWindow(WndTo,&previous,FALSE,TRUE,FALSE) || /* Ok for WndTo to be NULL here */ !previous) - co_IntSetActiveWindow(0,NULL,FALSE,TRUE); - + { + co_IntSetActiveWindow(0,NULL,FALSE,TRUE,FALSE); + } if (WndTo) UserDerefObjectCo(WndTo); } + UINT FASTCALL co_WinPosArrangeIconicWindows(PWND parent) @@ -250,7 +367,7 @@ co_WinPosArrangeIconicWindows(PWND parent) { PWND Child; - if (!(Child = UserGetWindowObject(List[i]))) + if (!(Child = ValidateHwndNoErr(List[i]))) continue; if((Child->style & WS_MINIMIZE) != 0 ) @@ -295,6 +412,7 @@ WinPosFindIconPos(PWND Window, POINT *Pos) pwndParent = Window->spwndParent; if (pwndParent == UserGetDesktopWindow()) { + //ERR("Parent is Desktop, Min off screen!\n"); /* ReactOS doesn't support iconic minimize to desktop */ Pos->x = Pos->y = -32000; Window->InternalPos.flags |= WPF_MININIT; @@ -413,8 +531,7 @@ WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect) Wnd->InternalPos.MaxPos.x, Rect.left, WorkArea.left, Wnd->InternalPos.MaxPos.y, - Rect.top, WorkArea.top); - */ + Rect.top, WorkArea.top);*/ } } else @@ -603,6 +720,7 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) { POINT Size; WINDOWPLACEMENT wpl; + LONG old_style; UINT SwpFlags = 0; ASSERT_REFS_CO(Wnd); @@ -617,8 +735,14 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) } if (Wnd->style & WS_MINIMIZE) { - if (ShowFlag == SW_MINIMIZE) return SWP_NOSIZE | SWP_NOMOVE; - + switch (ShowFlag) + { + case SW_SHOWMINNOACTIVE: + case SW_SHOWMINIMIZED: + case SW_FORCEMINIMIZE: + case SW_MINIMIZE: + return SWP_NOSIZE | SWP_NOMOVE; + } if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0)) { return(SWP_NOSIZE | SWP_NOMOVE); @@ -627,24 +751,33 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) } switch (ShowFlag) { + case SW_SHOWMINNOACTIVE: + case SW_SHOWMINIMIZED: + case SW_FORCEMINIMIZE: case SW_MINIMIZE: { + //ERR("MinMaximize Minimize\n"); if (Wnd->style & WS_MAXIMIZE) { Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED; - Wnd->style &= ~WS_MAXIMIZE; - SwpFlags |= SWP_STATECHANGED; } else { Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; } + + old_style = IntSetStyle( Wnd, WS_MINIMIZE, WS_MAXIMIZE ); + co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT); - Wnd->style |= WS_MINIMIZE; + if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION)) Wnd->InternalPos.flags &= ~WPF_MININIT; + WinPosFindIconPos(Wnd, &wpl.ptMinPosition); + + if (!(old_style & WS_MINIMIZE)) SwpFlags |= SWP_STATECHANGED; + /*ERR("Minimize: %d,%d %dx%d\n", wpl.ptMinPosition.x, wpl.ptMinPosition.y, UserGetSystemMetrics(SM_CXMINIMIZED), UserGetSystemMetrics(SM_CYMINIMIZED)); @@ -660,33 +793,42 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) case SW_MAXIMIZE: { + //ERR("MinMaximize Maximize\n"); + if ((Wnd->style & WS_MAXIMIZE) && (Wnd->style & WS_VISIBLE)) + { + SwpFlags = SWP_NOSIZE | SWP_NOMOVE; + break; + } co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); /*ERR("Maximize: %d,%d %dx%d\n", wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); */ - if (Wnd->style & WS_MINIMIZE) - { - SwpFlags |= SWP_STATECHANGED; - Wnd->style &= ~WS_MINIMIZE; - } - Wnd->style |= WS_MAXIMIZE; + old_style = IntSetStyle( Wnd, WS_MAXIMIZE, WS_MINIMIZE ); + + if (!(old_style & WS_MAXIMIZE)) SwpFlags |= SWP_STATECHANGED; RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, // wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); Size.x, Size.y); break; } + case SW_SHOWNOACTIVATE: + Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; + /* fall through */ + case SW_SHOWNORMAL: case SW_RESTORE: + case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ { - if (Wnd->style & WS_MINIMIZE) + //ERR("MinMaximize Restore\n"); + old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); + if (old_style & WS_MINIMIZE) { - Wnd->style &= ~WS_MINIMIZE; if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED) { co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); + IntSetStyle( Wnd, WS_MAXIMIZE, 0 ); SwpFlags |= SWP_STATECHANGED; - Wnd->style |= WS_MAXIMIZE; /*ERR("Restore to Max: %d,%d %dx%d\n", wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); */ @@ -708,11 +850,10 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) } else { - if (!(Wnd->style & WS_MAXIMIZE)) + if (!(old_style & WS_MAXIMIZE)) { - return 0; + break; } - Wnd->style &= ~WS_MAXIMIZE; SwpFlags |= SWP_STATECHANGED; Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; *NewPos = wpl.rcNormalPosition; @@ -1020,17 +1161,17 @@ co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, if ((ClientRect->right - ClientRect->left != Window->rcClient.right - Window->rcClient.left) || - (ClientRect->bottom - ClientRect->top != - Window->rcClient.bottom - Window->rcClient.top)) + (ClientRect->bottom - ClientRect->top != + Window->rcClient.bottom - Window->rcClient.top)) { WinPos->flags &= ~SWP_NOCLIENTSIZE; } } else { - if (! (WinPos->flags & SWP_NOMOVE) - && (ClientRect->left != Window->rcClient.left || - ClientRect->top != Window->rcClient.top)) + if (!(WinPos->flags & SWP_NOMOVE) && + (ClientRect->left != Window->rcClient.left || + ClientRect->top != Window->rcClient.top)) { WinPos->flags &= ~SWP_NOCLIENTMOVE; } @@ -1118,7 +1259,7 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) if (hWndInsertAfter != HWND_TOPMOST) { - DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); + DesktopWindow = UserGetDesktopWindow(); List = IntWinListChildren(DesktopWindow); if (List != NULL) @@ -1163,10 +1304,10 @@ WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) { PWND Wnd; - if (List[i] == Window->head.h) + if (List[i] == UserHMGetHandle(Window)) break; - if (!(Wnd = ValidateHwndNoErr(List[i]))) + if (!(Wnd = ValidateHwndNoErr(List[i]))) continue; if (Wnd->style & WS_POPUP && Wnd->spwndOwner == Window) @@ -1288,7 +1429,7 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) if (WinPos->hwndInsertAfter == HWND_NOTOPMOST) { if (!(Wnd->ExStyle & WS_EX_TOPMOST)) - WinPos->flags |= SWP_NOZORDER; + WinPos->flags |= SWP_NOZORDER; WinPos->hwndInsertAfter = HWND_TOP; } @@ -1307,7 +1448,7 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) { PWND InsAfterWnd; - InsAfterWnd = ValidateHwndNoErr(WinPos->hwndInsertAfter); + InsAfterWnd = ValidateHwndNoErr(WinPos->hwndInsertAfter); if(!InsAfterWnd) { return TRUE; @@ -1375,16 +1516,6 @@ co_WinPosSetWindowPos( ASSERT_REFS_CO(Window); /* FIXME: Get current active window from active queue. */ - /* - * Only allow CSRSS to mess with the desktop window - */ - - if ( Window->head.h == IntGetDesktopWindow() && - Window->head.pti->ppi != PsGetCurrentProcessWin32Process()) - { - ERR("Desktop Window...\n"); - return FALSE; - } bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y); @@ -1559,7 +1690,7 @@ co_WinPosSetWindowPos( RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN); if (Window->spwndParent == UserGetDesktopWindow()) - co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (LPARAM)Window->head.h); + co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM)Window->head.h, 0); Window->style &= ~WS_VISIBLE; //IntSetStyle( Window, 0, WS_VISIBLE ); IntNotifyWinEvent(EVENT_OBJECT_HIDE, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); @@ -1567,7 +1698,7 @@ co_WinPosSetWindowPos( else if (WinPos.flags & SWP_SHOWWINDOW) { if (Window->spwndParent == UserGetDesktopWindow()) - co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)Window->head.h); + co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)Window->head.h, 0); Window->style |= WS_VISIBLE; //IntSetStyle( Window, WS_VISIBLE, 0 ); IntNotifyWinEvent(EVENT_OBJECT_SHOW, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); @@ -1795,7 +1926,7 @@ co_WinPosSetWindowPos( } else { - TRACE("SetWindowPos Set FG Window!\n"); + //ERR("SetWindowPos Set FG Window!\n"); co_IntSetForegroundWindow(Window); } } @@ -1891,15 +2022,18 @@ BOOLEAN FASTCALL co_WinPosShowWindow(PWND Wnd, INT Cmd) { BOOLEAN WasVisible; - UINT Swp = 0; + UINT Swp = 0, EventMsg = 0; RECTL NewPos; BOOLEAN ShowFlag; LONG style; PWND Parent; + PTHREADINFO pti; + BOOL ShowOwned = FALSE; // HRGN VisibleRgn; ASSERT_REFS_CO(Wnd); + pti = PsGetCurrentThreadWin32Thread(); WasVisible = (Wnd->style & WS_VISIBLE) != 0; style = Wnd->style; @@ -1912,11 +2046,12 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) return(FALSE); } Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; - if (Wnd->head.h != UserGetActiveWindow()) + if (Wnd != pti->MessageQueue->spwndActive) Swp |= SWP_NOACTIVATE | SWP_NOZORDER; break; } + case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */ case SW_SHOWMINNOACTIVE: Swp |= SWP_NOACTIVATE | SWP_NOZORDER; /* Fall through. */ @@ -1928,6 +2063,8 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Swp |= SWP_NOACTIVATE; if (!(style & WS_MINIMIZE)) { + //IntShowOwnedPopups(Wnd, FALSE ); + // Fix wine Win test_SetFocus todo #1 & #2, if (Cmd == SW_SHOWMINIMIZED) { @@ -1937,16 +2074,20 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) co_UserSetFocus(0); } - Swp |= co_WinPosMinMaximize(Wnd, SW_MINIMIZE, &NewPos) | + Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos) | SWP_FRAMECHANGED; + + EventMsg = EVENT_SYSTEM_MINIMIZESTART; } else { - Swp |= SWP_NOSIZE | SWP_NOMOVE; - if (! WasVisible) + if (!WasVisible) { Swp |= SWP_FRAMECHANGED; } + else //// + return TRUE; + Swp |= SWP_NOSIZE | SWP_NOMOVE; } break; } @@ -1956,68 +2097,87 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Swp |= SWP_SHOWWINDOW; if (!(style & WS_MAXIMIZE)) { + ShowOwned = TRUE; + Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos) | SWP_FRAMECHANGED; + + EventMsg = EVENT_SYSTEM_MINIMIZEEND; } else { - Swp |= SWP_NOSIZE | SWP_NOMOVE; - if (! WasVisible) + if (!WasVisible) { Swp |= SWP_FRAMECHANGED; } + else //// + return TRUE; + Swp |= SWP_NOSIZE | SWP_NOMOVE; } break; } case SW_SHOWNA: - Swp |= SWP_NOACTIVATE | SWP_NOZORDER; - /* Fall through. */ + Swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; + if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOZORDER; + break; case SW_SHOW: - if (WasVisible) return(TRUE); // Nothing to do! + if (WasVisible) return(TRUE); // Nothing to do! Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; /* Don't activate the topmost window. */ - if (style & WS_CHILD) Swp |= SWP_NOACTIVATE | SWP_NOZORDER; + if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOACTIVATE | SWP_NOZORDER; break; case SW_SHOWNOACTIVATE: - Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; - //Swp |= SWP_NOZORDER; Swp |= SWP_NOACTIVATE | SWP_NOZORDER; /* Fall through. */ case SW_SHOWNORMAL: case SW_SHOWDEFAULT: case SW_RESTORE: - Swp |= SWP_SHOWWINDOW; + if (!WasVisible) Swp |= SWP_SHOWWINDOW; if (style & (WS_MINIMIZE | WS_MAXIMIZE)) { - Swp |= co_WinPosMinMaximize(Wnd, SW_RESTORE, &NewPos) | + Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos) | SWP_FRAMECHANGED; + + if (style & WS_MINIMIZE) EventMsg = EVENT_SYSTEM_MINIMIZEEND; } else { - Swp |= SWP_NOSIZE | SWP_NOMOVE; - if (! WasVisible) + if (!WasVisible) { Swp |= SWP_FRAMECHANGED; } + else //// + return TRUE; + Swp |= SWP_NOSIZE | SWP_NOMOVE; } + if ( style & WS_CHILD && + !(Wnd->ExStyle & WS_EX_MDICHILD) && + !(Swp & SWP_STATECHANGED)) + Swp |= SWP_NOACTIVATE | SWP_NOZORDER; break; + + default: + return WasVisible; } ShowFlag = (Cmd != SW_HIDE); - if (ShowFlag != WasVisible) + if ((ShowFlag != WasVisible || Cmd == SW_SHOWNA) && Cmd != SW_SHOWMAXIMIZED && !(Swp & SWP_STATECHANGED)) { co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0); if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0); + if (!VerifyWnd(Wnd)) return WasVisible; } /* We can't activate a child window */ if ((Wnd->style & WS_CHILD) && - !(Wnd->ExStyle & WS_EX_MDICHILD)) + !(Wnd->ExStyle & WS_EX_MDICHILD) && + Cmd != SW_SHOWNA) { + //ERR("SWP Child No active and ZOrder\n"); Swp |= SWP_NOACTIVATE | SWP_NOZORDER; } @@ -2026,11 +2186,16 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Wnd->pcls->style & CS_SAVEBITS && ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL))) { - co_IntSetActiveWindow(Wnd,NULL,FALSE,TRUE); + co_IntSetActiveWindow(Wnd,NULL,FALSE,TRUE,FALSE); Swp |= SWP_NOACTIVATE | SWP_NOZORDER; } #endif + if (IsChildVisible(Wnd) || Swp & SWP_STATECHANGED) + { + TRACE("Child is Vis %s or State changed %s. ShowFlag %s\n", + (IsChildVisible(Wnd) ? "TRUE" : "FALSE"), (Swp & SWP_STATECHANGED ? "TRUE" : "FALSE"), + (ShowFlag ? "TRUE" : "FALSE")); co_WinPosSetWindowPos( Wnd, 0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP, NewPos.left, @@ -2038,13 +2203,24 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) NewPos.right, //NewPos.right - NewPos.left, NewPos.bottom, //NewPos.bottom - NewPos.top, LOWORD(Swp)); + } + else + { + TRACE("Parent Vis?\n"); + /* if parent is not visible simply toggle WS_VISIBLE and return */ + if (ShowFlag) IntSetStyle( Wnd, WS_VISIBLE, 0 ); + else IntSetStyle( Wnd, 0, WS_VISIBLE ); + } + + if ( EventMsg ) IntNotifyWinEvent(EventMsg, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); + + //if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE ); if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE)) { - PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); - - // and Rule #1. - if (Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue()) + if ( ( Wnd->spwndParent == UserGetDesktopWindow() && !ActivateOtherWindowMin(Wnd) ) || + // and Rule #1. + ( Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue() ) ) { co_WinPosActivateOtherWindow(Wnd); } @@ -2649,8 +2825,6 @@ NtUserMinMaximize( UINT cmd, // Wine SW_ commands BOOL Hide) { - RECTL NewPos; - UINT SwFlags; PWND pWnd; TRACE("Enter NtUserMinMaximize\n"); @@ -2670,17 +2844,7 @@ NtUserMinMaximize( goto Exit; } - SwFlags = co_WinPosMinMaximize(pWnd, cmd, &NewPos); - - SwFlags |= Hide ? SWP_NOACTIVATE : 0; - - co_WinPosSetWindowPos( pWnd, - NULL, - NewPos.left, - NewPos.top, - NewPos.right, //NewPos.right - NewPos.left, - NewPos.bottom, //NewPos.bottom - NewPos.top, - SwFlags); + cmd |= Hide ? SW_HIDE : 0; co_WinPosShowWindow(pWnd, cmd); @@ -2749,8 +2913,7 @@ NtUserSetWindowPos( UserEnterExclusive(); if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: -// Due to desktopbg.c -// Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { ERR("NtUserSetWindowPos bad window handle!\n"); diff --git a/reactos/win32ss/user/user32/controls/regcontrol.c b/reactos/win32ss/user/user32/controls/regcontrol.c index 60de50e9004..a0b82837858 100644 --- a/reactos/win32ss/user/user32/controls/regcontrol.c +++ b/reactos/win32ss/user/user32/controls/regcontrol.c @@ -146,8 +146,8 @@ BOOL WINAPI RegisterClientPFN(VOID) pfnClientW.pfnTitleWndProc = IconTitleWndProc; pfnClientA.pfnMenuWndProc = PopupMenuWndProcA; pfnClientW.pfnMenuWndProc = PopupMenuWndProcW; - pfnClientA.pfnDesktopWndProc = DesktopWndProc; - pfnClientW.pfnDesktopWndProc = DesktopWndProc; + pfnClientA.pfnDesktopWndProc = DesktopWndProcA; + pfnClientW.pfnDesktopWndProc = DesktopWndProcW; pfnClientA.pfnDefWindowProc = DefWindowProcA; pfnClientW.pfnDefWindowProc = DefWindowProcW; pfnClientA.pfnMessageWindowProc = MsgWindowProc; diff --git a/reactos/win32ss/user/user32/include/controls.h b/reactos/win32ss/user/user32/include/controls.h index f80b7dc1294..15ddd867ae7 100644 --- a/reactos/win32ss/user/user32/include/controls.h +++ b/reactos/win32ss/user/user32/include/controls.h @@ -90,7 +90,8 @@ extern BOOL COMBO_FlipListbox( LPHEADCOMBO, BOOL, BOOL ); HRGN set_control_clipping( HDC hdc, const RECT *rect ); -LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); +LRESULT WINAPI DesktopWndProcA( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); +LRESULT WINAPI DesktopWndProcW( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); LRESULT WINAPI User32DefWindowProc(HWND,UINT,WPARAM,LPARAM,BOOL); BOOL WINAPI RegisterClientPFN(VOID); LRESULT WINAPI IconTitleWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ); diff --git a/reactos/win32ss/user/user32/misc/desktop.c b/reactos/win32ss/user/user32/misc/desktop.c index 0783e9f3120..a9833934a93 100644 --- a/reactos/win32ss/user/user32/misc/desktop.c +++ b/reactos/win32ss/user/user32/misc/desktop.c @@ -29,13 +29,61 @@ const struct builtin_class_descr DESKTOP_builtin_class = (HBRUSH)(COLOR_BACKGROUND+1) /* brush */ }; #endif + LRESULT WINAPI -DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) +DesktopWndProcW(HWND Wnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) { - TRACE("Desktop Class Atom! hWnd 0x%x, Msg %d\n", hwnd, message); - if (message == WM_NCCREATE) return TRUE; - return 0; /* all other messages are ignored */ + PAINTSTRUCT PS; + TRACE("Desktop W Class Atom! hWnd 0x%x, Msg %d\n", Wnd, Msg); + + switch(Msg) + { + case WM_NCCREATE: + case WM_CREATE: + case WM_CLOSE: + case WM_DISPLAYCHANGE: + { + LRESULT lResult; + NtUserMessageCall( Wnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DESKTOP, FALSE); + return lResult; + } + + case WM_ERASEBKGND: + PaintDesktop((HDC)wParam); + return 1; + + case WM_PAINT: + if (BeginPaint(Wnd, &PS)) + { + EndPaint(Wnd, &PS); + } + return 0; + + case WM_SYSCOLORCHANGE: + RedrawWindow(Wnd, NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); + break; + + case WM_PALETTECHANGED: + if (Wnd == (HWND)wParam) break; + case WM_QUERYNEWPALETTE: + { + HDC hdc = GetWindowDC( Wnd ); + PaintDesktop(hdc); + ReleaseDC( Wnd, hdc ); + break; + } + + case WM_SETCURSOR: + return (LRESULT)SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW)); + + default: + return DefWindowProcW(Wnd, Msg, wParam, lParam); + } + return 0; } VOID diff --git a/reactos/win32ss/user/user32/windows/message.c b/reactos/win32ss/user/user32/windows/message.c index d75449b2f6f..d87beec1f1f 100644 --- a/reactos/win32ss/user/user32/windows/message.c +++ b/reactos/win32ss/user/user32/windows/message.c @@ -1158,7 +1158,33 @@ map_wparam_AtoW( UINT message, WPARAM wparam ) return wparam; } ++LRESULT ++WINAPI +DesktopWndProcA( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) +{ + LRESULT Result; + MSG AnsiMsg, UcMsg; + TRACE("Desktop A Class Atom! hWnd 0x%x, Msg %d\n", hwnd, message); + + AnsiMsg.hwnd = hwnd; + AnsiMsg.message = message; + AnsiMsg.wParam = wParam; + AnsiMsg.lParam = lParam; + + // Desktop is always Unicode so convert Ansi here. + if (!MsgiAnsiToUnicodeMessage(hwnd, &UcMsg, &AnsiMsg)) + { + return FALSE; + } + + Result = DesktopWndProcW(hwnd, message, UcMsg.wParam, UcMsg.lParam); + + MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg); + + return Result; + } + /* * @implemented */ diff --git a/reactos/win32ss/user/win32csr/desktopbg.c b/reactos/win32ss/user/win32csr/desktopbg.c index 123b148bae2..4edd7a3fb2c 100644 --- a/reactos/win32ss/user/win32csr/desktopbg.c +++ b/reactos/win32ss/user/win32csr/desktopbg.c @@ -1,10 +1,27 @@ -/* $Id$ - * - * reactos/subsys/csrss/win32csr/desktopbg.c +/* + * win32ss/user/win32csr/desktopbg.c * * Desktop background window functions * * ReactOS Operating System + * + * Looks as a hax fix to a problem of not having a proper class window proc support + * which ReactOS has now. + * + * Notes on reason why this is here: + * http://www.reactos.org/archives/public/ros-kernel/2003-November/000538.html + * http://www.reactos.org/archives/public/ros-kernel/2003-November/000545.html + * http://www.reactos.org/archives/public/ros-kernel/2003-November/000586.html + * http://www.reactos.org/archives/public/ros-kernel/2003-November/000674.html + * Revision 6908 Move desktop window proc from WIN32K to CSRSS + * Bugs 42, 48 and 57. + * + * http://www.reactos.org/archives/public/ros-kernel/2003-December/001186.html + * + + Now this is used to start Desktops Threads with TEB support. + These first three are Application, Winlogon and ScreenSaver desktops. + */ #define NDEBUG @@ -36,7 +53,7 @@ typedef struct tagPRIVATE_NOTIFY_DESKTOP static BOOL BgInitialized = FALSE; static HWND VisibleDesktopWindow = NULL; - +#if 0 static LRESULT CALLBACK @@ -160,7 +177,7 @@ DtbgInit(VOID) return TRUE; } - +#endif static DWORD WINAPI @@ -170,6 +187,8 @@ DtbgDesktopThread(PVOID Data) MSG msg; PDTBG_THREAD_DATA ThreadData = (PDTBG_THREAD_DATA)Data; + DPRINT("DtbgDesktopThread\n"); + if (!SetThreadDesktop(ThreadData->Desktop)) { DPRINT1("Failed to set thread desktop\n"); @@ -181,9 +200,12 @@ DtbgDesktopThread(PVOID Data) BackgroundWnd = CreateWindowW((LPCWSTR)DESKTOP_WINDOW_ATOM, L"", WS_POPUP | WS_CLIPCHILDREN, - 0, 0, 0, 0, + GetSystemMetrics(SM_XVIRTUALSCREEN), + GetSystemMetrics(SM_YVIRTUALSCREEN), + GetSystemMetrics(SM_CXVIRTUALSCREEN), + GetSystemMetrics(SM_CYVIRTUALSCREEN), NULL, NULL, - (HINSTANCE)GetModuleHandleW(NULL), + (HINSTANCE)GetModuleHandleW(L"user32.dll"), // Run in win32k/user32. NULL); if (NULL == BackgroundWnd) @@ -194,15 +216,22 @@ DtbgDesktopThread(PVOID Data) return 1; } + DPRINT("BackgroundWnd 0x%p\n",BackgroundWnd); + ThreadData->Status = STATUS_SUCCESS; SetEvent(ThreadData->Event); while (GetMessageW(&msg, NULL, 0, 0)) { + if (msg.message == WM_QUIT) + { + DPRINT1("DtbgDesktopThread WM_QUIT\n"); + } TranslateMessage(&msg); DispatchMessageW(&msg); } + DPRINT1("DtbgDesktopThread Exit\n"); return 1; } @@ -217,8 +246,8 @@ CSR_API(CsrCreateDesktop) { BgInitialized = TRUE; - if (!DtbgInit()) - return STATUS_UNSUCCESSFUL; + // if (!DtbgInit()) + // return STATUS_UNSUCCESSFUL; } /* @@ -259,6 +288,7 @@ CSR_API(CsrCreateDesktop) CSR_API(CsrShowDesktop) { +#if 0 PRIVATE_NOTIFY_DESKTOP nmh; DPRINT("CsrShowDesktop\n"); @@ -276,12 +306,13 @@ CSR_API(CsrShowDesktop) { return STATUS_UNSUCCESSFUL; } - +#endif return STATUS_SUCCESS; } CSR_API(CsrHideDesktop) { +#if 0 PRIVATE_NOTIFY_DESKTOP nmh; DPRINT("CsrHideDesktop\n"); @@ -296,7 +327,7 @@ CSR_API(CsrHideDesktop) { return STATUS_UNSUCCESSFUL; } - +#endif return STATUS_SUCCESS; } @@ -304,6 +335,8 @@ BOOL FASTCALL DtbgIsDesktopVisible(VOID) { + VisibleDesktopWindow = GetDesktopWindow(); // DESKTOPWNDPROC + if (VisibleDesktopWindow != NULL && !IsWindowVisible(VisibleDesktopWindow)) {