- Patch by Victor Martinez Calvo : Several menu.c fixes. See CORE-7967.
- Sync port from wine with modifications

svn path=/trunk/; revision=62528
This commit is contained in:
James Tabor 2014-03-18 04:11:30 +00:00
parent 13bd05110c
commit 6e6984882a

View file

@ -36,6 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(menu);
#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */ #define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */
#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */ #define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */
/* top and bottom margins for popup menus */
#define MENU_TOP_MARGIN 3
#define MENU_BOTTOM_MARGIN 2
#define MENU_TYPE_MASK (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR) #define MENU_TYPE_MASK (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR)
@ -1303,7 +1306,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd
HBITMAP bm; HBITMAP bm;
INT y = rect.top + rect.bottom; INT y = rect.top + rect.bottom;
RECT rc = rect; RECT rc = rect;
int checked = FALSE; BOOL checked = FALSE;
UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK );
UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK ); UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK );
/* Draw the check mark /* Draw the check mark
@ -1551,6 +1554,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
POINT pt; POINT pt;
HMONITOR monitor; HMONITOR monitor;
MONITORINFO info; MONITORINFO info;
DWORD ex_style = 0;
TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n", 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, hmenu, id, x, y, xanchor, yanchor);
@ -1592,6 +1596,11 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
info.cbSize = sizeof(info); info.cbSize = sizeof(info);
GetMonitorInfoW( monitor, &info ); GetMonitorInfoW( monitor, &info );
if (flags & TPM_LAYOUTRTL)
{
ex_style = WS_EX_LAYOUTRTL;
flags ^= TPM_RIGHTALIGN;
}
if( flags & TPM_RIGHTALIGN ) x -= width; if( flags & TPM_RIGHTALIGN ) x -= width;
if( flags & TPM_CENTERALIGN ) x -= width / 2; if( flags & TPM_CENTERALIGN ) x -= width / 2;
@ -1619,7 +1628,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl
if( y < info.rcMonitor.top ) y = info.rcMonitor.top; if( y < info.rcMonitor.top ) y = info.rcMonitor.top;
/* NOTE: In Windows, top menu popup is not owned. */ /* NOTE: In Windows, top menu popup is not owned. */
MenuInfo.Wnd = CreateWindowExW( 0, WC_MENU, NULL, MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL,
WS_POPUP, x, y, width, height, WS_POPUP, x, y, width, height,
hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
(LPVOID) MenuInfo.Self); (LPVOID) MenuInfo.Self);
@ -1697,9 +1706,9 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn
} }
if (sendMenuSelect) if (sendMenuSelect)
{ {
WPARAM wParam = MAKELONG( ItemInfo.fType & MF_POPUP ? wIndex : ItemInfo.wID, WPARAM wParam = MAKEWPARAM( ItemInfo.fType & MF_POPUP ? wIndex : ItemInfo.wID,
ItemInfo.fType | ItemInfo.fState | ItemInfo.fType | ItemInfo.fState |
(hmenu->Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); (hmenu->Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) );
SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) hmenu->Self); SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) hmenu->Self);
} }
@ -1714,8 +1723,8 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn
if (MenuGetRosMenuInfo(&TopMenuInfo, topmenu) if (MenuGetRosMenuInfo(&TopMenuInfo, topmenu)
&& MenuGetRosMenuItemInfo(topmenu, pos, &ItemInfo)) && MenuGetRosMenuItemInfo(topmenu, pos, &ItemInfo))
{ {
WPARAM wParam = MAKELONG( Pos, ItemInfo.fType | ItemInfo.fState | WPARAM wParam = MAKEWPARAM( Pos, ItemInfo.fType | ItemInfo.fState |
(TopMenuInfo.Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) ); (TopMenuInfo.Flags & MNF_SYSDESKMN ? MF_SYSMENU : 0 ) );
SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) topmenu); SendMessageW(hwndOwner, WM_MENUSELECT, wParam, (LPARAM) topmenu);
} }
@ -1999,11 +2008,11 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam)
* *
* NOTE: flags is equivalent to the mtOption field * NOTE: flags is equivalent to the mtOption field
*/ */
static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode ) static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu)
{ {
WORD flags, id = 0; WORD flags, id = 0;
HMENU hSubMenu; HMENU hSubMenu;
LPCSTR str; LPCWSTR str;
BOOL end = FALSE; BOOL end = FALSE;
do do
@ -2020,46 +2029,19 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
id = GET_WORD(res); id = GET_WORD(res);
res += sizeof(WORD); res += sizeof(WORD);
} }
str = res; str = (LPCWSTR)res;
if(!unicode) res += (strlenW(str) + 1) * sizeof(WCHAR);
res += strlen(str) + 1;
else
res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR);
if (flags & MF_POPUP) if (flags & MF_POPUP)
{ {
hSubMenu = CreatePopupMenu(); hSubMenu = CreatePopupMenu();
if(!hSubMenu) return NULL; if(!hSubMenu) return NULL;
if(!(res = MENU_ParseResource(res, hSubMenu, unicode))) if(!(res = MENU_ParseResource(res, hSubMenu))) return NULL;
return NULL; AppendMenuW(hMenu, flags, (UINT_PTR)hSubMenu, (LPCWSTR)str);
if(!unicode)
AppendMenuA(hMenu, flags, (UINT)hSubMenu, str);
else
AppendMenuW(hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str);
} }
else /* Not a popup */ else /* Not a popup */
{ {
if(!unicode) AppendMenuW(hMenu, flags, id, *(LPCWSTR)str ? (LPCWSTR)str : NULL);
{
if (*str == 0)
flags = MF_SEPARATOR;
}
else
{
if (*(LPCWSTR)str == 0)
flags = MF_SEPARATOR;
}
if (flags & MF_SEPARATOR)
{
if (!(flags & (MF_GRAYED | MF_DISABLED)))
flags |= MF_GRAYED | MF_DISABLED;
}
if(!unicode)
AppendMenuA(hMenu, flags, id, *str ? str : NULL);
else
AppendMenuW(hMenu, flags, id,
*(LPCWSTR)str ? (LPCWSTR)str : NULL);
} }
} while(!end); } while(!end);
return res; return res;
@ -2075,10 +2057,10 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode )
static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu) static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu)
{ {
WORD resinfo; WORD resinfo;
MENUITEMINFOW mii;
do do
{ {
MENUITEMINFOW mii;
mii.cbSize = sizeof(mii); mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE; mii.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
mii.fType = GET_DWORD(res); mii.fType = GET_DWORD(res);
@ -2119,13 +2101,12 @@ static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu)
} }
mii.fMask |= MIIM_SUBMENU; mii.fMask |= MIIM_SUBMENU;
mii.fType |= MF_POPUP; mii.fType |= MF_POPUP;
mii.wID = (UINT)mii.hSubMenu;
} }
else if (!mii.dwTypeData[0]) else if (!mii.dwTypeData[0] && !(mii.fType & MF_SEPARATOR))
{
mii.fType |= MF_SEPARATOR; mii.fType |= MF_SEPARATOR;
}
if (!InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii)) InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii);
ERR("InsertMenuItemW failed\n");
} while (!(resinfo & MF_END)); } while (!(resinfo & MF_END));
return res; return res;
} }
@ -2332,7 +2313,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
if (0 == (Flags & TPM_NONOTIFY)) if (0 == (Flags & TPM_NONOTIFY))
{ {
SendMessageW(WndOwner, WM_INITMENUPOPUP, (WPARAM) ItemInfo.hSubMenu, SendMessageW(WndOwner, WM_INITMENUPOPUP, (WPARAM) ItemInfo.hSubMenu,
MAKELONG(MenuInfo->FocusedItem, IS_SYSTEM_MENU(MenuInfo))); MAKELPARAM(MenuInfo->FocusedItem, IS_SYSTEM_MENU(MenuInfo)));
} }
if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)) if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo))
@ -2377,38 +2358,47 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl
{ {
MenuInitSysMenuPopup(ItemInfo.hSubMenu, GetWindowLongPtrW(MenuInfo->Wnd, GWL_STYLE), MenuInitSysMenuPopup(ItemInfo.hSubMenu, GetWindowLongPtrW(MenuInfo->Wnd, GWL_STYLE),
GetClassLongPtrW(MenuInfo->Wnd, GCL_STYLE), HTSYSMENU); GetClassLongPtrW(MenuInfo->Wnd, GCL_STYLE), HTSYSMENU);
if (Flags & TPM_LAYOUTRTL) Rect.left;
NcGetSysPopupPos(MenuInfo->Wnd, &Rect); NcGetSysPopupPos(MenuInfo->Wnd, &Rect);
Rect.top = Rect.bottom; Rect.top = Rect.bottom;
Rect.right = GetSystemMetrics(SM_CXSIZE); Rect.right = GetSystemMetrics(SM_CXSIZE);
Rect.bottom = GetSystemMetrics(SM_CYSIZE); Rect.bottom = GetSystemMetrics(SM_CYSIZE);
} }
else else
{ {
GetWindowRect(MenuInfo->Wnd, &Rect); GetWindowRect(MenuInfo->Wnd, &Rect);
if (0 != (MenuInfo->Flags & MNF_POPUP)) if (0 != (MenuInfo->Flags & MNF_POPUP))
{ {
Rect.left += ItemInfo.Rect.right - GetSystemMetrics(SM_CXBORDER); if(Flags & TPM_LAYOUTRTL)
Rect.top += ItemInfo.Rect.top - 3; Rect.left += GetSystemMetrics(SM_CXBORDER);
else
Rect.left += ItemInfo.Rect.right- GetSystemMetrics(SM_CXBORDER);
Rect.top += ItemInfo.Rect.top - MENU_TOP_MARGIN;//3;
Rect.right = ItemInfo.Rect.left - ItemInfo.Rect.right + GetSystemMetrics(SM_CXBORDER); Rect.right = ItemInfo.Rect.left - ItemInfo.Rect.right + GetSystemMetrics(SM_CXBORDER);
Rect.bottom = ItemInfo.Rect.top - ItemInfo.Rect.bottom - 3 - 2 Rect.bottom = ItemInfo.Rect.top - ItemInfo.Rect.bottom - MENU_TOP_MARGIN - MENU_BOTTOM_MARGIN/*2*/
- GetSystemMetrics(SM_CYBORDER); - GetSystemMetrics(SM_CYBORDER);
} }
else else
{ {
Rect.left += ItemInfo.Rect.left; if(Flags & TPM_LAYOUTRTL)
Rect.left += Rect.right - ItemInfo.Rect.left;
else
Rect.left += ItemInfo.Rect.left;
Rect.top += ItemInfo.Rect.bottom; Rect.top += ItemInfo.Rect.bottom;
Rect.right = ItemInfo.Rect.right - ItemInfo.Rect.left; Rect.right = ItemInfo.Rect.right - ItemInfo.Rect.left;
Rect.bottom = ItemInfo.Rect.bottom - ItemInfo.Rect.top; Rect.bottom = ItemInfo.Rect.bottom - ItemInfo.Rect.top;
} }
} }
/* use default alignment for submenus */
Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN);
MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->FocusedItem, Flags, MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->FocusedItem, Flags,
Rect.left, Rect.top, Rect.right, Rect.bottom ); Rect.left, Rect.top, Rect.right, Rect.bottom );
if (SelectFirst && MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu)) if (SelectFirst && MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu))
{ {
MenuMoveSelection(WndOwner, &SubMenuInfo, ITEM_NEXT); MenuMoveSelection(WndOwner, &SubMenuInfo, ITEM_NEXT);
} }
Ret = ItemInfo.hSubMenu; Ret = ItemInfo.hSubMenu;
MenuCleanupRosMenuItemInfo(&ItemInfo); MenuCleanupRosMenuItemInfo(&ItemInfo);
@ -2985,20 +2975,20 @@ MenuSuspendPopup(MTRACKER* Mt, UINT uMsg)
switch( uMsg ) switch( uMsg )
{ {
case WM_KEYDOWN: case WM_KEYDOWN:
PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE); PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
if( msg.message == WM_KEYUP || msg.message == WM_PAINT ) if( msg.message == WM_KEYUP || msg.message == WM_PAINT )
{ {
PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE); PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE);
PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE); PeekMessageW( &msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE);
if( msg.message == WM_KEYDOWN && if( msg.message == WM_KEYDOWN &&
(msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT)) (msg.wParam == VK_LEFT || msg.wParam == VK_RIGHT))
{ {
Mt->TrackFlags |= TF_SUSPENDPOPUP; Mt->TrackFlags |= TF_SUSPENDPOPUP;
return TRUE; return TRUE;
} }
} }
break; break;
} }
/* failures go through this */ /* failures go through this */
Mt->TrackFlags &= ~TF_SUSPENDPOPUP; Mt->TrackFlags &= ~TF_SUSPENDPOPUP;
@ -3622,6 +3612,7 @@ VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt)
TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y); TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y);
if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) wFlags |= TPM_LAYOUTRTL;
if (IsMenu(hMenu)) if (IsMenu(hMenu))
{ {
/* map point to parent client coordinates */ /* map point to parent client coordinates */
@ -3723,6 +3714,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
/* ReactOS Check */ /* ReactOS Check */
if (!ValidateHwnd(Wnd)) if (!ValidateHwnd(Wnd))
{ {
/* invalid window see wine menu.c test_menu_trackpopupmenu line 3146 */
return FALSE; return FALSE;
} }
@ -4823,7 +4815,7 @@ LoadMenuIndirectW(CONST MENUTEMPLATE *lpMenuTemplate)
offset = GET_WORD(p); offset = GET_WORD(p);
p += sizeof(WORD) + offset; p += sizeof(WORD) + offset;
if (!(hMenu = CreateMenu())) return 0; if (!(hMenu = CreateMenu())) return 0;
if (!MENU_ParseResource(p, hMenu, TRUE)) if (!MENU_ParseResource(p, hMenu))
{ {
DestroyMenu(hMenu); DestroyMenu(hMenu);
return 0; return 0;