[User32|Win32k]

- Pass all the wine test_capture_1/2/3/4.
- Fix the menu tracking pop up hang issue by looking for deceased windows that pass on while in the start of tracking. This could be a fix for other wine tests.
- ReactOS is not Linux and wine is not enough!

svn path=/trunk/; revision=51265
This commit is contained in:
James Tabor 2011-04-06 12:53:52 +00:00
parent 374e21b4e0
commit 3890323807
6 changed files with 63 additions and 24 deletions

View file

@ -1576,6 +1576,11 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
MenuInfo.FocusedItem = NO_SELECTED_ITEM;
}
/* ReactOS Check */
if (!ValidateHwnd(hwndOwner))
{ // This window maybe already DEAD!!!
return FALSE;
}
/* store the owner for DrawItem */
MenuInfo.WndOwner = hwndOwner;
MenuSetRosMenuInfo(&MenuInfo);
@ -3208,14 +3213,16 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
fEndMenu = !fRemove;
}
if (wFlags & TF_ENDMENU) fEndMenu = TRUE;
/* owner may not be visible when tracking a popup, so use the menu itself */
capture_win = (wFlags & TPM_POPUPMENU) ? MenuInfo.Wnd : mt.OwnerWnd;
(void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, capture_win); // 1
SetCapture(capture_win); // 2
FIXME("MenuTrackMenu 1\n");
while (! fEndMenu)
{
BOOL ErrorExit = FALSE;
PVOID menu = ValidateHandle(mt.CurrentMenu, VALIDATE_TYPE_MENU);
if (!menu) /* sometimes happens if I do a window manager close */
break;
@ -3233,6 +3240,12 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
}
else
{
/* ReactOS Check */
if (!ValidateHwnd(mt.OwnerWnd) || !ValidateHwnd(MenuInfo.Wnd))
{
ErrorExit = TRUE; // Do not wait on dead windows, now test_capture_4 works.
break;
}
if (!enterIdleSent)
{
HWND win = MenuInfo.Flags & MF_POPUP ? MenuInfo.Wnd : NULL;
@ -3241,9 +3254,10 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
}
WaitMessage();
}
//FIXME("MenuTrackMenu loop 1\n");
}
if (ErrorExit) break; // Gracefully dropout.
/* check if EndMenu() tried to cancel us, by posting this message */
if (msg.message == WM_CANCELMODE)
{
@ -3449,7 +3463,6 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
{
PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
DispatchMessageW( &msg );
//FIXME("MenuTrackMenu loop 2\n");
continue;
}
@ -3460,9 +3473,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y,
if (fRemove && !(mt.TrackFlags & TF_SKIPREMOVE) )
PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE );
else mt.TrackFlags &= ~TF_SKIPREMOVE;
//FIXME("MenuTrackMenu loop 3\n");
}
FIXME("MenuTrackMenu 2\n");
(void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL);
SetCapture(NULL); /* release the capture */
@ -3521,12 +3532,11 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT
HideCaret(0);
MenuGetRosMenuInfo(&MenuInfo, hMenu);
/* This makes the menus of applications built with Delphi work.
* It also enables menus to be displayed in more than one window,
* but there are some bugs left that need to be fixed in this case.
*/
if(MenuInfo.Self == hMenu)
if (MenuGetRosMenuInfo(&MenuInfo, hMenu))
{
MenuInfo.Wnd = hWnd;
MenuSetRosMenuInfo(&MenuInfo);
@ -3658,13 +3668,7 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar)
MenuSelectItem( hwnd, &MenuInfo, uItem, TRUE, 0 );
if (wParam & HTSYSMENU)
{
/* prevent sysmenu activation for managed windows on Alt down/up */
// if (GetPropA( hwnd, "__wine_x11_managed" ))
wFlags |= TF_ENDMENU; /* schedule end of menu tracking */
}
else
if (!(wParam & HTSYSMENU) || wChar == ' ')
{
if( uItem == NO_SELECTED_ITEM )
MenuMoveSelection( hwnd, &MenuInfo, ITEM_NEXT );
@ -3693,6 +3697,12 @@ BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
return FALSE;
}
/* ReactOS Check */
if (!ValidateHwnd(Wnd))
{
return FALSE;
}
MenuGetRosMenuInfo(&MenuInfo, Menu);
if (IsWindow(MenuInfo.Wnd))
{

View file

@ -2380,9 +2380,7 @@ GetCapture(VOID)
BOOL WINAPI
ReleaseCapture(VOID)
{
HWND hwndPrev = NtUserSetCapture(NULL);
return(hwndPrev ? TRUE : FALSE);
// return (BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_RELEASECAPTURE);
return (BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_RELEASECAPTURE);
}

View file

@ -7,6 +7,10 @@ HWND FASTCALL
IntGetCaptureWindow(VOID);
HWND FASTCALL
IntGetFocusWindow(VOID);
HWND FASTCALL
co_UserSetCapture(HWND hWnd);
BOOL FASTCALL
IntReleaseCapture(VOID);
/*
* These functions take the window handles from current thread queue.

View file

@ -580,17 +580,44 @@ co_UserSetCapture(HWND hWnd)
ThreadQueue->CaptureWindow = hWnd;
/// These are hacks!
/* also remove other windows if not capturing anymore */
if (hWnd == NULL)
if (hWnd == NULL) // Release mode.
{
MOUSEINPUT mi;
/// These are hacks!
/* also remove other windows if not capturing anymore */
MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL);
MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL);
}
///
/* Somebody may have missed some mouse movements */
mi.dx = 0;
mi.dy = 0;
mi.mouseData = 0;
mi.dwFlags = MOUSEEVENTF_MOVE;
mi.time = 0;
mi.dwExtraInfo = 0;
IntMouseInput(&mi);
}
return hWndPrev;
}
BOOL
FASTCALL
IntReleaseCapture(VOID)
{
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE ThreadQueue;
pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue;
// Can not release inside WM_CAPTURECHANGED!!
if (ThreadQueue->QF_flags & QF_CAPTURELOCKED) return FALSE;
co_UserSetCapture(NULL);
return TRUE;
}
/*
* @implemented
*/

View file

@ -16,7 +16,6 @@
#include <debug.h>
BOOLEAN NTAPI PsGetProcessExitProcessCalled(PEPROCESS Process);
HWND FASTCALL co_UserSetCapture(HWND hWnd);
#define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
@ -861,7 +860,6 @@ co_IntWaitMessage( PWND Window,
{
SetLastNtError(Status);
DPRINT1("Exit co_IntWaitMessage on error!\n");
return FALSE;
}
if (Status == STATUS_USER_APC || Status == STATUS_TIMEOUT)

View file

@ -119,6 +119,9 @@ NtUserCallNoParam(DWORD Routine)
RETURN( (DWORD_PTR)MAKELONG(pti->ptLast.x, pti->ptLast.y));
}
case NOPARAM_ROUTINE_RELEASECAPTURE:
RETURN( (DWORD_PTR)IntReleaseCapture());
default:
DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
EngSetLastError(ERROR_INVALID_PARAMETER);
@ -252,7 +255,6 @@ NtUserCallOneParam(
{
BOOL ret = TRUE;
_SEH2_TRY
{
ProbeForWrite((POINT*)Param,sizeof(POINT),1);