diff --git a/reactos/win32ss/user/ntuser/desktop.c b/reactos/win32ss/user/ntuser/desktop.c index e67ac78aee1..8b073dc0dcf 100644 --- a/reactos/win32ss/user/ntuser/desktop.c +++ b/reactos/win32ss/user/ntuser/desktop.c @@ -28,7 +28,7 @@ IntFreeDesktopHeap(IN PDESKTOP pdesk); /* Currently active desktop */ PDESKTOP gpdeskInputDesktop = NULL; HDC ScreenDeviceContext = NULL; -PTHREADINFO gptiDesktopThread; +PTHREADINFO gptiDesktopThread = NULL; HCURSOR gDesktopCursor = NULL; /* OBJECT CALLBACKS **********************************************************/ @@ -834,6 +834,9 @@ VOID co_IntShellHookNotify(WPARAM Message, WPARAM wParam, LPARAM lParam) return; } + // Allow other devices have a shot at foreground. + if (Message == HSHELL_APPCOMMAND) ptiLastInput = NULL; + // FIXME: System Tray Support. HwndList = UserBuildShellHookHwndList(Desktop); diff --git a/reactos/win32ss/user/ntuser/desktop.h b/reactos/win32ss/user/ntuser/desktop.h index 25e1f9e331c..9d2fd2ef284 100644 --- a/reactos/win32ss/user/ntuser/desktop.h +++ b/reactos/win32ss/user/ntuser/desktop.h @@ -69,9 +69,10 @@ typedef struct _DESKTOP DESKTOP_SWITCHDESKTOP | \ DESKTOP_WRITEOBJECTS -extern PDESKTOP InputDesktop; +extern PDESKTOP gpdeskInputDesktop; extern PCLS DesktopWindowClass; extern HDC ScreenDeviceContext; +extern PTHREADINFO gptiForeground; extern PTHREADINFO gptiDesktopThread; typedef struct _SHELL_HOOK_WINDOW diff --git a/reactos/win32ss/user/ntuser/focus.c b/reactos/win32ss/user/ntuser/focus.c index 8902c129b84..cf79511c2d9 100644 --- a/reactos/win32ss/user/ntuser/focus.c +++ b/reactos/win32ss/user/ntuser/focus.c @@ -80,7 +80,7 @@ BOOL FASTCALL co_IntMakeWindowActive(PWND Window) { PWND spwndOwner; - if (Window) + if (VerifyWnd(Window)) { // Set last active for window and it's owner. spwndOwner = Window; while (spwndOwner->spwndOwner) @@ -132,6 +132,7 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO { UINT flags = SWP_NOSIZE | SWP_NOMOVE; if (Window == pwndTemp) flags |= SWP_NOACTIVATE; + //ERR("co_IntSendActivateMessages SetWindowPos! Async %d pti Q == FGQ %d\n",Async,pti->MessageQueue == gpqForeground); co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, flags); } } @@ -156,8 +157,7 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO if ( OldTID ) { ptiOld->TIF_flags |= TIF_INACTIVATEAPPMSG; - ptiOld->pClientInfo->dwTIFlags = ptiOld->TIF_flags; - + // Note: Do not set pci flags, this does crash! for (phWnd = List; *phWnd; ++phWnd) { cWindow = ValidateHwndNoErr(*phWnd); @@ -168,13 +168,11 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO } } 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) { @@ -186,7 +184,7 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO } } } - ExFreePoolWithTag(List, USERTAG_WINDOWLIST); + ExFreePool(List);//ExFreePoolWithTag(List, USERTAG_WINDOWLIST); } } if (WindowPrev) @@ -205,12 +203,11 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO co_IntMakeWindowActive(Window); - UserDerefObjectCo(Window); - /* FIXME: IntIsWindow */ + co_IntSendMessageNoWait( UserHMGetHandle(Window), WM_NCACTIVATE, - (WPARAM)(gpqForeground ? (Window == gpqForeground->spwndActive) : FALSE), + (WPARAM)(Window == (gpqForeground ? gpqForeground->spwndActive : NULL)), 0); //(LPARAM)hWndPrev); co_IntSendMessageNoWait( UserHMGetHandle(Window), @@ -226,6 +223,7 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO Window->state &= ~WNDS_NONCPAINT; + UserDerefObjectCo(Window); } return InAAPM; } @@ -294,7 +292,7 @@ IntFindChildWindowToOwner(PWND Root, PWND Owner) } VOID FASTCALL -FindRemoveAsyncMsg(PWND Wnd) +FindRemoveAsyncMsg(PWND Wnd, WPARAM wParam) { PTHREADINFO pti; PUSER_SENT_MESSAGE Message; @@ -311,20 +309,60 @@ FindRemoveAsyncMsg(PWND Wnd) Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); do { + if (IsListEmpty(Entry)) return; + if (!Message) return; + Entry = Message->ListEntry.Flink; + if (Message->Msg.message == WM_ASYNC_SETACTIVEWINDOW && Message->Msg.hwnd == UserHMGetHandle(Wnd) && - Message->Msg.wParam == 0 ) + Message->Msg.wParam == wParam ) { - TRACE("ASYNC SAW: Found one in the Sent Msg Queue! %p\n", Message->Msg.hwnd); - RemoveEntryList(Entry); // Purge the entry. + ERR("ASYNC SAW: Found one in the Sent Msg Queue! %p Activate/Deactivate %d\n", Message->Msg.hwnd,!!wParam); + RemoveEntryList(&Message->ListEntry); // Purge the entry. + ExFreePoolWithTag(Message, TAG_USRMSG); } - Entry = Message->ListEntry.Flink; Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); } while (Entry != &pti->SentMessagesListHead); } } +BOOL FASTCALL +ToggleFGActivate(PTHREADINFO pti) +{ + BOOL Ret; + PPROCESSINFO ppi = pti->ppi; + + Ret = !!(pti->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE); + if (Ret) + { + pti->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE; + } + else + Ret = !!(ppi->W32PF_flags & W32PF_ALLOWFOREGROUNDACTIVATE); + + if (Ret) + ppi->W32PF_flags &= ~W32PF_ALLOWFOREGROUNDACTIVATE; + //ERR("ToggleFGActivate is %d\n",Ret); + return Ret; +} + +BOOL FASTCALL +IsAllowedFGActive(PTHREADINFO pti, PWND Wnd) +{ + // Not allowed if one or more,, + if (!ToggleFGActivate(pti) || // bits not set, + pti->rpdesk != gpdeskInputDesktop || // not current Desktop, + pti->MessageQueue == gpqForeground || // if already the queue foreground, + IsFGLocked() || // foreground is locked, + Wnd->ExStyle & WS_EX_NOACTIVATE ) // or,,, does not become the foreground window when the user clicks it. + { + return FALSE; + } + //ERR("IsAllowedFGActive is TRUE\n"); + return TRUE; +} + /* Can the system force foreground from one or more conditions. */ @@ -339,6 +377,7 @@ CanForceFG(PPROCESSINFO ppi) gppiInputProvider == ppi || !gpqForeground ) return TRUE; + //ERR("CanForceFG is FALSE\n"); return FALSE; } @@ -356,37 +395,35 @@ CanForceFG(PPROCESSINFO ppi) * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo). * No menus are active. */ - -static BOOL FASTCALL +static +BOOL FASTCALL co_IntSetForegroundAndFocusWindow( _In_ PWND Wnd, _In_ BOOL MouseActivate) { - HWND hWnd; + HWND hWnd = Wnd ? UserHMGetHandle(Wnd) : NULL; HWND hWndPrev = NULL; + PWND pWndPrev = NULL; PUSER_MESSAGE_QUEUE PrevForegroundQueue; PTHREADINFO pti; BOOL fgRet = FALSE, Ret = FALSE; - ASSERT_REFS_CO(Wnd); - NT_ASSERT(Wnd != NULL); + if (Wnd) ASSERT_REFS_CO(Wnd); - hWnd = UserHMGetHandle(Wnd); - - TRACE("SetForegroundAndFocusWindow(%p, %s)\n", hWnd, (MouseActivate ? "TRUE" : "FALSE")); + //ERR("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) { + //ERR("Same Window Q as foreground just do active.\n"); if (pti->MessageQueue == PrevForegroundQueue) { // Same WQ and TQ go active. //ERR("Same WQ and TQ go active.\n"); - Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE, FALSE); + Ret = co_IntSetActiveWindow(Wnd, MouseActivate, TRUE, FALSE); } else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) { // Same WQ and it is active. @@ -396,13 +433,14 @@ co_IntSetForegroundAndFocusWindow( 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 ); + co_IntSendMessage(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate ); Ret = TRUE; } return Ret; } hWndPrev = PrevForegroundQueue->spwndActive ? UserHMGetHandle(PrevForegroundQueue->spwndActive) : 0; + pWndPrev = PrevForegroundQueue->spwndActive; } if ( (( !IsFGLocked() || pti->ppi == gppiInputProvider ) && @@ -410,16 +448,29 @@ co_IntSetForegroundAndFocusWindow( pti->ppi == ppiScrnSaver ) { - 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); + + //ToggleFGActivate(pti); // win.c line 2662 fail + if (Wnd) + { + IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue); + gptiForeground = Wnd->head.pti; + //ERR("Set Foreground pti 0x%p Q 0x%p hWnd 0x%p\n",Wnd->head.pti, Wnd->head.pti->MessageQueue,Wnd->head.h); + } + else + { + IntSetFocusMessageQueue(NULL); + gptiForeground = NULL; + //ERR("Set Foreground pti 0x0 Q 0x0 hWnd 0x0\n"); + } /* Henri Verbeet, What happens is that we get the WM_WINE_SETACTIVEWINDOW message sent by the other thread after we already changed the foreground window back to our own window. */ - FindRemoveAsyncMsg(Wnd); // Do this to fix test_SFW todos! + //ERR("SFAFW: 1\n"); + FindRemoveAsyncMsg(Wnd, 0); // Do this to fix test_SFW todos! + fgRet = TRUE; } @@ -428,34 +479,41 @@ co_IntSetForegroundAndFocusWindow( { if (PrevForegroundQueue && fgRet && - Wnd->head.pti->MessageQueue != PrevForegroundQueue && PrevForegroundQueue->spwndActive) { //ERR("SFGW: Send NULL to 0x%x\n",hWndPrev); if (pti->MessageQueue == PrevForegroundQueue) { //ERR("SFGW: TI same as Prev TI\n"); - co_IntSetActiveWindow(NULL, NULL, FALSE, TRUE, FALSE); + co_IntSetActiveWindow(NULL, FALSE, TRUE, FALSE); + } + else if (pWndPrev) + { + //ERR("SFGW Deactivate: TI not same as Prev TI\n"); + // No real reason to wait here. + co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 ); } - else - co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 ); } } + if (!Wnd) return FALSE; // Always return false. + if (pti->MessageQueue == Wnd->head.pti->MessageQueue) { - Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE, FALSE); + //ERR("Same PQ and WQ go active.\n"); + Ret = co_IntSetActiveWindow(Wnd, MouseActivate, TRUE, FALSE); } else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) { + //ERR("Same Active and Wnd.\n"); Ret = TRUE; } else { + //ERR("Activate Not same PQ and WQ and Wnd.\n"); co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate ); Ret = TRUE; } - return Ret && fgRet; } @@ -500,7 +558,7 @@ co_IntMouseActivateWindow(PWND Wnd) } BOOL FASTCALL -co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, BOOL Async) +co_IntSetActiveWindow(PWND Wnd OPTIONAL, BOOL bMouse, BOOL bFocus, BOOL Async) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; @@ -509,38 +567,83 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, HWND hWnd = 0; BOOL InAAPM; CBTACTIVATESTRUCT cbt; - + //ERR("co_IntSetActiveWindow 1\n"); 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; + //ERR("co_IntSetActiveWindow 1a hWnd 0x%p\n",hWnd); } + //ERR("co_IntSetActiveWindow 2\n"); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL; - if (Prev) *Prev = hWndPrev; - if (hWndPrev == hWnd) return TRUE; pWndChg = ThreadQueue->spwndActive; // Keep to notify of a preemptive switch. - if (Wnd) + while (Wnd) { - if (ThreadQueue != Wnd->head.pti->MessageQueue) - { - PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); - // Rule 1 & 4, We are foreground so set this FG window or NULL foreground.... - if (!ForegroundQueue || ForegroundQueue == ThreadQueue) - { - return co_IntSetForegroundAndFocusWindow(Wnd, bMouse); - } - } + BOOL Ret, DoFG, AllowFG; if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE; + + if (ThreadQueue == Wnd->head.pti->MessageQueue) + { + if (IsAllowedFGActive(pti, Wnd)) + { + DoFG = TRUE; + } + else + { + //ERR("co_IntSetActiveWindow 3 Go Out!\n"); + break; + } + AllowFG = !pti->cVisWindows; // Nothing is visable. + //ERR("co_IntSetActiveWindow 3a DoFG = %d AllowFG = %d\n",DoFG,AllowFG); + } + else //if (ThreadQueue != Wnd->head.pti->MessageQueue) + { + //PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); + // Rule 1 & 4, We are foreground so set this FG window or NULL foreground.... + //if (!ForegroundQueue || ForegroundQueue == ThreadQueue) + if (!gpqForeground || gpqForeground == ThreadQueue) + { + DoFG = TRUE; + } + else + DoFG = FALSE; + if (DoFG) + { + if (pti->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE || pti->cVisWindows) + AllowFG = TRUE; + else + AllowFG = FALSE; + } + else + AllowFG = FALSE; + //ERR("co_IntSetActiveWindow 3b DoFG = %d AllowFG = %d\n",DoFG,AllowFG); + } + Ret = FALSE; + if (DoFG) + { + pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; + //ERR("co_IntSetActiveWindow 3c FG set\n"); + Ret = co_IntSetForegroundAndFocusWindow(Wnd, bMouse); + if (AllowFG) + { + pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; + } + else + { + pti->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE; + } + } + return Ret; } /* Call CBT hook chain */ @@ -562,14 +665,16 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, if (WndPrev) { if (ThreadQueue == gpqForeground) gpqForegroundPrev = ThreadQueue; - if (!co_IntSendDeactivateMessages(hWndPrev, hWnd)) return FALSE; + if (!co_IntSendDeactivateMessages(UserHMGetHandle(WndPrev), hWnd)) return FALSE; } + WndPrev = ThreadQueue->spwndActive; // Again keep to save changing active. + // 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 || + pWndChg != WndPrev || (Wnd && !VerifyWnd(Wnd)) || ThreadQueue != pti->MessageQueue ) { @@ -582,6 +687,8 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED; IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); + //// Breaks Atl-Esc/Tab via User32. + ////FindRemoveAsyncMsg(Wnd,(WPARAM)Wnd); // Clear out activate ASYNC messages. /* check if the specified window can be set in the input data of a given queue */ if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue) @@ -590,6 +697,8 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, ThreadQueue->spwndActive = Wnd; } + WndPrev = VerifyWnd(ThreadQueue->spwndActivePrev); // Now should be set but verify it again. + InAAPM = co_IntSendActivateMessages(WndPrev, Wnd, bMouse, Async); /* now change focus if necessary */ @@ -610,16 +719,40 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, if (InAAPM) { pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG; - pti->pClientInfo->dwTIFlags = pti->TIF_flags; } // FIXME: Used in the menu loop!!! //ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE; + //ERR("co_IntSetActiveWindow Exit\n"); if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED; return (ThreadQueue->spwndActive == Wnd); } +BOOL FASTCALL +UserSetActiveWindow(PWND Wnd) +{ + if (Wnd) // Must have a window! + { + if ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; + + return co_IntSetActiveWindow(Wnd, FALSE, TRUE, FALSE); + } + /* + Yes your eye are not deceiving you~! + + First part of wines Win.c test_SetActiveWindow: + + flush_events( TRUE ); + ShowWindow(hwnd, SW_HIDE); + SetFocus(0); + SetActiveWindow(0); + check_wnd_state(0, 0, 0, 0); <-- This should pass if ShowWindow does it's job!!! As of 10/28/2012 it does! + + */ + return FALSE; +} + HWND FASTCALL co_UserSetFocus(PWND Window) { @@ -653,17 +786,10 @@ co_UserSetFocus(PWND Window) } /* Check if we can set the focus to this window */ - pwndTop = Window; - for (;;) + for (pwndTop = Window; pwndTop != NULL; pwndTop = pwndTop->spwndParent) { if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0; - 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 ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break; } if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) @@ -676,8 +802,13 @@ co_UserSetFocus(PWND Window) if (pwndTop != ThreadQueue->spwndActive) { PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Keep it based on desktop. - if (ThreadQueue != ForegroundQueue) // HACK see rule 2 & 3. + if (ThreadQueue != ForegroundQueue && IsAllowedFGActive(pti, pwndTop)) // Rule 2 & 3. { + //ERR("SetFocus: Set Foreground!\n"); + if (!(pwndTop->style & WS_VISIBLE)) + { + pti->ppi->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; + } if (!co_IntSetForegroundAndFocusWindow(pwndTop, FALSE)) { ERR("SetFocus: Set Foreground and Focus Failed!\n"); @@ -688,7 +819,8 @@ co_UserSetFocus(PWND Window) /* Set Active when it is needed. */ if (pwndTop != ThreadQueue->spwndActive) { - if (!co_IntSetActiveWindow(pwndTop, NULL, FALSE, FALSE, FALSE)) + //ERR("SetFocus: Set Active!\n"); + if (!co_IntSetActiveWindow(pwndTop, FALSE, FALSE, FALSE)) { ERR("SetFocus: Set Active Failed!\n"); return 0; @@ -714,8 +846,6 @@ co_UserSetFocus(PWND Window) } else /* NULL hwnd passed in */ { -// if (!hWndPrev) return 0; /* nothing to do */ - if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) { ERR("SetFocus: 2 WH_CBT Call Hook return!\n"); @@ -857,7 +987,7 @@ IntReleaseCapture(VOID) BOOL FASTCALL co_IntSetForegroundWindow(PWND Window) { - ASSERT_REFS_CO(Window); + if (Window) ASSERT_REFS_CO(Window); return co_IntSetForegroundAndFocusWindow(Window, FALSE); } @@ -937,12 +1067,13 @@ IntAllowSetForegroundWindow(DWORD dwProcessId) } if (dwProcessId == ASFW_ANY) { // All processes will be enabled to set the foreground window. + //ERR("ptiLastInput is CLEARED!!\n"); ptiLastInput = NULL; } else { // Rule #3, last input event in force. - ERR("Fixme: ptiLastInput is SET!!\n"); - //ptiLastInput = ppi->ptiList; + ERR("ptiLastInput is SET!!\n"); + //ptiLastInput = ppi->ptiList; // See CORE-6384 & CORE-7030. ObDereferenceObject(Process); } return TRUE; @@ -962,7 +1093,7 @@ NtUserGetForegroundWindow(VOID) RETURN( UserGetForegroundWindow()); CLEANUP: - TRACE("Leave NtUserGetForegroundWindow, ret=%p\n", _ret_); + TRACE("Leave NtUserGetForegroundWindow, ret=%p\n",_ret_); UserLeave(); END_CLEANUP; } @@ -993,7 +1124,7 @@ NtUserSetActiveWindow(HWND hWnd) { hWndPrev = gptiCurrent->MessageQueue->spwndActive ? UserHMGetHandle(gptiCurrent->MessageQueue->spwndActive) : NULL; if (Window) UserRefObjectCo(Window, &Ref); - co_IntSetActiveWindow(Window, NULL, FALSE, TRUE, FALSE); + UserSetActiveWindow(Window); if (Window) UserDerefObjectCo(Window); RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 ); } diff --git a/reactos/win32ss/user/ntuser/focus.h b/reactos/win32ss/user/ntuser/focus.h index 48ac7efacd1..bc82c3bf5da 100644 --- a/reactos/win32ss/user/ntuser/focus.h +++ b/reactos/win32ss/user/ntuser/focus.h @@ -2,6 +2,7 @@ extern PUSER_MESSAGE_QUEUE gpqForeground; extern PUSER_MESSAGE_QUEUE gpqForegroundPrev; +extern PTHREADINFO ptiLastInput; /* * These functions take the window handles from current message queue. @@ -18,7 +19,8 @@ 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,HWND *,BOOL,BOOL,BOOL); BOOL FASTCALL co_IntSetForegroundWindowMouse(PWND Window); +BOOL FASTCALL co_IntSetActiveWindow(PWND,BOOL,BOOL,BOOL); +BOOL FASTCALL UserSetActiveWindow(PWND Wnd); BOOL FASTCALL IntLockSetForegroundWindow(UINT uLockCode); BOOL FASTCALL IntAllowSetForegroundWindow(DWORD dwProcessId); diff --git a/reactos/win32ss/user/ntuser/input.c b/reactos/win32ss/user/ntuser/input.c index 04382acac94..4223669256a 100644 --- a/reactos/win32ss/user/ntuser/input.c +++ b/reactos/win32ss/user/ntuser/input.c @@ -402,24 +402,47 @@ NtUserBlockInput( return ret; } -PTHREADINFO FASTCALL -IsThreadAttach(PTHREADINFO ptiTo) +BOOL +FASTCALL +IsRemoveAttachThread(PTHREADINFO pti) { + NTSTATUS Status; PATTACHINFO pai; + BOOL Ret = TRUE; + PTHREADINFO ptiFrom = NULL, ptiTo = NULL; - if (!gpai) return NULL; - - pai = gpai; do { - if (pai->pti2 == ptiTo) break; - pai = pai->paiNext; - } while (pai); + if (!gpai) return TRUE; + + pai = gpai; // Bottom of the list. - if (!pai) return NULL; + do + { + if (pai->pti2 == pti) + { + ptiFrom = pai->pti1; + ptiTo = pti; + break; + } + if (pai->pti1 == pti) + { + ptiFrom = pti; + ptiTo = pai->pti2; + break; + } + pai = pai->paiNext; + + } while (pai); - // Return ptiFrom. - return pai->pti1; + if (!pai && !ptiFrom && !ptiTo) break; + + Status = UserAttachThreadInput(ptiFrom, ptiTo, FALSE); + if (!NT_SUCCESS(Status)) Ret = FALSE; + + } while (Ret); + + return Ret; } NTSTATUS FASTCALL @@ -454,44 +477,52 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach) paiCount++; ERR("Attach Allocated! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount); - if (ptiTo->MessageQueue == ptiFrom->MessageQueue) + if (ptiTo->MessageQueue != ptiFrom->MessageQueue) + { + + ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel; + + // FIXME: conditions? + if (ptiTo->MessageQueue == gpqForeground) + { + ERR("ptiTo is Foreground\n"); + } + else + { + ERR("ptiTo NOT Foreground\n"); + } + + if (ptiFrom->MessageQueue == gpqForeground) + { + ERR("ptiFrom is Foreground\n"); + ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive; + ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus; + ptiTo->MessageQueue->CursorObject = ptiFrom->MessageQueue->CursorObject; + ptiTo->MessageQueue->spwndCapture = ptiFrom->MessageQueue->spwndCapture; + ptiTo->MessageQueue->QF_flags ^= ((ptiTo->MessageQueue->QF_flags ^ ptiFrom->MessageQueue->QF_flags) & QF_CAPTURELOCKED); + ptiTo->MessageQueue->CaretInfo = ptiFrom->MessageQueue->CaretInfo; + IntSetFocusMessageQueue(NULL); + IntSetFocusMessageQueue(ptiTo->MessageQueue); + gptiForeground = ptiTo; + } + else + { + ERR("ptiFrom NOT Foreground\n"); + } + + MsqDestroyMessageQueue(ptiFrom); + + ptiFrom->MessageQueue = ptiTo->MessageQueue; + + ptiFrom->MessageQueue->cThreads++; + ERR("ptiTo S Share count %d\n", ptiFrom->MessageQueue->cThreads); + + IntReferenceMessageQueue(ptiTo->MessageQueue); + } + else { ERR("Attach Threads are already associated!\n"); } - - ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel; - - /* Keep the original queue in pqAttach (ie do not trash it in a second attachment) */ - if (ptiFrom->pqAttach == NULL) - ptiFrom->pqAttach = ptiFrom->MessageQueue; - ptiFrom->MessageQueue = ptiTo->MessageQueue; - - ptiFrom->MessageQueue->cThreads++; - ERR("ptiTo S Share count %lu\n", ptiFrom->MessageQueue->cThreads); - - // FIXME: conditions? - if (ptiFrom->pqAttach == gpqForeground) - { - ERR("ptiFrom is Foreground\n"); - ptiFrom->MessageQueue->spwndActive = ptiFrom->pqAttach->spwndActive; - ptiFrom->MessageQueue->spwndFocus = ptiFrom->pqAttach->spwndFocus; - ptiFrom->MessageQueue->CursorObject = ptiFrom->pqAttach->CursorObject; - ptiFrom->MessageQueue->spwndCapture = ptiFrom->pqAttach->spwndCapture; - ptiFrom->MessageQueue->QF_flags ^= ((ptiFrom->MessageQueue->QF_flags ^ ptiFrom->pqAttach->QF_flags) & QF_CAPTURELOCKED); - ptiFrom->MessageQueue->CaretInfo = ptiFrom->pqAttach->CaretInfo; - } - else - { - ERR("ptiFrom NOT Foreground\n"); - } - if (ptiTo->MessageQueue == gpqForeground) - { - ERR("ptiTo is Foreground\n"); - } - else - { - ERR("ptiTo NOT Foreground\n"); - } } else /* If clear, unlink and free it. */ { @@ -518,41 +549,31 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach) } if (!Hit) return STATUS_INVALID_PARAMETER; - - ASSERT(ptiFrom->pqAttach); ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount); - - /* Search list and check if the thread is attached one more time */ - pai = gpai; - while(pai) + + if (ptiTo->MessageQueue == ptiFrom->MessageQueue) { - /* If the thread is attached again , we are done */ - if (pai->pti1 == ptiFrom) - { - ptiFrom->MessageQueue->cThreads--; - ERR("ptiTo L Share count %lu\n", ptiFrom->MessageQueue->cThreads); - /* Use the message queue of the last attachment */ - ptiFrom->MessageQueue = pai->pti2->MessageQueue; - ptiFrom->MessageQueue->CursorObject = NULL; - ptiFrom->MessageQueue->spwndActive = NULL; - ptiFrom->MessageQueue->spwndFocus = NULL; - ptiFrom->MessageQueue->spwndCapture = NULL; - return STATUS_SUCCESS; - } - pai = pai->paiNext; - } + if (gptiForeground == ptiFrom) + { + ERR("ptiTo is now pti FG.\n"); + // MessageQueue foreground is set so switch threads. + gptiForeground = ptiTo; + } + ptiTo->MessageQueue->cThreads--; + ERR("ptiTo E Share count %d\n", ptiTo->MessageQueue->cThreads); + ASSERT(ptiTo->MessageQueue->cThreads >= 1); - ptiFrom->MessageQueue->cThreads--; - ERR("ptiTo E Share count %lu\n", ptiFrom->MessageQueue->cThreads); - ptiFrom->MessageQueue = ptiFrom->pqAttach; - // FIXME: conditions? - ptiFrom->MessageQueue->CursorObject = NULL; - ptiFrom->MessageQueue->spwndActive = NULL; - ptiFrom->MessageQueue->spwndFocus = NULL; - ptiFrom->MessageQueue->spwndCapture = NULL; - ptiFrom->pqAttach = NULL; - ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel; + IntDereferenceMessageQueue(ptiTo->MessageQueue); + + ptiFrom->MessageQueue = MsqCreateMessageQueue(ptiFrom); + + ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel; + } + else + { + ERR("Detaching Threads are not associated!\n"); + } } /* Note that key state, which can be ascertained by calls to the GetKeyState or GetKeyboardState function, is reset after a call to AttachThreadInput. diff --git a/reactos/win32ss/user/ntuser/input.h b/reactos/win32ss/user/ntuser/input.h index 985d2c96a30..c34eb4a9ff0 100644 --- a/reactos/win32ss/user/ntuser/input.h +++ b/reactos/win32ss/user/ntuser/input.h @@ -63,7 +63,7 @@ INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID); BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt); DWORD NTAPI CreateSystemThreads(UINT Type); NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL); -PTHREADINFO FASTCALL IsThreadAttach(PTHREADINFO); +BOOL FASTCALL IsRemoveAttachThread(PTHREADINFO); VOID FASTCALL DoTheScreenSaver(VOID); #define ThreadHasInputAccess(W32Thread) (TRUE) diff --git a/reactos/win32ss/user/ntuser/keyboard.c b/reactos/win32ss/user/ntuser/keyboard.c index 7af7cc5a84e..2b2cf6260fd 100644 --- a/reactos/win32ss/user/ntuser/keyboard.c +++ b/reactos/win32ss/user/ntuser/keyboard.c @@ -825,6 +825,7 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d TRACE("HotKey Processed\n"); bPostMsg = FALSE; } + wFixedVk = IntFixVk(wSimpleVk, bExt); /* LSHIFT + EXT = RSHIFT */ if (wSimpleVk == VK_SHIFT) /* shift can't be extended */ bExt = FALSE; @@ -892,23 +893,31 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d } else if (pFocusQueue && bPostMsg) { - PWND Wnd = pFocusQueue->spwndFocus; - if (!Wnd) + PWND Wnd = pFocusQueue->spwndFocus; // SysInit..... + + pti = pFocusQueue->ptiKeyboard; + + if (!Wnd && pFocusQueue->spwndActive) // SysInit..... { - // Focus can be null so going with Active. WM_SYSKEYXXX last wine Win test_keyboard_input. + // Going with Active. WM_SYSKEYXXX last wine Win test_keyboard_input. Wnd = pFocusQueue->spwndActive; } + if (Wnd) pti = Wnd->head.pti; - if ( !Wnd || Wnd->state2 & WNDS2_INDESTROY || Wnd->state & WNDS_DESTROYED ) + if ( Msg.message == WM_KEYDOWN || Msg.message == WM_SYSKEYDOWN ) { - ERR("ProcessKeyEvent Active Focus window is dead!\n"); - return FALSE; + if ( (Msg.wParam == VK_SHIFT || + Msg.wParam == VK_CONTROL || + Msg.wParam == VK_MENU ) && + !IS_KEY_DOWN(gafAsyncKeyState, Msg.wParam)) + { + ERR("Set last input\n"); + //ptiLastInput = pti; + } } - - pti = Wnd->head.pti; /* Init message */ - Msg.hwnd = UserHMGetHandle(Wnd); + Msg.hwnd = Wnd ? UserHMGetHandle(Wnd) : NULL; Msg.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */ Msg.lParam = MAKELPARAM(1, wScanCode); Msg.time = dwTime; @@ -934,6 +943,7 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d /* Post a keyboard message */ TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", Msg.message, Msg.wParam, Msg.lParam); + if (!Wnd) {ERR("Window is NULL\n");} MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0); } @@ -956,9 +966,9 @@ UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected) /* Find the target thread whose locale is in effect */ pFocusQueue = IntGetFocusMessageQueue(); - if (pFocusQueue && pFocusQueue->ptiOwner) + if (pFocusQueue && pFocusQueue->ptiKeyboard) { - pKl = pFocusQueue->ptiOwner->KeyboardLayout; + pKl = pFocusQueue->ptiKeyboard->KeyboardLayout; } if (!pKl) @@ -1039,9 +1049,9 @@ UserProcessKeyboardInput( /* Find the target thread whose locale is in effect */ pFocusQueue = IntGetFocusMessageQueue(); - if (pFocusQueue && pFocusQueue->ptiOwner) + if (pFocusQueue && pFocusQueue->ptiKeyboard) { - pKl = pFocusQueue->ptiOwner->KeyboardLayout; + pKl = pFocusQueue->ptiKeyboard->KeyboardLayout; } if (!pKl) diff --git a/reactos/win32ss/user/ntuser/main.c b/reactos/win32ss/user/ntuser/main.c index df84709f02d..c872d020554 100644 --- a/reactos/win32ss/user/ntuser/main.c +++ b/reactos/win32ss/user/ntuser/main.c @@ -154,6 +154,9 @@ Win32kProcessCallback(struct _EPROCESS *Process, ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER; } + // Fixme check if this process is allowed. + ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off. + /* Create pools for GDI object attributes */ ppiCurrent->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG'); ppiCurrent->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG'); @@ -275,14 +278,17 @@ UserCreateThreadInfo(struct _ETHREAD *Thread) RtlZeroMemory(ptiCurrent, sizeof(THREADINFO)); + /* Initialize the THREADINFO */ + PsSetThreadWin32Thread(Thread, ptiCurrent); + IntReferenceThreadInfo(ptiCurrent); + ptiCurrent->pEThread = Thread; + ptiCurrent->ppi = PsGetCurrentProcessWin32Process(); pTeb->Win32ThreadInfo = ptiCurrent; ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo; TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread); - /* Initialize the THREADINFO */ - IntReferenceThreadInfo(ptiCurrent); InitializeListHead(&ptiCurrent->WindowListHead); InitializeListHead(&ptiCurrent->W32CallbackListHead); InitializeListHead(&ptiCurrent->PostedMessagesListHead); @@ -294,8 +300,6 @@ UserCreateThreadInfo(struct _ETHREAD *Thread) { InitializeListHead(&ptiCurrent->aphkStart[i]); } - ptiCurrent->pEThread = Thread; - ptiCurrent->ppi = PsGetCurrentProcessWin32Process(); ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList; ptiCurrent->ppi->ptiList = ptiCurrent; ptiCurrent->ppi->cThreads++; @@ -307,7 +311,7 @@ UserCreateThreadInfo(struct _ETHREAD *Thread) { goto error; } - Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0, + Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0, ExEventObjectType, KernelMode, (PVOID*)&ptiCurrent->pEventQueueServer, NULL); if (!NT_SUCCESS(Status)) @@ -319,7 +323,7 @@ UserCreateThreadInfo(struct _ETHREAD *Thread) KeQueryTickCount(&LargeTickCount); ptiCurrent->timeLast = LargeTickCount.u.LowPart; - + ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent); if(ptiCurrent->MessageQueue == NULL) { @@ -419,8 +423,14 @@ UserCreateThreadInfo(struct _ETHREAD *Thread) /* mark the thread as fully initialized */ ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED; - ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; + if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) && + (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi )) + { + ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; + } + ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; + ERR_CH(UserThread,"UserCreateW32Thread pti 0x%p\n",ptiCurrent); return STATUS_SUCCESS; error: @@ -483,27 +493,10 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread) ppiCurrent = ptiCurrent->ppi; ASSERT(ppiCurrent); - // ptiTo - if (IsThreadAttach(ptiCurrent)) - { - PTHREADINFO ptiFrom = IsThreadAttach(ptiCurrent); - TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n"); - UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE); - } + IsRemoveAttachThread(ptiCurrent); - // ptiFrom - if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue) - { - PTHREADINFO ptiTo; - ptiTo = ptiCurrent->MessageQueue->ptiOwner; - TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n"); - if (ptiTo) UserAttachThreadInput( ptiCurrent, ptiTo, FALSE); - else - { - // eThread maybe okay but Win32Thread already made NULL! - ERR_CH(UserThread,"Attached Thread ptiFrom did not switch due to ptiTo is NULL!\n"); - } - } + ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE; + ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; /* Decrement thread count and check if its 0 */ ppiCurrent->cThreads--; @@ -553,9 +546,10 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread) */ co_DestroyThreadWindows(Thread); - if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling) + if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling && + ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED) { - //ERR_CH(UserThread,"DestroyProcessClasses\n"); + ERR_CH(UserThread,"DestroyProcessClasses\n"); /* no process windows should exist at this point, or the function will assert! */ DestroyProcessClasses(ppiCurrent); ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED; @@ -592,8 +586,24 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread) if (ptiCurrent->KeyboardLayout) UserDereferenceObject(ptiCurrent->KeyboardLayout); - IntSetThreadDesktop(NULL, TRUE); + if (gptiForeground == ptiCurrent) + { +// IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); +// IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0); + gptiForeground = NULL; + } + + // Fixes CORE-6384 & CORE-7030. +/* if (ptiLastInput == ptiCurrent) + { + if (!ppiCurrent->ptiList) + ptiLastInput = gptiForeground; + else + ptiLastInput = ppiCurrent->ptiList; + ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n"); + } +*/ TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent); /* Free the THREADINFO */ diff --git a/reactos/win32ss/user/ntuser/message.c b/reactos/win32ss/user/ntuser/message.c index d4064ee5390..5b4c27ff1b5 100644 --- a/reactos/win32ss/user/ntuser/message.c +++ b/reactos/win32ss/user/ntuser/message.c @@ -502,13 +502,7 @@ VOID FASTCALL IdlePing(VOID) { PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); - PUSER_MESSAGE_QUEUE ForegroundQueue; - PTHREADINFO pti, ptiForeground = NULL; - - ForegroundQueue = IntGetFocusMessageQueue(); - - if (ForegroundQueue) - ptiForeground = ForegroundQueue->ptiOwner; + PTHREADINFO pti; pti = PsGetCurrentThreadWin32Thread(); @@ -516,7 +510,7 @@ IdlePing(VOID) { pti->pClientInfo->cSpins = 0; // Reset spins. - if ( pti->pDeskInfo && pti == ptiForeground ) + if ( pti->pDeskInfo && pti == gptiForeground ) { if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) || pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ) @@ -602,13 +596,14 @@ static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPAR { LRESULT lRes; USER_REFERENCE_ENTRY Ref; +// PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); if (!pWnd || pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND return 0; - TRACE("Internal Event Msg %u hWnd %p\n", msg, pWnd->head.h); + TRACE("Internal Event Msg %p hWnd 0x%x\n",msg,pWnd->head.h); switch(msg) { @@ -632,7 +627,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,TRUE); + lRes = (LRESULT)co_IntSetActiveWindow(Window,(BOOL)lparam,TRUE,TRUE); if (wparam) UserDerefObjectCo(Window); return lRes; } @@ -751,6 +746,14 @@ IntDispatchMessage(PMSG pMsg) /* * Internal version of PeekMessage() doing all the work + * + * MSDN: + * Sent messages + * Posted messages + * Input (hardware) messages and system internal events + * Sent messages (again) + * WM_PAINT messages + * WM_TIMER messages */ BOOL FASTCALL co_IntPeekMessage( PMSG Msg, @@ -770,7 +773,7 @@ co_IntPeekMessage( PMSG Msg, RemoveMessages = RemoveMsg & PM_REMOVE; ProcessMask = HIWORD(RemoveMsg); - + /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns all available messages (that is, no range filtering is performed)". */ if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT); @@ -1083,6 +1086,19 @@ UserPostThreadMessage( PTHREADINFO pti, return TRUE; } +PTHREADINFO FASTCALL +IntSendTo(PWND Window, PTHREADINFO ptiCur, UINT Msg) +{ + if ( ptiCur ) + { + if ( Window->head.pti->MessageQueue == ptiCur->MessageQueue ) + { + return NULL; + } + } + return Window->head.pti; +} + BOOL FASTCALL UserPostMessage( HWND Wnd, UINT Msg, @@ -1192,11 +1208,11 @@ UserPostMessage( HWND Wnd, if (WM_QUIT == Msg) { - MsqPostQuitMessage(Window->head.pti, wParam); + MsqPostQuitMessage(pti, wParam); } else { - MsqPostMessage(Window->head.pti, &Message, FALSE, QS_POSTMESSAGE, 0); + MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0); } } return TRUE; @@ -1230,7 +1246,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, PMSGMEMORY MsgMemoryEntry; INT lParamBufferSize; LPARAM lParamPacked; - PTHREADINFO Win32Thread; + PTHREADINFO Win32Thread, ptiSendTo = NULL; ULONG_PTR Hi, Lo, Result = 0; DECLARE_RETURN(LRESULT); USER_REFERENCE_ENTRY Ref; @@ -1246,8 +1262,9 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, Win32Thread = PsGetCurrentThreadWin32Thread(); - if ( Win32Thread && - Window->head.pti == Win32Thread) + ptiSendTo = IntSendTo(Window, Win32Thread, Msg); + + if ( !ptiSendTo ) { if (Win32Thread->TIF_flags & TIF_INCLEANUP) { @@ -1333,7 +1350,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, RETURN( TRUE); } - if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->head.pti)) + if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(ptiSendTo/*Window->head.pti*/)) { // FIXME: Set window hung and add to a list. /* FIXME: Set a LastError? */ @@ -1349,7 +1366,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, do { - Status = co_MsqSendMessage( Window->head.pti, + Status = co_MsqSendMessage( ptiSendTo, //Window->head.pti, hWnd, Msg, wParam, @@ -1361,7 +1378,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, } while ((STATUS_TIMEOUT == Status) && (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) && - !MsqIsHung(Window->head.pti)); // FIXME: Set window hung and add to a list. + !MsqIsHung(ptiSendTo/*Window->head.pti*/)); // FIXME: Set window hung and add to a list. if (STATUS_TIMEOUT == Status) { @@ -1491,7 +1508,7 @@ co_IntSendMessageWithCallBack( HWND hWnd, PMSGMEMORY MsgMemoryEntry; INT lParamBufferSize; LPARAM lParamPacked; - PTHREADINFO Win32Thread; + PTHREADINFO Win32Thread, ptiSendTo = NULL; DECLARE_RETURN(LRESULT); USER_REFERENCE_ENTRY Ref; PUSER_SENT_MESSAGE Message; @@ -1519,9 +1536,11 @@ co_IntSendMessageWithCallBack( HWND hWnd, { RETURN(FALSE); } + + ptiSendTo = IntSendTo(Window, Win32Thread, Msg); if (Msg & 0x80000000 && - Window->head.pti == Win32Thread) + !ptiSendTo) { if (Win32Thread->TIF_flags & TIF_INCLEANUP) RETURN( FALSE); @@ -1542,14 +1561,14 @@ co_IntSendMessageWithCallBack( HWND hWnd, lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam); } - if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, Window->head.pti != Win32Thread))) + if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, !!ptiSendTo))) { ERR("Failed to pack message parameters\n"); RETURN( FALSE); } /* If it can be sent now, then send it. */ - if (Window->head.pti == Win32Thread) + if ( !ptiSendTo ) { if (Win32Thread->TIF_flags & TIF_INCLEANUP) { @@ -1599,7 +1618,7 @@ co_IntSendMessageWithCallBack( HWND hWnd, } } - if (Window->head.pti == Win32Thread) + if ( !ptiSendTo) { if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE))) { @@ -1622,7 +1641,7 @@ co_IntSendMessageWithCallBack( HWND hWnd, Message->Result = 0; Message->lResult = 0; Message->QS_Flags = 0; - Message->ptiReceiver = Window->head.pti; + Message->ptiReceiver = ptiSendTo; //Window->head.pti; Message->ptiSender = NULL; // mjmartin, you are right! This is null. Message->ptiCallBackSender = Win32Thread; Message->DispatchingListEntry.Flink = NULL; @@ -1633,10 +1652,10 @@ co_IntSendMessageWithCallBack( HWND hWnd, Message->QS_Flags = QS_SENDMESSAGE; if (Msg & 0x80000000) // Higher priority event message! - InsertHeadList(&Window->head.pti->SentMessagesListHead, &Message->ListEntry); + InsertHeadList(&ptiSendTo->SentMessagesListHead/*&Window->head.pti->SentMessagesListHead*/, &Message->ListEntry); else - InsertTailList(&Window->head.pti->SentMessagesListHead, &Message->ListEntry); - MsqWakeQueue(Window->head.pti, QS_SENDMESSAGE, TRUE); + InsertTailList(&ptiSendTo->SentMessagesListHead/*&Window->head.pti->SentMessagesListHead*/, &Message->ListEntry); + MsqWakeQueue(ptiSendTo/*Window->head.pti*/, QS_SENDMESSAGE, TRUE); RETURN(TRUE); @@ -1674,7 +1693,7 @@ co_IntPostOrSendMessage( HWND hWnd, pti = PsGetCurrentThreadWin32Thread(); - if ( Window->head.pti->MessageQueue != pti->MessageQueue && + if ( IntSendTo(Window, pti, Msg) && FindMsgMemory(Msg) == 0 ) { Result = UserPostMessage(hWnd, Msg, wParam, lParam); diff --git a/reactos/win32ss/user/ntuser/misc.c b/reactos/win32ss/user/ntuser/misc.c index 935104f7cfd..52f0abe377c 100644 --- a/reactos/win32ss/user/ntuser/misc.c +++ b/reactos/win32ss/user/ntuser/misc.c @@ -662,8 +662,11 @@ void UserDbgAssertThreadInfo(BOOL showCaller) ASSERT(pti->pDeskInfo == pti->rpdesk->pDeskInfo); /*too bad we still get this assertion*/ + + // Why? Not all flags are passed to the user and doing so could crash the system........ + /* ASSERT(pci->dwTIFlags == pti->TIF_flags); */ - if(pci->dwTIFlags != pti->TIF_flags) +/* if(pci->dwTIFlags != pti->TIF_flags) { ERR("pci->dwTIFlags(0x%x) doesn't match pti->TIF_flags(0x%x)\n", pci->dwTIFlags, pti->TIF_flags); if(showCaller) @@ -673,6 +676,7 @@ void UserDbgAssertThreadInfo(BOOL showCaller) } pci->dwTIFlags = pti->TIF_flags; } +*/ } void diff --git a/reactos/win32ss/user/ntuser/msgqueue.c b/reactos/win32ss/user/ntuser/msgqueue.c index 5be8095794b..c4e677ddf69 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.c +++ b/reactos/win32ss/user/ntuser/msgqueue.c @@ -404,7 +404,6 @@ MsqWakeQueue(PTHREADINFO pti, DWORD MessageBits, BOOL KeyEvent) { ERR("This Message Queue is in Destroy!\n"); } - pti->pcti->fsWakeBits |= MessageBits; pti->pcti->fsChangeBits |= MessageBits; @@ -475,6 +474,10 @@ ClearMsgBitsMask(PTHREADINFO pti, UINT MessageBits) { if (--pti->nCntsQBits[QSRosHotKey] == 0) ClrMask |= QS_HOTKEY; } + if (MessageBits & QS_EVENT) + { + if (--pti->nCntsQBits[QSRosEvent] == 0) ClrMask |= QS_EVENT; + } pti->pcti->fsWakeBits &= ~ClrMask; pti->pcti->fsChangeBits &= ~ClrMask; @@ -506,6 +509,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook { LARGE_INTEGER LargeTickCount; MSLLHOOKSTRUCT MouseHookData; +// PDESKTOP pDesk; PWND pwnd, pwndDesktop; HDC hdcScreen; PTHREADINFO pti; @@ -549,6 +553,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook /* Get the desktop window */ pwndDesktop = UserGetDesktopWindow(); if (!pwndDesktop) return; +// pDesk = pwndDesktop->head.rpdesk; /* Check if the mouse is captured */ Msg->hwnd = IntGetCaptureWindow(); @@ -626,6 +631,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook } else { + //if (!IntGetCaptureWindow()) ptiLastInput = pti; TRACE("Posting mouse message to hwnd=%p!\n", UserHMGetHandle(pwnd)); MsqPostMessage(pti, Msg, TRUE, QS_MOUSEBUTTON, 0); } @@ -661,7 +667,7 @@ MsqDestroyMessage(PUSER_MESSAGE Message) } BOOLEAN FASTCALL -co_MsqDispatchOneSentMessage(_In_ PTHREADINFO pti) +co_MsqDispatchOneSentMessage(PTHREADINFO pti) { PUSER_SENT_MESSAGE SaveMsg, Message; PLIST_ENTRY Entry; @@ -911,12 +917,6 @@ co_MsqSendMessageAsync(PTHREADINFO ptiReceiver, ptiSender = PsGetCurrentThreadWin32Thread(); - IntReferenceMessageQueue(ptiReceiver->MessageQueue); - /* Take reference on this MessageQueue if its a callback. It will be released - when message is processed or removed from target hwnd MessageQueue */ - if (CompletionCallback) - IntReferenceMessageQueue(ptiSender->MessageQueue); - Message->Msg.hwnd = hwnd; Message->Msg.message = Msg; Message->Msg.wParam = wParam; @@ -1180,6 +1180,12 @@ MsqPostMessage(PTHREADINFO pti, PUSER_MESSAGE Message; PUSER_MESSAGE_QUEUE MessageQueue; + if ( pti->TIF_flags & TIF_INCLEANUP || pti->MessageQueue->QF_flags & QF_INDESTROY ) + { + ERR("Post Msg; Thread or Q is Dead!\n"); + return; + } + if(!(Message = MsqCreateMessage(Msg))) { return; @@ -1189,6 +1195,7 @@ MsqPostMessage(PTHREADINFO pti, if (dwQEvent) { + ERR("Post Msg; System Qeued Event Message!\n"); InsertHeadList(&pti->PostedMessagesListHead, &Message->ListEntry); } @@ -1206,7 +1213,7 @@ MsqPostMessage(PTHREADINFO pti, if (Msg->message == WM_HOTKEY) MessageBits |= QS_HOTKEY; // Justin Case, just set it. Message->dwQEvent = dwQEvent; Message->QS_Flags = MessageBits; - //Message->pti = pti; Fixed in ATI changes. See CORE-6551 + Message->pti = pti; MsqWakeQueue(pti, MessageBits, (MessageBits & QS_TIMER ? FALSE : TRUE)); } @@ -1254,7 +1261,7 @@ FASTCALL IntTrackMouseMove(PWND pwndTrack, PDESKTOP pDesk, PMSG msg, USHORT hittest) { // PWND pwndTrack = IntChildrenWindowFromPoint(pwndMsg, msg->pt.x, msg->pt.y); - hittest = (USHORT)GetNCHitEx(pwndTrack, msg->pt); /// @todo WTF is this??? +// hittest = (USHORT)GetNCHitEx(pwndTrack, msg->pt); /// @todo WTF is this??? if ( pDesk->spwndTrack != pwndTrack || // Change with tracking window or msg->message != WM_MOUSEMOVE || // Mouse click changes or @@ -1491,7 +1498,7 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT hook.dwExtraInfo = 0 /* extra_info */ ; co_HOOK_CallHooks( WH_CBT, HCBT_CLICKSKIPPED, message, (LPARAM)&hook ); - ERR("WH_MOUSE dorpped mouse message!\n"); + ERR("WH_MOUSE dropped mouse message!\n"); /* Remove and skip message */ *RemoveMessages = TRUE; @@ -1805,7 +1812,7 @@ MsqPeekMessage(IN PTHREADINFO pti, ListHead = &pti->PostedMessagesListHead; if (IsListEmpty(CurrentEntry)) return FALSE; - + CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); do @@ -1880,9 +1887,8 @@ HungAppSysTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) BOOLEAN FASTCALL MsqInitializeMessageQueue(PTHREADINFO pti, PUSER_MESSAGE_QUEUE MessageQueue) { - MessageQueue->ptiOwner = pti; MessageQueue->CaretInfo = (PTHRDCARETINFO)(MessageQueue + 1); - InitializeListHead(&MessageQueue->HardwareMessagesListHead); + InitializeListHead(&MessageQueue->HardwareMessagesListHead); // Keep here! MessageQueue->spwndFocus = NULL; MessageQueue->iCursorLevel = 0; MessageQueue->CursorObject = NULL; @@ -1900,7 +1906,7 @@ MsqCleanupThreadMsgs(PTHREADINFO pti) PLIST_ENTRY CurrentEntry; PUSER_MESSAGE CurrentMessage; PUSER_SENT_MESSAGE CurrentSentMessage; - + /* cleanup posted messages */ while (!IsListEmpty(&pti->PostedMessagesListHead)) { @@ -1936,7 +1942,7 @@ MsqCleanupThreadMsgs(PTHREADINFO pti) if (CurrentSentMessage->Msg.lParam) ExFreePool((PVOID)CurrentSentMessage->Msg.lParam); } - + /* free the message */ ExFreePool(CurrentSentMessage); } @@ -1999,16 +2005,16 @@ MsqCleanupThreadMsgs(PTHREADINFO pti) pti->nCntsQBits[QSRosPostMessage] = 0; pti->nCntsQBits[QSRosSendMessage] = 0; pti->nCntsQBits[QSRosHotKey] = 0; - + pti->nCntsQBits[QSRosEvent] = 0; } - + VOID FASTCALL MsqCleanupMessageQueue(PTHREADINFO pti) { PUSER_MESSAGE_QUEUE MessageQueue; MessageQueue = pti->MessageQueue; - MessageQueue->cThreads--; + MessageQueue->cThreads--; if (MessageQueue->cThreads) { @@ -2033,6 +2039,7 @@ MsqCleanupMessageQueue(PTHREADINFO pti) IntGetSysCursorInfo()->CurrentCursorObject = NULL; } + ERR("DereferenceObject pCursor\n"); UserDereferenceObject(pCursor); } diff --git a/reactos/win32ss/user/ntuser/msgqueue.h b/reactos/win32ss/user/ntuser/msgqueue.h index 4b2a8ceaa6b..365f76536e5 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.h +++ b/reactos/win32ss/user/ntuser/msgqueue.h @@ -42,7 +42,6 @@ typedef struct _USER_MESSAGE_QUEUE /* Reference counter, only access this variable with interlocked functions! */ LONG References; - PTHREADINFO ptiOwner; // temp.. /* Desktop that the message queue is attached to */ struct _DESKTOP *Desktop; diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index 6189050c11c..363e175a28f 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -548,6 +548,13 @@ UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner) #endif } + +HANDLE FASTCALL ValidateHandleNoErr(HANDLE handle, HANDLE_TYPE type) +{ + if (handle) return (PWND)UserGetObjectNoErr(gHandleTable, handle, type); + return NULL; +} + /* * NtUserValidateHandleSecure * diff --git a/reactos/win32ss/user/ntuser/object.h b/reactos/win32ss/user/ntuser/object.h index 51355746184..22267d6fa12 100644 --- a/reactos/win32ss/user/ntuser/object.h +++ b/reactos/win32ss/user/ntuser/object.h @@ -18,6 +18,7 @@ BOOL FASTCALL UserCreateHandleTable(VOID); BOOL FASTCALL UserObjectInDestroy(HANDLE); void DbgUserDumpHandleTable(); VOID FASTCALL UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner); +HANDLE FASTCALL ValidateHandleNoErr(HANDLE handle, HANDLE_TYPE type); static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry) diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 52255f3e438..25a1b0a7633 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -123,7 +123,12 @@ IntSetStyle( PWND pwnd, ULONG set_bits, ULONG clear_bits ) styleNew = (pwnd->style | set_bits) & ~clear_bits; if (styleNew == styleOld) return styleNew; pwnd->style = styleNew; - if ((styleOld ^ styleNew) & WS_VISIBLE) DceResetActiveDCEs( pwnd ); + if ((styleOld ^ styleNew) & WS_VISIBLE) // State Change. + { + if (styleOld & WS_VISIBLE) pwnd->head.pti->cVisWindows--; + if (styleNew & WS_VISIBLE) pwnd->head.pti->cVisWindows++; + DceResetActiveDCEs( pwnd ); + } return styleOld; } @@ -159,21 +164,16 @@ IntIsWindow(HWND hWnd) BOOL FASTCALL IntIsWindowVisible(PWND Wnd) { - BOOL Ret = TRUE; - do + PWND Temp = Wnd; + for (;;) { - if (!(Wnd->style & WS_VISIBLE)) - { - Ret = FALSE; - break; - } - if (Wnd->spwndParent != NULL) - Wnd = Wnd->spwndParent; - else - break; + if (!Temp) return TRUE; + if (!(Temp->style & WS_VISIBLE)) break; + if (Temp->style & WS_MINIMIZE && Temp != Wnd) break; + if (Temp->fnid == FNID_DESKTOP) return TRUE; + Temp = Temp->spwndParent; } - while (Wnd != NULL); - return Ret; + return FALSE; } PWND FASTCALL @@ -436,6 +436,7 @@ static LRESULT co_UserFreeWindow(PWND Window, } Window->state2 |= WNDS2_INDESTROY; Window->style &= ~WS_VISIBLE; + Window->head.pti->cVisWindows--; IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0); @@ -497,9 +498,6 @@ static LRESULT co_UserFreeWindow(PWND Window, /* flush the message queue */ MsqRemoveWindowMessagesFromQueue(Window); - NT_ASSERT(Window->head.pti); - IntDereferenceMessageQueue(Window->head.pti->MessageQueue); - /* from now on no messages can be sent to this window anymore */ Window->state |= WNDS_DESTROYED; Window->fnid |= FNID_FREED; @@ -578,6 +576,7 @@ static LRESULT co_UserFreeWindow(PWND Window, GreDeleteObject(Window->hrgnClip); Window->hrgnClip = NULL; } + Window->head.pti->cWindows--; // ASSERT(Window != NULL); UserFreeWindowInfo(Window->head.pti, Window); @@ -1098,8 +1097,8 @@ IntProcessOwnerSwap(PWND Wnd, PWND WndNewOwner, PWND WndOldOwner) Wnd->head.pti == WndNewOwner->head.pti || WndOldOwner->head.pti != WndNewOwner->head.pti ) { - ERR("ProcessOwnerSwap Old out.\n"); - //UserAttachThreadInput(Wnd->head.pti, WndOldOwner->head.pti, FALSE); + //ERR("ProcessOwnerSwap Old out.\n"); + UserAttachThreadInput(Wnd->head.pti, WndOldOwner->head.pti, FALSE); } } } @@ -1110,8 +1109,8 @@ IntProcessOwnerSwap(PWND Wnd, PWND WndNewOwner, PWND WndOldOwner) if (!WndOldOwner || WndOldOwner->head.pti != WndNewOwner->head.pti ) { - ERR("ProcessOwnerSwap New in.\n"); - //UserAttachThreadInput(Wnd->head.pti, WndNewOwner->head.pti, TRUE); + //ERR("ProcessOwnerSwap New in.\n"); + UserAttachThreadInput(Wnd->head.pti, WndNewOwner->head.pti, TRUE); } } } @@ -1140,6 +1139,8 @@ IntSetOwner(HWND hWnd, HWND hWndNewOwner) goto Error; } + /* if parent belongs to a different thread and the window isn't */ + /* top-level, attach the two threads */ IntProcessOwnerSwap(Wnd, WndNewOwner, WndOldOwner); if (IntValidateOwnerDepth(Wnd, WndNewOwner)) @@ -1186,6 +1187,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) /* Some applications try to set a child as a parent */ if (IntIsChildWindow(Wnd, WndNewParent)) { + TRACE("IntSetParent try to set a child as a parent.\n"); EngSetLastError( ERROR_INVALID_PARAMETER ); return NULL; } @@ -1196,6 +1198,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) { if (Wnd == pWndExam) { + TRACE("IntSetParent Failed Test for set parent to parent!\n"); EngSetLastError(ERROR_INVALID_PARAMETER); return NULL; } @@ -1210,7 +1213,10 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) /* Window must belong to current process */ if (Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process()) + { + ERR("IntSetParent Window must belong to current process!\n"); return NULL; + } WndOldParent = Wnd->spwndParent; @@ -1249,22 +1255,31 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) } + if ( WndNewParent == co_GetDesktopWindow(Wnd) && + !(Wnd->style & WS_CLIPSIBLINGS) ) + { + Wnd->style |= WS_CLIPSIBLINGS; + DceResetActiveDCEs(Wnd); + } + + /* if parent belongs to a different thread and the window isn't */ + /* top-level, attach the two threads */ if ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) { if ( Wnd->spwndParent != co_GetDesktopWindow(Wnd)) { if (Wnd->head.pti != WndOldParent->head.pti) { - ERR("SetParent Old out.\n"); - //UserAttachThreadInput(Wnd->head.pti, WndOldParent->head.pti, FALSE); + //ERR("SetParent Old out.\n"); + UserAttachThreadInput(Wnd->head.pti, WndOldParent->head.pti, FALSE); } } if ( WndNewParent != co_GetDesktopWindow(Wnd)) { if (Wnd->head.pti != WndNewParent->head.pti) { - ERR("SetParent New in.\n"); - //UserAttachThreadInput(Wnd->head.pti, WndNewParent->head.pti, TRUE); + //ERR("SetParent New in.\n"); + UserAttachThreadInput(Wnd->head.pti, WndNewParent->head.pti, TRUE); } } } @@ -1278,10 +1293,11 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) * in the z-order and send the expected WM_WINDOWPOSCHANGING and * WM_WINDOWPOSCHANGED notification messages. */ + //ERR("IntSetParent SetWindowPos 1\n"); co_WinPosSetWindowPos( Wnd, (0 == (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOP : HWND_TOPMOST), pt.x, pt.y, 0, 0, swFlags); - + //ERR("IntSetParent SetWindowPos 2\n"); if (WasVisible) co_WinPosShowWindow(Wnd, SW_SHOWNORMAL); return WndOldParent; @@ -1302,6 +1318,7 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent) if (hWndChild == IntGetDesktopWindow()) { + ERR("UserSetParent Access Denied!\n"); EngSetLastError(ERROR_ACCESS_DENIED); return( NULL); } @@ -1310,6 +1327,7 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent) { if (!(WndParent = UserGetWindowObject(hWndNewParent))) { + ERR("UserSetParent Bad New Parent!\n"); return( NULL); } } @@ -1323,6 +1341,7 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent) if (!(Wnd = UserGetWindowObject(hWndChild))) { + ERR("UserSetParent Bad Child!\n"); return( NULL); } @@ -1762,13 +1781,14 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, pWnd->InternalPos.MaxPos.x = pWnd->InternalPos.MaxPos.y = -1; pWnd->InternalPos.IconPos.x = pWnd->InternalPos.IconPos.y = -1; - IntReferenceMessageQueue(pWnd->head.pti->MessageQueue); if (pWnd->spwndParent != NULL && Cs->hwndParent != 0) { pWnd->HideFocus = pWnd->spwndParent->HideFocus; pWnd->HideAccel = pWnd->spwndParent->HideAccel; } + pWnd->head.pti->cWindows++; + if (Class->hIcon && !Class->hIconSm) { Class->hIconSmIntern = co_IntCopyImage( Class->hIcon, IMAGE_ICON, @@ -1962,8 +1982,8 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, Class->atomClassName != gpsi->atomSysClass[ICLS_IME] && pti != pWnd->spwndOwner->head.pti) { - ERR("CreateWindow Owner in.\n"); - //UserAttachThreadInput(pti, pWnd->spwndOwner->head.pti, TRUE); + //ERR("CreateWindow Owner in.\n"); + UserAttachThreadInput(pti, pWnd->spwndOwner->head.pti, TRUE); } } @@ -2203,6 +2223,15 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, Cs->lpszName = (LPCWSTR) WindowName; Cs->lpszClass = (LPCWSTR) ClassName; + if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) + { + if (ParentWindow != co_GetDesktopWindow(Window)) + { + Cs->x += ParentWindow->rcClient.left; + Cs->y += ParentWindow->rcClient.top; + } + } + /* Send the WM_GETMINMAXINFO message */ Size.cx = Cs->cx; Size.cy = Cs->cy; @@ -2220,6 +2249,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, Window->rcWindow.top = Cs->y; Window->rcWindow.right = Cs->x + Size.cx; Window->rcWindow.bottom = Cs->y + Size.cy; +/* if (0 != (Window->style & WS_CHILD) && ParentWindow) { // ERR("co_UserCreateWindowEx(): Offset rcWindow\n"); @@ -2227,6 +2257,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, ParentWindow->rcClient.left, ParentWindow->rcClient.top); } +*/ Window->rcClient = Window->rcWindow; /* Link the window */ @@ -2239,8 +2270,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, IntLinkHwnd(Window, hwndInsertAfter); } - // Remove flags that are retro. - if (!(Window->state2 & WNDS2_WIN31COMPAT)) // FIXME: support version flags. + if (!(Window->state2 & WNDS2_WIN31COMPAT)) { if (Class->style & CS_PARENTDC && !(ParentWindow->style & WS_CLIPCHILDREN)) Window->style &= ~(WS_CLIPSIBLINGS | WS_CLIPCHILDREN); @@ -2252,8 +2282,8 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, { if (pti != Window->spwndParent->head.pti) { - ERR("CreateWindow Parent in.\n"); - //UserAttachThreadInput(pti, Window->spwndParent->head.pti, TRUE); + //ERR("CreateWindow Parent in.\n"); + UserAttachThreadInput(pti, Window->spwndParent->head.pti, TRUE); } } } @@ -2267,14 +2297,19 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, } /* Send the WM_NCCALCSIZE message */ + { + // RECT rc; MaxPos.x = Window->rcWindow.left; MaxPos.y = Window->rcWindow.top; Result = co_WinPosGetNonClientSize(Window, &Window->rcWindow, &Window->rcClient); + //rc = Window->rcWindow; + //Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM)&rc); + //Window->rcClient = rc; RECTL_vOffsetRect(&Window->rcWindow, MaxPos.x - Window->rcWindow.left, MaxPos.y - Window->rcWindow.top); - + } /* Send the WM_CREATE message. */ Result = co_IntSendMessage(UserHMGetHandle(Window), WM_CREATE, 0, (LPARAM) Cs); @@ -2593,8 +2628,8 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) { if (Window->spwndOwner) { - ERR("DestroyWindow Owner out.\n"); - //UserAttachThreadInput(Window->head.pti, Window->spwndOwner->head.pti, FALSE); + //ERR("DestroyWindow Owner out.\n"); + UserAttachThreadInput(Window->head.pti, Window->spwndOwner->head.pti, FALSE); } } } @@ -2632,8 +2667,8 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) { if (!IntIsTopLevelWindow(Window)) { - ERR("DestroyWindow Parent out.\n"); - //UserAttachThreadInput(Window->head.pti, Window->spwndParent->head.pti, FALSE); + //ERR("DestroyWindow Parent out.\n"); + UserAttachThreadInput(Window->head.pti, Window->spwndParent->head.pti, FALSE); } } } @@ -3377,9 +3412,12 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView) if (ti->pDeskInfo) { ti->pDeskInfo->hShellWindow = hwndShell; + ti->pDeskInfo->spwndShell = WndShell; ti->pDeskInfo->ppiShellProcess = ti->ppi; } + UserRegisterHotKey(WndShell, SC_TASKLIST, MOD_CONTROL, VK_ESCAPE); + UserDerefObjectCo(WndShell); ObDereferenceObject(WinStaObject); @@ -3579,6 +3617,12 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi) else Window->ExStyle &= ~WS_EX_WINDOWEDGE; + if ((Style.styleOld ^ Style.styleNew) & WS_VISIBLE) + { + if (Style.styleOld & WS_VISIBLE) Window->head.pti->cVisWindows--; + if (Style.styleNew & WS_VISIBLE) Window->head.pti->cVisWindows++; + DceResetActiveDCEs( Window ); + } Window->style = (DWORD)Style.styleNew; co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style); break; diff --git a/reactos/win32ss/user/ntuser/winpos.c b/reactos/win32ss/user/ntuser/winpos.c index ccaa0c2a968..bc4cc6598ce 100644 --- a/reactos/win32ss/user/ntuser/winpos.c +++ b/reactos/win32ss/user/ntuser/winpos.c @@ -237,6 +237,7 @@ BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd) if (!(pWndSetActive->ExStyle & WS_EX_TOOLWINDOW) ) { UserRefObjectCo(pWndSetActive, &Ref); + //ERR("ActivateOtherWindowMin Set FG 1\n"); co_IntSetForegroundWindow(pWndSetActive); UserDerefObjectCo(pWndSetActive); //ERR("AOWM 2 Exit Good\n"); @@ -273,6 +274,7 @@ BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd) if ((pWndSetActive = pWndTemp)) { UserRefObjectCo(pWndSetActive, &Ref); + //ERR("ActivateOtherWindowMin Set FG 2\n"); co_IntSetForegroundWindow(pWndSetActive); UserDerefObjectCo(pWndSetActive); //ERR("AOWM 3 Exit Good\n"); @@ -299,7 +301,7 @@ BOOL FASTCALL can_activate_window( PWND Wnd OPTIONAL) if (style & WS_MINIMIZE) return FALSE; if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; return TRUE; - /* FIXME: This window could be disable because the child that closed + /* FIXME: This window could be disable because the child that closed was a popup. */ //return !(style & WS_DISABLED); } @@ -314,7 +316,6 @@ VOID FASTCALL co_WinPosActivateOtherWindow(PWND Wnd) { PWND WndTo = NULL; - HWND Fg, previous; USER_REFERENCE_ENTRY Ref; ASSERT_REFS_CO(Wnd); @@ -345,26 +346,24 @@ done: if (WndTo) UserRefObjectCo(WndTo, &Ref); - Fg = UserGetForegroundWindow(); - if ((!Fg || Wnd->head.h == Fg) && WndTo) // FIXME: Ok if WndTo is NULL?? No, rule #4. + if (!gpqForeground || Wnd == gpqForeground->spwndActive) { - /* FIXME: Wine can pass WndTo = NULL to co_IntSetForegroundWindow. Hmm... */ + /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */ + //ERR("WinPosActivateOtherWindow Set FG 0x%p\n",WndTo); if (co_IntSetForegroundWindow(WndTo)) { - UserDerefObjectCo(WndTo); + if (WndTo) UserDerefObjectCo(WndTo); return; } } - - if (!co_IntSetActiveWindow(WndTo,&previous,FALSE,TRUE,FALSE) || /* Ok for WndTo to be NULL here */ - !previous) + //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo); + if (!co_IntSetActiveWindow(WndTo,FALSE,TRUE,FALSE)) /* Ok for WndTo to be NULL here */ { - co_IntSetActiveWindow(0,NULL,FALSE,TRUE,FALSE); + co_IntSetActiveWindow(0,FALSE,TRUE,FALSE); } if (WndTo) UserDerefObjectCo(WndTo); } - UINT FASTCALL co_WinPosArrangeIconicWindows(PWND parent) @@ -1131,11 +1130,71 @@ FixClientRect(PRECTL ClientRect, PRECTL WindowRect) ClientRect->bottom = WindowRect->bottom; } } +/*********************************************************************** + * get_valid_rects + * + * Compute the valid rects from the old and new client rect and WVR_* flags. + * Helper for WM_NCCALCSIZE handling. + */ +static +VOID FASTCALL +get_valid_rects( RECTL *old_client, RECTL *new_client, UINT flags, RECTL *valid ) +{ + int cx, cy; + + if (flags & WVR_REDRAW) + { + RECTL_vSetEmptyRect( &valid[0] ); + RECTL_vSetEmptyRect( &valid[1] ); + return; + } + + if (flags & WVR_VALIDRECTS) + { + if (!RECTL_bIntersectRect( &valid[0], &valid[0], new_client ) || + !RECTL_bIntersectRect( &valid[1], &valid[1], old_client )) + { + RECTL_vSetEmptyRect( &valid[0] ); + RECTL_vSetEmptyRect( &valid[1] ); + return; + } + flags = WVR_ALIGNLEFT | WVR_ALIGNTOP; + } + else + { + valid[0] = *new_client; + valid[1] = *old_client; + } + + /* make sure the rectangles have the same size */ + cx = min( valid[0].right - valid[0].left, valid[1].right - valid[1].left ); + cy = min( valid[0].bottom - valid[0].top, valid[1].bottom - valid[1].top ); + + if (flags & WVR_ALIGNBOTTOM) + { + valid[0].top = valid[0].bottom - cy; + valid[1].top = valid[1].bottom - cy; + } + else + { + valid[0].bottom = valid[0].top + cy; + valid[1].bottom = valid[1].top + cy; + } + if (flags & WVR_ALIGNRIGHT) + { + valid[0].left = valid[0].right - cx; + valid[1].left = valid[1].right - cx; + } + else + { + valid[0].right = valid[0].left + cx; + valid[1].right = valid[1].left + cx; + } +} static LONG FASTCALL -co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, - RECT* WindowRect, RECT* ClientRect) +co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, RECTL* WindowRect, RECTL* ClientRect, RECTL* validRects) { PWND Parent; UINT wvrFlags = 0; @@ -1148,9 +1207,10 @@ co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, NCCALCSIZE_PARAMS params; WINDOWPOS winposCopy; - params.rgrc[0] = *WindowRect; - params.rgrc[1] = Window->rcWindow; - params.rgrc[2] = Window->rcClient; + params.rgrc[0] = *WindowRect; // new coordinates of a window that has been moved or resized + params.rgrc[1] = Window->rcWindow; // window before it was moved or resized + params.rgrc[2] = Window->rcClient; // client area before the window was moved or resized + Parent = Window->spwndParent; if (0 != (Window->style & WS_CHILD) && Parent) { @@ -1161,6 +1221,7 @@ co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, RECTL_vOffsetRect(&(params.rgrc[2]), - Parent->rcClient.left, - Parent->rcClient.top); } + params.lppos = &winposCopy; winposCopy = *WinPos; @@ -1170,7 +1231,7 @@ co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom) { - *ClientRect = params.rgrc[0]; + *ClientRect = params.rgrc[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize if ((Window->style & WS_CHILD) && Parent) { RECTL_vOffsetRect(ClientRect, Parent->rcClient.left, @@ -1179,21 +1240,30 @@ co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, FixClientRect(ClientRect, WindowRect); } - /* FIXME: WVR_ALIGNxxx */ - if (ClientRect->left != Window->rcClient.left || ClientRect->top != Window->rcClient.top) { WinPos->flags &= ~SWP_NOCLIENTMOVE; } - if ((ClientRect->right - ClientRect->left != - Window->rcClient.right - Window->rcClient.left) || - (ClientRect->bottom - ClientRect->top != - Window->rcClient.bottom - Window->rcClient.top)) + if (ClientRect->right - ClientRect->left != + Window->rcClient.right - Window->rcClient.left) { WinPos->flags &= ~SWP_NOCLIENTSIZE; } + else + wvrFlags &= ~WVR_HREDRAW; + + if (ClientRect->bottom - ClientRect->top != + Window->rcClient.bottom - Window->rcClient.top) + { + WinPos->flags &= ~SWP_NOCLIENTSIZE; + } + else + wvrFlags &= ~WVR_VREDRAW; + + validRects[0] = params.rgrc[1]; // second rectangle contains the valid destination rectangle + validRects[1] = params.rgrc[2]; // third rectangle contains the valid source rectangle } else { @@ -1205,6 +1275,13 @@ co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, } } + if (WinPos->flags & (SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_HIDEWINDOW)) + { + RECTL_vSetEmptyRect( &validRects[0] ); + RECTL_vSetEmptyRect( &validRects[1] ); + } + else get_valid_rects( &Window->rcClient, ClientRect, wvrFlags, validRects ); + return wvrFlags; } @@ -1215,15 +1292,46 @@ co_WinPosDoWinPosChanging(PWND Window, PRECTL WindowRect, PRECTL ClientRect) { - INT X, Y; - ASSERT_REFS_CO(Window); + /* Send WM_WINDOWPOSCHANGING message */ + if (!(WinPos->flags & SWP_NOSENDCHANGING)) { co_IntSendMessageNoWait(Window->head.h, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos); } + /* Calculate new position and size */ + + *WindowRect = Window->rcWindow; + *ClientRect = (Window->style & WS_MINIMIZE) ? Window->rcWindow : Window->rcClient; + + if (!(WinPos->flags & SWP_NOSIZE)) + { + if (Window->style & WS_MINIMIZE) + { + WindowRect->right = WindowRect->left + UserGetSystemMetrics(SM_CXICON); + WindowRect->bottom = WindowRect->top + UserGetSystemMetrics(SM_CYICON); + } + else + { + WindowRect->right = WindowRect->left + WinPos->cx; + WindowRect->bottom = WindowRect->top + WinPos->cy; + } + } +#if 0 + if (!(WinPos->flags & SWP_NOMOVE)) + { + WindowRect->left = WinPos->x; + WindowRect->top = WinPos->y; + WindowRect->right += WinPos->x - Window->rcWindow.left; + WindowRect->bottom += WinPos->y - Window->rcWindow.top; + RECTL_vOffsetRect(ClientRect, + WinPos->x - Window->rcWindow.left, + WinPos->y - Window->rcWindow.top); + + } + *WindowRect = Window->rcWindow; *ClientRect = Window->rcClient; @@ -1232,22 +1340,26 @@ co_WinPosDoWinPosChanging(PWND Window, WindowRect->right = WindowRect->left + WinPos->cx; WindowRect->bottom = WindowRect->top + WinPos->cy; } - +#endif if (!(WinPos->flags & SWP_NOMOVE)) { + INT X, Y; PWND Parent; X = WinPos->x; Y = WinPos->y; + //ERR("Not SWP_NOMOVE\n"); Parent = Window->spwndParent; - if ((0 != (Window->style & WS_CHILD)) && Parent) + if ((0 != (Window->style & WS_CHILD)) && Parent && + Parent != Window->head.rpdesk->pDeskInfo->spwnd) { + //ERR("Not SWP_NOMOVE Parent client offset\n"); X += Parent->rcClient.left; Y += Parent->rcClient.top; } - WindowRect->left = X; - WindowRect->top = Y; - WindowRect->right += X - Window->rcWindow.left; + WindowRect->left = X; + WindowRect->top = Y; + WindowRect->right += X - Window->rcWindow.left; WindowRect->bottom += Y - Window->rcWindow.top; RECTL_vOffsetRect(ClientRect, X - Window->rcWindow.left, @@ -1256,6 +1368,10 @@ co_WinPosDoWinPosChanging(PWND Window, WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE; + TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n", + WinPos->hwnd, WinPos->hwndInsertAfter, WinPos->x, WinPos->y, + WinPos->cx, WinPos->cy, WinPos->flags ); + return TRUE; } @@ -1396,6 +1512,21 @@ static BOOL FASTCALL WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) { + PWND Parent; + POINT pt; + + /* Finally make sure that all coordinates are valid */ + if (WinPos->x < -32768) WinPos->x = -32768; + else if (WinPos->x > 32767) WinPos->x = 32767; + if (WinPos->y < -32768) WinPos->y = -32768; + else if (WinPos->y > 32767) WinPos->y = 32767; + + WinPos->cx = max(WinPos->cx, 0); + WinPos->cy = max(WinPos->cy, 0); + + Parent = UserGetAncestor( Wnd, GA_PARENT ); + if (!IntIsWindowVisible( Parent )) WinPos->flags |= SWP_NOREDRAW; + if (Wnd->style & WS_VISIBLE) { WinPos->flags &= ~SWP_SHOWWINDOW; @@ -1407,9 +1538,6 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) WinPos->flags |= SWP_NOREDRAW; } - WinPos->cx = max(WinPos->cx, 0); - WinPos->cy = max(WinPos->cy, 0); - /* Check for right size */ if (Wnd->rcWindow.right - Wnd->rcWindow.left == WinPos->cx && Wnd->rcWindow.bottom - Wnd->rcWindow.top == WinPos->cy) @@ -1417,10 +1545,15 @@ WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) WinPos->flags |= SWP_NOSIZE; } + pt.x = WinPos->x; + pt.y = WinPos->y; + IntClientToScreen( Parent, &pt ); +// ERR("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos->x,WinPos->y,pt.x,pt.y); /* Check for right position */ - if (Wnd->rcWindow.left == WinPos->x && - Wnd->rcWindow.top == WinPos->y) + if (Wnd->rcWindow.left == pt.x && + Wnd->rcWindow.top == pt.y) { +// ERR("In right pos\n"); WinPos->flags |= SWP_NOMOVE; } @@ -1526,6 +1659,7 @@ co_WinPosSetWindowPos( WINDOWPOS WinPos; RECTL NewWindowRect; RECTL NewClientRect; + RECTL valid_rects[2]; PROSRGNDATA VisRgn; HRGN VisBefore = NULL; HRGN VisAfter = NULL; @@ -1543,7 +1677,7 @@ co_WinPosSetWindowPos( ASSERT_REFS_CO(Window); - /* FIXME: Get current active window from active queue. */ + /* FIXME: Get current active window from active queue. Why? since r2915. */ bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y); @@ -1555,6 +1689,27 @@ co_WinPosSetWindowPos( WinPos.cy = cy; WinPos.flags = flags; + if ( flags & SWP_ASYNCWINDOWPOS ) + { + LRESULT lRes; + PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP); + if ( ppos ) + { + WinPos.flags &= ~SWP_ASYNCWINDOWPOS; // Clear flag. + *ppos = WinPos; + /* Yes it's a pointer inside Win32k! */ + lRes = co_IntSendMessageNoWait( WinPos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos); + /* We handle this the same way as Event Hooks and Hooks. */ + if ( !lRes ) + { + ExFreePoolWithTag(ppos, USERTAG_SWP); + return FALSE; + } + return TRUE; + } + return FALSE; + } + co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect); // HWND_NOTOPMOST is redirected in WinPosFixupFlags. @@ -1610,9 +1765,11 @@ co_WinPosSetWindowPos( } } - WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect); + WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect, valid_rects); - TRACE("co_WinPosDoNCCALCSize returned %lu\n", WvrFlags); +// ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags, +// valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom, +// valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom); /* Validate link windows. (also take into account shell window in hwndShellWindow) */ if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow()) @@ -1624,6 +1781,7 @@ co_WinPosSetWindowPos( if ((ParentWindow = Window->spwndParent)) // Must have a Parent window! { + //ERR("SetWindowPos has parent window.\n"); if (WinPos.hwndInsertAfter == HWND_TOPMOST) { InsertAfterWindow = NULL; @@ -1682,20 +1840,8 @@ co_WinPosSetWindowPos( OldWindowRect = Window->rcWindow; OldClientRect = Window->rcClient; - - if (OldClientRect.bottom - OldClientRect.top == - NewClientRect.bottom - NewClientRect.top) - { - WvrFlags &= ~WVR_VREDRAW; - } - - if (OldClientRect.right - OldClientRect.left == - NewClientRect.right - NewClientRect.left) - { - WvrFlags &= ~WVR_HREDRAW; - } - - /* FIXME: Actually do something with WVR_VALIDRECTS */ + //ERR("SetWindowPos OldWindowRect: %d %d %d %d\n", OldWindowRect.left,OldWindowRect.top,OldWindowRect.right,OldWindowRect.bottom); + //ERR("SetWindowPos OldClientRect: %d %d %d %d\n", OldClientRect.left,OldClientRect.top,OldClientRect.right,OldClientRect.bottom); if (NewClientRect.left != OldClientRect.left || NewClientRect.top != OldClientRect.top) @@ -1708,6 +1854,9 @@ co_WinPosSetWindowPos( Window->rcWindow = NewWindowRect; Window->rcClient = NewClientRect; + //ERR("SetWindowPos NewWindowRect: %d %d %d %d\n", NewWindowRect.left,NewWindowRect.top,NewWindowRect.right,NewWindowRect.bottom); + //ERR("SetWindowPos NewClientRect: %d %d %d %d\n", NewClientRect.left,NewClientRect.top,NewClientRect.right,NewClientRect.bottom); + /* erase parent when hiding or resizing child */ if (WinPos.flags & SWP_HIDEWINDOW) { @@ -1721,6 +1870,7 @@ co_WinPosSetWindowPos( co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM)Window->head.h, 0); Window->style &= ~WS_VISIBLE; //IntSetStyle( Window, 0, WS_VISIBLE ); + Window->head.pti->cVisWindows--; IntNotifyWinEvent(EVENT_OBJECT_HIDE, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); } else if (WinPos.flags & SWP_SHOWWINDOW) @@ -1729,6 +1879,7 @@ co_WinPosSetWindowPos( co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)Window->head.h, 0); Window->style |= WS_VISIBLE; //IntSetStyle( Window, WS_VISIBLE, 0 ); + Window->head.pti->cVisWindows++; IntNotifyWinEvent(EVENT_OBJECT_SHOW, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); } @@ -1955,7 +2106,10 @@ co_WinPosSetWindowPos( else { //ERR("SetWindowPos Set FG Window!\n"); - co_IntSetForegroundWindow(Window); + if (Window->state & WNDS_BEINGACTIVATED) // Inside SAW? + co_IntSetActiveWindow(Window, FALSE, TRUE, FALSE); // Fixes Api AttachThreadInput tests. + else + co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow. } } @@ -2036,7 +2190,7 @@ co_WinPosSendSizeMove(PWND Wnd) co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, lParam); - if (Wnd->spwndParent == UserGetDesktopWindow()) // Wnd->spwndParent->fnid != FNID_DESKTOP ) + if (Wnd->spwndParent == UserGetDesktopWindow()) // Wnd->spwndParent->fnid == FNID_DESKTOP ) lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top); else lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top); @@ -2056,9 +2210,9 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) LONG style; PWND Parent; PTHREADINFO pti; - // BOOL ShowOwned = FALSE; // HRGN VisibleRgn; - + //ERR("co_WinPosShowWindow START\n"); + BOOL ShowOwned = FALSE; ASSERT_REFS_CO(Wnd); pti = PsGetCurrentThreadWin32Thread(); @@ -2071,6 +2225,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) { if (!WasVisible) { + //ERR("co_WinPosShowWindow Exit Bad\n"); return(FALSE); } Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; @@ -2091,11 +2246,12 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Swp |= SWP_NOACTIVATE; if (!(style & WS_MINIMIZE)) { - //IntShowOwnedPopups(Wnd, FALSE ); + IntShowOwnedPopups(Wnd, FALSE ); // Fix wine Win test_SetFocus todo #1 & #2, if (Cmd == SW_SHOWMINIMIZED) { + //ERR("co_WinPosShowWindow Set focus 1\n"); if ((style & (WS_CHILD | WS_POPUP)) == WS_CHILD) co_UserSetFocus(Wnd->spwndParent); else @@ -2114,7 +2270,10 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Swp |= SWP_FRAMECHANGED; } else //// + { + //ERR("co_WinPosShowWindow Exit Good\n"); return TRUE; + } Swp |= SWP_NOSIZE | SWP_NOMOVE; } break; @@ -2125,7 +2284,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Swp |= SWP_SHOWWINDOW; if (!(style & WS_MAXIMIZE)) { - //ShowOwned = TRUE; + ShowOwned = TRUE; Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos) | SWP_FRAMECHANGED; @@ -2139,7 +2298,10 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Swp |= SWP_FRAMECHANGED; } else //// + { + //ERR("co_WinPosShowWindow Exit Good 1\n"); return TRUE; + } Swp |= SWP_NOSIZE | SWP_NOMOVE; } break; @@ -2177,7 +2339,10 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Swp |= SWP_FRAMECHANGED; } else //// + { + //ERR("co_WinPosShowWindow Exit Good 3\n"); return TRUE; + } Swp |= SWP_NOSIZE | SWP_NOMOVE; } if ( style & WS_CHILD && @@ -2187,6 +2352,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) break; default: + //ERR("co_WinPosShowWindow Exit Good 4\n"); return WasVisible; } @@ -2214,7 +2380,8 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) Wnd->pcls->style & CS_SAVEBITS && ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL))) { - co_IntSetActiveWindow(Wnd,NULL,FALSE,TRUE,FALSE); + ERR("WinPosShowWindow Set active\n"); + UserSetActiveWindow(Wnd); Swp |= SWP_NOACTIVATE | SWP_NOZORDER; } #endif @@ -2242,7 +2409,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) if ( EventMsg ) IntNotifyWinEvent(EventMsg, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); - //if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE ); + if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE ); if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE)) { @@ -2281,6 +2448,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd) // Fix wine Win test_SetFocus todo #3, if (!(style & WS_CHILD)) co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_ACTIVATE, WA_ACTIVE, 0); } + //ERR("co_WinPosShowWindow EXIT\n"); return(WasVisible); }