From 085f7653edcbae8d5f7dce01f1557be5797c9fe8 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Sat, 8 Aug 2015 00:25:04 +0000 Subject: [PATCH] [Win32k] - Move menu related functions. Support more system commands. Add a thread based menu structure. svn path=/trunk/; revision=68621 --- reactos/win32ss/user/ntuser/menu.c | 147 ++++++++++++++++++++++++++- reactos/win32ss/user/ntuser/menu.h | 50 +++++++++ reactos/win32ss/user/ntuser/window.c | 116 --------------------- 3 files changed, 193 insertions(+), 120 deletions(-) diff --git a/reactos/win32ss/user/ntuser/menu.c b/reactos/win32ss/user/ntuser/menu.c index 58dee0bcaca..6ce59d02848 100644 --- a/reactos/win32ss/user/ntuser/menu.c +++ b/reactos/win32ss/user/ntuser/menu.c @@ -620,6 +620,7 @@ IntCloneMenu(PMENU Source) BOOL FASTCALL IntSetMenuFlagRtoL(PMENU Menu) { + ERR("SetMenuFlagRtoL\n"); Menu->fFlags |= MNF_RTOL; return TRUE; } @@ -705,6 +706,12 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi) Menu->TimeToHide = lpmi->TimeToHide; Menu->hWnd = lpmi->Wnd; } + if ( lpmi->fMask & MIM_STYLE) + { + if (lpmi->dwStyle & MNS_AUTODISMISS) FIXME("MNS_AUTODISMISS unimplemented wine\n"); + if (lpmi->dwStyle & MNS_DRAGDROP) FIXME("MNS_DRAGDROP unimplemented wine\n"); + if (lpmi->dwStyle & MNS_MODELESS) FIXME("MNS_MODELESS unimplemented wine\n"); + } return TRUE; } @@ -971,8 +978,16 @@ IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable) MenuItem->fState ^= (res ^ uEnable) & (MF_GRAYED | MF_DISABLED); /* If the close item in the system menu change update the close button */ - if((MenuItem->wID == SC_CLOSE) && (res != uEnable)) + if (res != uEnable) { + switch (MenuItem->wID) // More than just close. + { + case SC_CLOSE: + case SC_MAXIMIZE: + case SC_MINIMIZE: + case SC_MOVE: + case SC_RESTORE: + case SC_SIZE: if (MenuObject->fFlags & MNF_SYSSUBMENU && MenuObject->spwndNotify != 0) { RECTL rc = MenuObject->spwndNotify->rcWindow; @@ -982,6 +997,9 @@ IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable) rc.bottom = 0; co_UserRedrawWindow(MenuObject->spwndNotify, &rc, 0, RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN); } + default: + break; + } } return res; } @@ -1822,6 +1840,77 @@ IntSetSystemMenu(PWND Window, PMENU Menu) return TRUE; } +BOOL FASTCALL +IntSetMenu( + PWND Wnd, + HMENU Menu, + BOOL *Changed) +{ + PMENU OldMenu, NewMenu = NULL; + + if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) + { + ERR("SetMenu: Invalid handle 0x%p!\n",UserHMGetHandle(Wnd)); + EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); + return FALSE; + } + + *Changed = (Wnd->IDMenu != (UINT) Menu); + if (! *Changed) + { + return TRUE; + } + + if (Wnd->IDMenu) + { + OldMenu = IntGetMenuObject((HMENU) Wnd->IDMenu); + ASSERT(NULL == OldMenu || OldMenu->hWnd == Wnd->head.h); + } + else + { + OldMenu = NULL; + } + + if (NULL != Menu) + { + NewMenu = IntGetMenuObject(Menu); + if (NULL == NewMenu) + { + if (NULL != OldMenu) + { + IntReleaseMenuObject(OldMenu); + } + EngSetLastError(ERROR_INVALID_MENU_HANDLE); + return FALSE; + } + if (NULL != NewMenu->hWnd) + { + /* Can't use the same menu for two windows */ + if (NULL != OldMenu) + { + IntReleaseMenuObject(OldMenu); + } + EngSetLastError(ERROR_INVALID_MENU_HANDLE); + return FALSE; + } + + } + + Wnd->IDMenu = (UINT) Menu; + if (NULL != NewMenu) + { + NewMenu->hWnd = Wnd->head.h; + IntReleaseMenuObject(NewMenu); + } + if (NULL != OldMenu) + { + OldMenu->hWnd = NULL; + IntReleaseMenuObject(OldMenu); + } + + return TRUE; +} + /* FUNCTIONS *****************************************************************/ @@ -2142,6 +2231,7 @@ NtUserGetMenuBarInfo( HMENU hMenu; MENUBARINFO kmbi; BOOL Ret; + PPOPUPMENU pPopupMenu; NTSTATUS Status = STATUS_SUCCESS; PMENU Menu = NULL; DECLARE_RETURN(BOOL); @@ -2226,7 +2316,13 @@ NtUserGetMenuBarInfo( kmbi.hwndMenu = NULL; kmbi.fBarFocused = FALSE; kmbi.fFocused = FALSE; - //kmbi.fBarFocused = top_popup_hmenu == hMenu; + + pPopupMenu = ((PMENUWND)pWnd)->ppopupmenu; + if (pPopupMenu) + { + //kmbi.fBarFocused = pPopupMenu->spmenu == Menu; + } + if (idItem) { kmbi.fFocused = Menu->iItem == idItem-1; @@ -2238,8 +2334,8 @@ NtUserGetMenuBarInfo( /* else { kmbi.fFocused = kmbi.fBarFocused; - } -*/ + }*/ + _SEH2_TRY { RtlCopyMemory(pmbi, &kmbi, sizeof(MENUBARINFO)); @@ -2505,6 +2601,49 @@ CLEANUP: } +/* + * @implemented + */ +BOOL APIENTRY +NtUserSetMenu( + HWND hWnd, + HMENU Menu, + BOOL Repaint) +{ + PWND Window; + BOOL Changed; + DECLARE_RETURN(BOOL); + + TRACE("Enter NtUserSetMenu\n"); + UserEnterExclusive(); + + if (!(Window = UserGetWindowObject(hWnd))) + { + RETURN( FALSE); + } + + if (! IntSetMenu(Window, Menu, &Changed)) + { + RETURN( FALSE); + } + + // Not minimized and please repaint!!! + if (!(Window->style & WS_MINIMIZE) && (Repaint || Changed)) + { + USER_REFERENCE_ENTRY Ref; + UserRefObjectCo(Window, &Ref); + co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); + UserDerefObjectCo(Window); + } + + RETURN( TRUE); + +CLEANUP: + TRACE("Leave NtUserSetMenu, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} + /* * @implemented */ diff --git a/reactos/win32ss/user/ntuser/menu.h b/reactos/win32ss/user/ntuser/menu.h index 286e8647cac..ca01889a79b 100644 --- a/reactos/win32ss/user/ntuser/menu.h +++ b/reactos/win32ss/user/ntuser/menu.h @@ -10,6 +10,55 @@ #define MF_END (0x0080) #endif +typedef struct tagMENUSTATE +{ + PPOPUPMENU pGlobalPopupMenu; + struct + { + ULONG fMenuStarted:1; + ULONG fIsSysMenu:1; + ULONG fInsideMenuLoop:1; + ULONG fButtonDown:1; + ULONG fInEndMenu:1; + ULONG fUnderline:1; + ULONG fButtonAlwaysDown:1; + ULONG fDragging:1; + ULONG fModelessMenu:1; + ULONG fInCallHandleMenuMessages:1; + ULONG fDragAndDrop:1; + ULONG fAutoDismiss:1; + ULONG fAboutToAutoDismiss:1; + ULONG fIgnoreButtonUp:1; + ULONG fMouseOffMenu:1; + ULONG fInDoDragDrop:1; + ULONG fActiveNoForeground:1; + ULONG fNotifyByPos:1; + ULONG fSetCapture:1; + ULONG iAniDropDir:5; + }; + POINT ptMouseLast; + INT mnFocus; + INT cmdLast; + PTHREADINFO ptiMenuStateOwner; + DWORD dwLockCount; + struct tagMENUSTATE* pmnsPrev; + POINT ptButtonDown; + ULONG_PTR uButtonDownHitArea; + UINT uButtonDownIndex; + INT vkButtonDown; + ULONG_PTR uDraggingHitArea; + UINT uDraggingIndex; + UINT uDraggingFlags; + HDC hdcWndAni; + DWORD dwAniStartTime; + INT ixAni; + INT iyAni; + INT cxAni; + INT cyAni; + HBITMAP hbmAni; + HDC hdcAni; +} MENUSTATE, *PMENUSTATE; + typedef struct _SETMENUITEMRECT { UINT uItem; @@ -51,3 +100,4 @@ UINT FASTCALL IntGetMenuState( HMENU hMenu, UINT uId, UINT uFlags); BOOL FASTCALL IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse); PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ); BOOL FASTCALL IntMenuItemInfo(PMENU Menu, UINT Item, BOOL ByPosition, PROSMENUITEMINFO UnsafeItemInfo, BOOL SetOrGet, PUNICODE_STRING lpstr); +BOOL FASTCALL IntSetMenu(PWND Wnd,HMENU Menu,BOOL *Changed); diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index ba6b6fc8710..6de81b44b17 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -794,77 +794,6 @@ IntSetWindowProc(PWND pWnd, return Ret; } -static BOOL FASTCALL -IntSetMenu( - PWND Wnd, - HMENU Menu, - BOOL *Changed) -{ - PMENU OldMenu, NewMenu = NULL; - - if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) - { - ERR("SetMenu: Invalid handle 0x%p!\n",UserHMGetHandle(Wnd)); - EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); - return FALSE; - } - - *Changed = (Wnd->IDMenu != (UINT) Menu); - if (! *Changed) - { - return TRUE; - } - - if (Wnd->IDMenu) - { - OldMenu = IntGetMenuObject((HMENU) Wnd->IDMenu); - ASSERT(NULL == OldMenu || OldMenu->hWnd == Wnd->head.h); - } - else - { - OldMenu = NULL; - } - - if (NULL != Menu) - { - NewMenu = IntGetMenuObject(Menu); - if (NULL == NewMenu) - { - if (NULL != OldMenu) - { - IntReleaseMenuObject(OldMenu); - } - EngSetLastError(ERROR_INVALID_MENU_HANDLE); - return FALSE; - } - if (NULL != NewMenu->hWnd) - { - /* Can't use the same menu for two windows */ - if (NULL != OldMenu) - { - IntReleaseMenuObject(OldMenu); - } - EngSetLastError(ERROR_INVALID_MENU_HANDLE); - return FALSE; - } - - } - - Wnd->IDMenu = (UINT) Menu; - if (NULL != NewMenu) - { - NewMenu->hWnd = Wnd->head.h; - IntReleaseMenuObject(NewMenu); - } - if (NULL != OldMenu) - { - OldMenu->hWnd = NULL; - IntReleaseMenuObject(OldMenu); - } - - return TRUE; -} - /* INTERNAL ******************************************************************/ @@ -3939,51 +3868,6 @@ CLEANUP: END_CLEANUP; } -/* - * @implemented - */ -BOOL APIENTRY -NtUserSetMenu( - HWND hWnd, - HMENU Menu, - BOOL Repaint) -{ - PWND Window; - BOOL Changed; - DECLARE_RETURN(BOOL); - - TRACE("Enter NtUserSetMenu\n"); - UserEnterExclusive(); - - if (!(Window = UserGetWindowObject(hWnd))) - { - RETURN( FALSE); - } - - if (! IntSetMenu(Window, Menu, &Changed)) - { - RETURN( FALSE); - } - - if (Changed && Repaint) - { - USER_REFERENCE_ENTRY Ref; - - UserRefObjectCo(Window, &Ref); - co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | - SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); - - UserDerefObjectCo(Window); - } - - RETURN( TRUE); - -CLEANUP: - TRACE("Leave NtUserSetMenu, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - /* * @implemented */