From: Andrew Eikum Subject: [PATCH 3/3] user32: Avoid HMENU internally for showing popups Message-Id: <20140912154621.GH4782@foghorn.codeweavers.com> Date: Fri, 12 Sep 2014 10:46:21 -0500 This is the first in a series of about 7 patches which removes needless pointer->HMENU->pointer conversions. --- dlls/user32/menu.c | 141 ++++++++++++++++++++++++----------------------------- 1 file changed, 63 insertions(+), 78 deletions(-) diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 969c441..6002e24 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -1436,14 +1436,13 @@ static void draw_popup_arrow( HDC hdc, RECT rect, UINT arrow_bitmap_width, * * Draw a single menu item. */ -static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, MENUITEM *lpitem, +static void MENU_DrawMenuItem( HWND hwnd, POPUPMENU *menu, HWND hwndOwner, HDC hdc, MENUITEM *lpitem, UINT height, BOOL menuBar, UINT odaction ) { RECT rect; BOOL flat_menu = FALSE; int bkgnd; UINT arrow_bitmap_width = 0, arrow_bitmap_height = 0; - POPUPMENU *menu = MENU_GetMenu(hmenu); RECT bmprc; debug_print_menuitem("MENU_DrawMenuItem: ", lpitem, ""); @@ -1459,7 +1458,6 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, { if( !IsIconic(hwnd) ) NC_DrawSysButton( hwnd, hdc, lpitem->fState & (MF_HILITE | MF_MOUSESELECT) ); - MENU_ReleaseMenu(menu); return; } @@ -1516,7 +1514,7 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED|ODS_DISABLED; if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED; dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */ - dis.hwndItem = (HWND)hmenu; + dis.hwndItem = (HWND)MENU_GetHandle(menu); dis.hDC = hdc; dis.rcItem = rect; TRACE("Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, " @@ -1528,14 +1526,11 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, if (lpitem->fType & MF_POPUP) draw_popup_arrow( hdc, rect, arrow_bitmap_width, arrow_bitmap_height); - MENU_ReleaseMenu(menu); return; } - if (menuBar && (lpitem->fType & MF_SEPARATOR)) { - MENU_ReleaseMenu(menu); + if (menuBar && (lpitem->fType & MF_SEPARATOR)) return; - } if (lpitem->fState & MF_HILITE) { @@ -1597,7 +1592,6 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, } else DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP); - MENU_ReleaseMenu(menu); return; } @@ -1683,7 +1677,7 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, POINT origorg; /* some applications make this assumption on the DC's origin */ SetViewportOrgEx( hdc, rect.left, rect.top, &origorg); - MENU_DrawBitmapItem(hdc, lpitem, &bmprc, hmenu, hwndOwner, + MENU_DrawBitmapItem(hdc, lpitem, &bmprc, MENU_GetHandle(menu), hwndOwner, odaction, FALSE); SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL); } @@ -1701,7 +1695,7 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, POINT origorg; SetViewportOrgEx( hdc, rect.left, rect.top, &origorg); - MENU_DrawBitmapItem( hdc, lpitem, &bmprc, hmenu, hwndOwner, + MENU_DrawBitmapItem( hdc, lpitem, &bmprc, MENU_GetHandle(menu), hwndOwner, odaction, menuBar); SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL); } @@ -1780,8 +1774,6 @@ static void MENU_DrawMenuItem( HWND hwnd, HMENU hmenu, HWND hwndOwner, HDC hdc, if (hfontOld) SelectObject (hdc, hfontOld); } - - MENU_ReleaseMenu(menu); } @@ -1829,7 +1821,7 @@ static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu ) item = menu->items; for( u = menu->nItems; u > 0; u--, item++) - MENU_DrawMenuItem( hwnd, hmenu, menu->hwndOwner, hdc, + MENU_DrawMenuItem( hwnd, menu, menu->hwndOwner, hdc, item, menu->Height, FALSE, ODA_DRAWENTIRE ); } /* draw scroll arrows */ @@ -1868,20 +1860,18 @@ UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd ) * * Popup menu initialization before WM_ENTERMENULOOP. */ -static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) +static BOOL MENU_InitPopup( HWND hwndOwner, POPUPMENU *menu, UINT flags ) { - POPUPMENU *menu; DWORD ex_style = 0; - TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu); + TRACE("owner=%p hmenu=%p\n", hwndOwner, MENU_GetHandle(menu)); - if (!(menu = MENU_GetMenu( hmenu ))) return FALSE; + if (!menu) return FALSE; /* store the owner for DrawItem */ if (!IsWindow( hwndOwner )) { SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - MENU_ReleaseMenu(menu); return FALSE; } menu->hwndOwner = hwndOwner; @@ -1893,13 +1883,10 @@ static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) menu->hWnd = CreateWindowExW( ex_style, (LPCWSTR)POPUPMENU_CLASS_ATOM, NULL, WS_POPUP, 0, 0, 0, 0, hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), - (LPVOID)hmenu ); - if( !menu->hWnd ) { - MENU_ReleaseMenu(menu); + (LPVOID)MENU_GetHandle(menu) ); + if( !menu->hWnd ) return FALSE; - } - MENU_ReleaseMenu(menu); return TRUE; } @@ -1909,19 +1896,18 @@ static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) * * Display a popup menu. */ -static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id, UINT flags, +static BOOL MENU_ShowPopup( HWND hwndOwner, POPUPMENU *menu, UINT id, UINT flags, INT x, INT y, INT xanchor, INT yanchor ) { - POPUPMENU *menu; INT width, height; POINT pt; HMONITOR monitor; MONITORINFO info; TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n", - hwndOwner, hmenu, id, x, y, xanchor, yanchor); + hwndOwner, MENU_GetHandle(menu), id, x, y, xanchor, yanchor); - if (!(menu = MENU_GetMenu( hmenu ))) return FALSE; + if (!menu) return FALSE; if (menu->FocusedItem != NO_SELECTED_ITEM) { menu->items[menu->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT); @@ -1974,14 +1960,13 @@ static BOOL MENU_ShowPopup( HWND hwndOwner, HMENU hmenu, UINT id, UINT flags, if (!top_popup) { top_popup = menu->hWnd; - top_popup_hmenu = hmenu; + top_popup_hmenu = MENU_GetHandle(menu); } /* Display the window */ SetWindowPos( menu->hWnd, HWND_TOPMOST, x, y, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE ); UpdateWindow( menu->hWnd ); - MENU_ReleaseMenu(menu); return TRUE; } @@ -2060,7 +2045,7 @@ static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex, if (lppop->FocusedItem != NO_SELECTED_ITEM) { lppop->items[lppop->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT); - MENU_DrawMenuItem(lppop->hWnd, hmenu, hwndOwner, hdc,&lppop->items[lppop->FocusedItem], + MENU_DrawMenuItem(lppop->hWnd, lppop, hwndOwner, hdc,&lppop->items[lppop->FocusedItem], lppop->Height, !(lppop->wFlags & MF_POPUP), ODA_SELECT ); } @@ -2072,7 +2057,7 @@ static void MENU_SelectItem( HWND hwndOwner, HMENU hmenu, UINT wIndex, if(!(lppop->items[wIndex].fType & MF_SEPARATOR)) { lppop->items[wIndex].fState |= MF_HILITE; MENU_EnsureMenuItemVisible(lppop, wIndex, hdc); - MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc, + MENU_DrawMenuItem( lppop->hWnd, lppop, hwndOwner, hdc, &lppop->items[wIndex], lppop->Height, !(lppop->wFlags & MF_POPUP), ODA_SELECT ); } @@ -2358,50 +2343,40 @@ static HMENU MENU_GetSubPopup( HMENU hmenu ) * * Hide the sub-popup menus of this menu. */ -static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu, +static void MENU_HideSubPopups( HWND hwndOwner, POPUPMENU *menu, BOOL sendMenuSelect, UINT wFlags ) { - POPUPMENU *menu = MENU_GetMenu( hmenu ); - TRACE("owner=%p hmenu=%p 0x%04x\n", hwndOwner, hmenu, sendMenuSelect); + TRACE("owner=%p hmenu=%p 0x%04x\n", hwndOwner, MENU_GetHandle(menu), sendMenuSelect); if (!menu) return; if (top_popup) { - HMENU hsubmenu; - POPUPMENU *submenu; - MENUITEM *item; + HMENU hsubmenu; + MENUITEM *item; - if (menu->FocusedItem != NO_SELECTED_ITEM) - { - item = &menu->items[menu->FocusedItem]; - if (!(item->fType & MF_POPUP) || - !(item->fState & MF_MOUSESELECT)) return; - item->fState &= ~MF_MOUSESELECT; - submenu = item->submenu; - hsubmenu = MENU_GetHandle(item->submenu); - } else { - MENU_ReleaseMenu(menu); - return; - } + if (menu->FocusedItem == NO_SELECTED_ITEM) + return; - if (!submenu) { - MENU_ReleaseMenu(menu); - return; - } - MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE, wFlags ); - MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 ); - DestroyWindow( submenu->hWnd ); - submenu->hWnd = 0; + item = &menu->items[menu->FocusedItem]; + if (!(item->fType & MF_POPUP) || + !(item->fState & MF_MOUSESELECT)) return; + item->fState &= ~MF_MOUSESELECT; + if (!item->submenu) + return; + hsubmenu = MENU_GetHandle(item->submenu); + + MENU_HideSubPopups( hwndOwner, item->submenu, FALSE, wFlags ); + MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 ); + DestroyWindow( item->submenu->hWnd ); + item->submenu->hWnd = 0; if (!(wFlags & TPM_NONOTIFY)) SendMessageW( hwndOwner, WM_UNINITMENUPOPUP, (WPARAM)hsubmenu, - MAKELPARAM(0, IS_SYSTEM_MENU(submenu)) ); + MAKELPARAM(0, IS_SYSTEM_MENU(item->submenu)) ); } - - MENU_ReleaseMenu(menu); } @@ -2454,7 +2429,7 @@ static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu, SelectObject( hdc, get_menu_font(FALSE)); item->fState |= MF_HILITE; - MENU_DrawMenuItem( menu->hWnd, hmenu, hwndOwner, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP), ODA_DRAWENTIRE ); + MENU_DrawMenuItem( menu->hWnd, menu, hwndOwner, hdc, item, menu->Height, !(menu->wFlags & MF_POPUP), ODA_DRAWENTIRE ); ReleaseDC( menu->hWnd, hdc ); } if (!item->rect.top && !item->rect.left && !item->rect.bottom && !item->rect.right) @@ -2509,9 +2484,9 @@ static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu, /* use default alignment for submenus */ wFlags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN); - MENU_InitPopup( hwndOwner, MENU_GetHandle(item->submenu), wFlags ); + MENU_InitPopup( hwndOwner, item->submenu, wFlags ); - MENU_ShowPopup( hwndOwner, MENU_GetHandle(item->submenu), menu->FocusedItem, wFlags, + MENU_ShowPopup( hwndOwner, item->submenu, menu->FocusedItem, wFlags, rect.left, rect.top, rect.right, rect.bottom ); if (selectFirst) MENU_MoveSelection( hwndOwner, MENU_GetHandle(item->submenu), ITEM_NEXT ); @@ -2663,11 +2638,11 @@ static void MENU_SwitchTracking( MTRACKER* pmt, HMENU hPtMenu, UINT id, UINT wFl !((ptmenu->wFlags | topmenu->wFlags) & MF_POPUP) ) { /* both are top level menus (system and menu-bar) */ - MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE, wFlags ); + MENU_HideSubPopups( pmt->hOwnerWnd, topmenu, FALSE, wFlags ); MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, FALSE, 0 ); pmt->hTopMenu = hPtMenu; } - else MENU_HideSubPopups( pmt->hOwnerWnd, hPtMenu, FALSE, wFlags ); + else MENU_HideSubPopups( pmt->hOwnerWnd, ptmenu, FALSE, wFlags ); MENU_SelectItem( pmt->hOwnerWnd, hPtMenu, id, TRUE, 0 ); MENU_ReleaseMenu(ptmenu); MENU_ReleaseMenu(topmenu); @@ -2929,9 +2904,12 @@ static LRESULT MENU_DoNextMenu( MTRACKER* pmt, UINT vk, UINT wFlags ) if( hNewMenu != pmt->hTopMenu ) { MENU_SelectItem( pmt->hOwnerWnd, pmt->hTopMenu, NO_SELECTED_ITEM, - FALSE, 0 ); - if( pmt->hCurrentMenu != pmt->hTopMenu ) - MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE, wFlags ); + FALSE, 0 ); + if( pmt->hCurrentMenu != pmt->hTopMenu ) { + POPUPMENU *topmenu = MENU_GetMenu(pmt->hTopMenu); + MENU_HideSubPopups( pmt->hOwnerWnd, topmenu, FALSE, wFlags ); + MENU_ReleaseMenu(topmenu); + } } if( hNewWnd != pmt->hOwnerWnd ) @@ -3002,6 +2980,7 @@ static BOOL MENU_KeyEscape(MTRACKER* pmt, UINT wFlags) if (menu->wFlags & MF_POPUP) { HMENU hmenutmp, hmenuprev; + POPUPMENU *menuprev; hmenuprev = hmenutmp = pmt->hTopMenu; @@ -3012,7 +2991,9 @@ static BOOL MENU_KeyEscape(MTRACKER* pmt, UINT wFlags) hmenutmp = MENU_GetSubPopup( hmenuprev ); } - MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE, wFlags ); + menuprev = MENU_GetMenu(hmenuprev); + MENU_HideSubPopups( pmt->hOwnerWnd, menuprev, TRUE, wFlags ); + MENU_ReleaseMenu(menuprev); pmt->hCurrentMenu = hmenuprev; bEndMenu = FALSE; } @@ -3029,7 +3010,7 @@ static BOOL MENU_KeyEscape(MTRACKER* pmt, UINT wFlags) */ static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags ) { - POPUPMENU *menu; + POPUPMENU *menu, *menuprev; HMENU hmenutmp, hmenuprev; UINT prevcol; @@ -3053,7 +3034,9 @@ static void MENU_KeyLeft( MTRACKER* pmt, UINT wFlags ) hmenutmp = MENU_GetSubPopup( hmenuprev ); } - MENU_HideSubPopups( pmt->hOwnerWnd, hmenuprev, TRUE, wFlags ); + menuprev = MENU_GetMenu(hmenuprev); + MENU_HideSubPopups( pmt->hOwnerWnd, menuprev, TRUE, wFlags ); + MENU_ReleaseMenu(menuprev); pmt->hCurrentMenu = hmenuprev; if ( (hmenuprev == pmt->hTopMenu) && !(menu->wFlags & MF_POPUP) ) @@ -3125,7 +3108,9 @@ static void MENU_KeyRight( MTRACKER* pmt, UINT wFlags ) { if( pmt->hCurrentMenu != pmt->hTopMenu ) { - MENU_HideSubPopups( pmt->hOwnerWnd, pmt->hTopMenu, FALSE, wFlags ); + POPUPMENU *topmenu = MENU_GetMenu( pmt->hTopMenu); + MENU_HideSubPopups( pmt->hOwnerWnd, topmenu, FALSE, wFlags ); + MENU_ReleaseMenu(topmenu); hmenutmp = pmt->hCurrentMenu = pmt->hTopMenu; } else hmenutmp = 0; @@ -3429,7 +3414,7 @@ static BOOL MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y, if( IsWindow( mt.hOwnerWnd ) ) { - MENU_HideSubPopups( mt.hOwnerWnd, mt.hTopMenu, FALSE, wFlags ); + MENU_HideSubPopups( mt.hOwnerWnd, menu, FALSE, wFlags ); if (menu && (menu->wFlags & MF_POPUP)) { @@ -3633,7 +3618,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y, return FALSE; } - if (MENU_InitPopup( hWnd, hMenu, wFlags )) + if (MENU_InitPopup( hWnd, menu, wFlags )) { MENU_InitTracking(hWnd, hMenu, TRUE, wFlags); @@ -3641,7 +3626,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y, if (!(wFlags & TPM_NONOTIFY)) SendMessageW( hWnd, WM_INITMENUPOPUP, (WPARAM)hMenu, 0); - if (MENU_ShowPopup( hWnd, hMenu, 0, wFlags, x, y, 0, 0 )) + if (MENU_ShowPopup( hWnd, menu, 0, wFlags, x, y, 0, 0 )) ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, lpTpm ? &lpTpm->rcExclude : NULL ); MENU_ExitTracking(hWnd, TRUE); @@ -3943,7 +3928,7 @@ BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID, MENU_ReleaseMenu(menu); return TRUE; } - MENU_HideSubPopups( hWnd, hMenu, FALSE, 0 ); + MENU_HideSubPopups( hWnd, menu, FALSE, 0 ); MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 ); MENU_ReleaseMenu(menu); return TRUE; @@ -4656,7 +4641,7 @@ DWORD WINAPI DrawMenuBarTemp(HWND hwnd, HDC hDC, LPRECT lprect, HMENU hMenu, HFO for (i = 0; i < lppop->nItems; i++) { - MENU_DrawMenuItem( hwnd, hMenu, hwnd, + MENU_DrawMenuItem( hwnd, lppop, hwnd, hDC, &lppop->items[i], lppop->Height, TRUE, ODA_DRAWENTIRE ); } retvalue = lppop->Height; -- 2.1.0