From d700b033fcc8330ad8d7ca9a057f9a4be5bf5931 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Sun, 20 Oct 2013 05:16:52 +0000 Subject: [PATCH] [Win32k] - The (ATI) patch CORE-6551. Please oh please use this jira core issue for all bug reports and regressions. - Major rewrite to input message queue. It is now attachable between threads. After all the hubbub the only thing we pass are all the SetActive/Foreground/Parent/Window wine msg and win tests. But not the message sequence tests. - Pass all but one foreground API User32 ATI test when the message patch is installed. But w/o it, pass all but 8'ish. - Tested XP osk (On-Screen Keyboard) with CMD, it works but is quirky. Need to look into set to top window issues. - AHK issues work long as ATI is used and when it is not the some AHK tests fail. That was why all the hot key changes had been committed before. Still looking into this. - Please test everything and post to the appropriate jira issue reports. I do not have a lot of time anymore to focus hard on many issues, it will take months to do so with just one. svn path=/trunk/; revision=60718 --- reactos/win32ss/user/ntuser/desktop.c | 5 +- reactos/win32ss/user/ntuser/desktop.h | 3 +- reactos/win32ss/user/ntuser/focus.c | 271 +++++++++++++++++------ reactos/win32ss/user/ntuser/focus.h | 4 +- reactos/win32ss/user/ntuser/input.c | 175 ++++++++------- reactos/win32ss/user/ntuser/input.h | 2 +- reactos/win32ss/user/ntuser/keyboard.c | 36 ++-- reactos/win32ss/user/ntuser/main.c | 70 +++--- reactos/win32ss/user/ntuser/message.c | 77 ++++--- reactos/win32ss/user/ntuser/misc.c | 6 +- reactos/win32ss/user/ntuser/msgqueue.c | 45 ++-- reactos/win32ss/user/ntuser/msgqueue.h | 1 - reactos/win32ss/user/ntuser/object.c | 7 + reactos/win32ss/user/ntuser/object.h | 1 + reactos/win32ss/user/ntuser/window.c | 120 +++++++---- reactos/win32ss/user/ntuser/winpos.c | 288 +++++++++++++++++++------ 16 files changed, 769 insertions(+), 342 deletions(-) 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); }