
user: client/user menu data split
Move back menu drawing state into client

Thomas Kho

---

 dlls/user/menu.c               |  237 ++++++++++++++++++++++++----------------
 dlls/user/user_private.h       |    5 +
 dlls/user/win.c                |    5 -
 include/wine/server_protocol.h |   28 +----
 server/menu.c                  |   17 ---
 server/protocol.def            |   26 +---
 server/trace.c                 |    8 -
 7 files changed, 162 insertions(+), 164 deletions(-)

diff --git a/dlls/user/menu.c b/dlls/user/menu.c
index aa0a3aa..20af392 100644
--- a/dlls/user/menu.c
+++ b/dlls/user/menu.c
@@ -98,11 +98,7 @@ typedef struct {
     UINT        nItems;       /* Number of items in the menu */
     HWND        hWnd;         /* Window containing the menu */
     MENUITEM    *items;       /* Array of menu items */
-    UINT        FocusedItem;  /* Currently focused item */
     HWND	hwndOwner;    /* window receiving the messages for ownerdraw */
-    BOOL        bTimeToHide;  /* Request hiding when receiving a second click in the top-level menu item */
-    BOOL        bScrolling;   /* Scroll arrows are active */
-    UINT        nScrollPos;   /* Current scroll position */
     UINT        nTotalHeight; /* Total height of menu items inside menu */
     /* ------------ MENUINFO members ------ */
     DWORD	dwStyle;	/* Extended menu style */
@@ -114,6 +110,13 @@ typedef struct {
     SIZE        maxBmpSize;     /* Maximum size of the bitmap items */
 } POPUPMENU, *LPPOPUPMENU;
 
+typedef struct {
+    UINT        FocusedItem;  /* Currently focused item */
+    BOOL        bTimeToHide;  /* Request hiding when receiving a second click in the top-level menu item */
+    BOOL        bScrolling;   /* Scroll arrows are active */
+    UINT        nScrollPos;   /* Current scroll position */
+} LOCALPOPUPMENU, *LPLOCALPOPUPMENU;
+
 /* internal flags for menu tracking */
 
 #define TF_ENDMENU              0x0001
@@ -283,6 +286,17 @@ #undef MENUFLAG
 
 
 /***********************************************************************
+ *           MENU_GetLocalMenu
+ *
+ * Get a local copy of menu for given hMenu
+ */
+static LOCALPOPUPMENU * MENU_GetLocalMenu(HMENU hMenu)
+{
+    TRACE("hMenu=%p\n", hMenu);
+    return user_handles[USER_HANDLE_TO_INDEX(hMenu)];
+}
+
+/***********************************************************************
  *           MENU_GetMenu
  *
  * Get a local copy of menu for given hMenu
@@ -303,11 +317,7 @@ static NTSTATUS MENU_GetMenu(HMENU hMenu
             menu->nItems = reply->nitems;
             menu->hWnd = reply->hwnd;
             menu->items = reply->items;
-            menu->FocusedItem = reply->focuseditem;
             menu->hwndOwner = reply->hwndowner;
-            menu->bTimeToHide = reply->timetohide;
-            menu->bScrolling = reply->scrolling;
-            menu->nScrollPos = reply->scrollpos;
             menu->nTotalHeight = reply->totalheight;
 
             menu->dwStyle = reply->style;
@@ -343,11 +353,7 @@ static NTSTATUS MENU_UpdateMenu(HMENU hM
         req->nitems = menu->nItems;
         req->hwnd = menu->hWnd;
         req->items = menu->items;
-        req->focuseditem = menu->FocusedItem;
         req->hwndowner = menu->hwndOwner;
-        req->timetohide = menu->bTimeToHide;
-        req->scrolling = menu->bScrolling;
-        req->scrollpos = menu->nScrollPos;
         req->totalheight = menu->nTotalHeight;
 
         req->style = menu->dwStyle;
@@ -598,7 +604,7 @@ static UINT  MENU_GetStartOfNextColumn(
     if(MENU_GetMenu(hMenu, menu))
 	return NO_SELECTED_ITEM;
 
-    i = menu->FocusedItem + 1;
+    i = MENU_GetLocalMenu(hMenu)->FocusedItem + 1;
     if( i == NO_SELECTED_ITEM )
 	return i;
 
@@ -628,14 +634,15 @@ static UINT  MENU_GetStartOfPrevColumn(
     if( MENU_GetMenu(hMenu, menu) )
 	return NO_SELECTED_ITEM;
 
-    if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM )
+    i = MENU_GetLocalMenu(hMenu)->FocusedItem;
+    if( i == 0 || i == NO_SELECTED_ITEM )
 	return NO_SELECTED_ITEM;
 
     /* Find the start of the column */
 
-    for(i = menu->FocusedItem; i != 0 &&
-	 !(menu->items[i].fType & MF_MENUBARBREAK);
-	--i); /* empty */
+    for(i = MENU_GetLocalMenu(hMenu)->FocusedItem; i != 0 &&
+        !(menu->items[i].fType & MF_MENUBARBREAK);
+        --i) ; /* empty */
 
     if(i == 0)
 	return NO_SELECTED_ITEM;
@@ -757,8 +764,9 @@ static void MENU_FreeItemData( MENUITEM*
  * Adjust menu item rectangle according to scrolling state.
  */
 static void
-MENU_AdjustMenuItemRect(const POPUPMENU *menu, LPRECT rect)
+MENU_AdjustMenuItemRect(HMENU hmenu, LPRECT rect)
 {
+    LOCALPOPUPMENU *menu = MENU_GetLocalMenu(hmenu);
     if (menu->bScrolling)
     {
         UINT arrow_bitmap_width, arrow_bitmap_height;
@@ -780,13 +788,15 @@ MENU_AdjustMenuItemRect(const POPUPMENU 
  * not work for child windows and therefore should not be called for
  * an arbitrary system menu.
  */
-static MENUITEM *MENU_FindItemByCoords( const POPUPMENU *menu,
-					POINT pt, UINT *pos )
+static MENUITEM *MENU_FindItemByCoords( HMENU hmenu, POINT pt, UINT *pos )
 {
     MENUITEM *item;
     UINT i;
     RECT wrect;
     RECT rect;
+    POPUPMENU tmpmenu;
+    LPPOPUPMENU menu = &tmpmenu;
+    MENU_GetMenu(hmenu, menu);
 
     if (!GetWindowRect(menu->hWnd,&wrect)) return NULL;
     pt.x -= wrect.left;pt.y -= wrect.top;
@@ -794,7 +804,7 @@ static MENUITEM *MENU_FindItemByCoords( 
     for (i = 0; i < menu->nItems; i++, item++)
     {
         rect = item->rect;
-        MENU_AdjustMenuItemRect(menu, &rect);
+        MENU_AdjustMenuItemRect(hmenu, &rect);
 	if ((pt.x >= rect.left) && (pt.x < rect.right) &&
 	    (pt.y >= rect.top) && (pt.y < rect.bottom))
 	{
@@ -1194,15 +1204,23 @@ MENU_GetMaxPopupHeight(LPPOPUPMENU lppop
  *
  * Calculate the size of a popup menu.
  */
-static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
+static void MENU_PopupMenuCalcSize( HMENU hmenu, HWND hwndOwner )
 {
     MENUITEM *lpitem;
     HDC hdc;
     int start, i;
     int orgX, orgY, maxX, maxTab, maxTabWidth, maxHeight;
+    POPUPMENU tmppop;
+    LPPOPUPMENU lppop = &tmppop;
+    LOCALPOPUPMENU *lpm = MENU_GetLocalMenu(hmenu);
+    MENU_GetMenu(hmenu, lppop);
 
     lppop->Width = lppop->Height = 0;
-    if (lppop->nItems == 0) return;
+    if (lppop->nItems == 0)
+    {
+        MENU_UpdateMenu(hmenu, lppop, SET_MI_WIDTH|SET_MI_HEIGHT);
+        return;
+    }
     hdc = GetDC( 0 );
 
     SelectObject( hdc, get_menu_font(FALSE));
@@ -1264,13 +1282,14 @@ static void MENU_PopupMenuCalcSize( LPPO
     if (lppop->Height >= maxHeight)
     {
         lppop->Height = maxHeight;
-        lppop->bScrolling = TRUE;
+        lpm->bScrolling = TRUE;
     }
     else
     {
-        lppop->bScrolling = FALSE;
+        lpm->bScrolling = FALSE;
     }
 
+    MENU_UpdateMenu(hmenu, lppop, SET_MI_WIDTH|SET_MI_HEIGHT|SET_MI_MAXBMPSIZE|SET_MI_TOTALHEIGHT);
     ReleaseDC( 0, hdc );
 }
 
@@ -1356,20 +1375,22 @@ static void MENU_MenuBarCalcSize( HDC hd
  * Draw scroll arrows.
  */
 static void
-MENU_DrawScrollArrows(LPPOPUPMENU lppop, HDC hdc)
+MENU_DrawScrollArrows(HMENU hmenu, HDC hdc)
 {
     HDC hdcMem = CreateCompatibleDC(hdc);
     HBITMAP hOrigBitmap;
     UINT arrow_bitmap_width, arrow_bitmap_height;
     BITMAP bmp;
     RECT rect;
+    POPUPMENU tmpmenu;
+    const LPPOPUPMENU lppop = &tmpmenu;
+    MENU_GetMenu(hmenu, lppop);
 
     GetObjectW(get_down_arrow_bitmap(), sizeof(bmp), &bmp);
     arrow_bitmap_width = bmp.bmWidth;
     arrow_bitmap_height = bmp.bmHeight;
 
-    
-    if (lppop->nScrollPos)
+    if (MENU_GetLocalMenu(hmenu)->nScrollPos)
         hOrigBitmap = SelectObject(hdcMem, get_up_arrow_bitmap());
     else
         hOrigBitmap = SelectObject(hdcMem, get_up_arrow_inactive_bitmap());
@@ -1383,7 +1404,7 @@ MENU_DrawScrollArrows(LPPOPUPMENU lppop,
     rect.top = lppop->Height - arrow_bitmap_height;
     rect.bottom = lppop->Height;
     FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENU));
-    if (lppop->nScrollPos < lppop->nTotalHeight - (MENU_GetMaxPopupHeight(lppop) - 2 * arrow_bitmap_height))
+    if (MENU_GetLocalMenu(hmenu)->nScrollPos < lppop->nTotalHeight - (MENU_GetMaxPopupHeight(lppop) - 2 * arrow_bitmap_height))
         SelectObject(hdcMem, get_down_arrow_bitmap());
     else
         SelectObject(hdcMem, get_down_arrow_inactive_bitmap());
@@ -1476,7 +1497,7 @@ static void MENU_DrawMenuItem( HWND hwnd
     TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->rect));
     rect = lpitem->rect;
     MENU_GetMenu(hmenu, menu);
-    MENU_AdjustMenuItemRect(menu, &rect);
+    MENU_AdjustMenuItemRect(hmenu, &rect);
 
     if (lpitem->fType & MF_OWNERDRAW)
     {
@@ -1807,8 +1828,8 @@ static void MENU_DrawPopupMenu( HWND hwn
                                 item, menu->Height, FALSE, ODA_DRAWENTIRE );
                 }
                 /* draw scroll arrows */
-                if (menu->bScrolling)
-                    MENU_DrawScrollArrows(menu, hdc);
+                if (MENU_GetLocalMenu(hmenu)->bScrolling)
+                    MENU_DrawScrollArrows(hmenu, hdc);
             }
  	} else
 	{
@@ -1866,25 +1887,26 @@ static BOOL MENU_ShowPopup( HWND hwndOwn
 {
     POPUPMENU tmpmenu;
     POPUPMENU *menu = &tmpmenu;
+    LOCALPOPUPMENU *lpm = MENU_GetLocalMenu(hmenu);
     UINT width, height;
 
     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);
 
     if (MENU_GetMenu( hmenu, menu )) return FALSE;
-    if (menu->FocusedItem != NO_SELECTED_ITEM)
+    if (lpm->FocusedItem != NO_SELECTED_ITEM)
     {
-	menu->items[menu->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
-	menu->FocusedItem = NO_SELECTED_ITEM;
-        MENU_UpdateMenu(hmenu, menu, SET_MI_FOCUSITEM);
+	menu->items[lpm->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
+	lpm->FocusedItem = NO_SELECTED_ITEM;
     }
 
     /* store the owner for DrawItem */
     menu->hwndOwner = hwndOwner;
+    MENU_UpdateMenu(hmenu, menu, SET_MI_OWNER);
 
-    menu->nScrollPos = 0;
-    MENU_PopupMenuCalcSize( menu, hwndOwner );
-    MENU_UpdateMenu(hmenu, menu, SET_MI_WIDTH|SET_MI_HEIGHT|SET_MI_MAXBMPSIZE|SET_MI_TOTALHEIGHT|SET_MI_SCROLLING|SET_MI_SCROLLPOS|SET_MI_OWNER);
+    lpm->nScrollPos = 0;
+    MENU_PopupMenuCalcSize( hmenu, hwndOwner );
+    MENU_GetMenu(hmenu, menu);
 
     /* adjust popup menu pos so that it fits within the desktop */
 
@@ -1933,13 +1955,18 @@ static BOOL MENU_ShowPopup( HWND hwndOwn
  *           MENU_EnsureMenuItemVisible
  */
 static void
-MENU_EnsureMenuItemVisible(LPPOPUPMENU lppop, UINT wIndex, HDC hdc)
+MENU_EnsureMenuItemVisible(HMENU hmenu, UINT wIndex, HDC hdc)
 {
-    if (lppop->bScrolling)
+    POPUPMENU tmppop;
+    LPPOPUPMENU lppop = &tmppop;
+    LPLOCALPOPUPMENU lpm = MENU_GetLocalMenu(hmenu);
+    MENU_GetMenu(hmenu, lppop);
+
+    if (lpm->bScrolling)
     {
         MENUITEM *item = &lppop->items[wIndex];
         UINT nMaxHeight = MENU_GetMaxPopupHeight(lppop);
-        UINT nOldPos = lppop->nScrollPos;
+        UINT nOldPos = lpm->nScrollPos;
         RECT rc;
         UINT arrow_bitmap_height;
         BITMAP bmp;
@@ -1953,18 +1980,18 @@ MENU_EnsureMenuItemVisible(LPPOPUPMENU l
         rc.bottom -= arrow_bitmap_height + MENU_BOTTOM_MARGIN;
        
         nMaxHeight -= GetSystemMetrics(SM_CYBORDER) + 2 * arrow_bitmap_height;
-        if (item->rect.bottom > lppop->nScrollPos + nMaxHeight)
+        if (item->rect.bottom > lpm->nScrollPos + nMaxHeight)
         {
             
-            lppop->nScrollPos = item->rect.bottom - nMaxHeight;
-            ScrollWindow(lppop->hWnd, 0, nOldPos - lppop->nScrollPos, &rc, &rc);
-            MENU_DrawScrollArrows(lppop, hdc);
+            lpm->nScrollPos = item->rect.bottom - nMaxHeight;
+            ScrollWindow(lppop->hWnd, 0, nOldPos - lpm->nScrollPos, &rc, &rc);
+            MENU_DrawScrollArrows(hmenu, hdc);
         }
-        else if (item->rect.top - MENU_TOP_MARGIN < lppop->nScrollPos)
+        else if (item->rect.top - MENU_TOP_MARGIN < lpm->nScrollPos)
         {
-            lppop->nScrollPos = item->rect.top - MENU_TOP_MARGIN;
-            ScrollWindow(lppop->hWnd, 0, nOldPos - lppop->nScrollPos, &rc, &rc);
-            MENU_DrawScrollArrows(lppop, hdc);
+            lpm->nScrollPos = item->rect.top - MENU_TOP_MARGIN;
+            ScrollWindow(lppop->hWnd, 0, nOldPos - lpm->nScrollPos, &rc, &rc);
+            MENU_DrawScrollArrows(hmenu, hdc);
         }
     }
 }
@@ -1978,6 +2005,7 @@ static void MENU_SelectItem( HWND hwndOw
 {
     POPUPMENU tmppop;
     LPPOPUPMENU lppop = &tmppop;
+    LOCALPOPUPMENU *lpm;
     HDC hdc;
 
     TRACE("owner=%p menu=%p index=0x%04x select=0x%04x\n", hwndOwner, hmenu, wIndex, sendMenuSelect);
@@ -1985,7 +2013,8 @@ static void MENU_SelectItem( HWND hwndOw
     if (MENU_GetMenu( hmenu, lppop ) || (!lppop->nItems)
         || (!lppop->hWnd)) return;
 
-    if (lppop->FocusedItem == wIndex) return;
+    lpm = MENU_GetLocalMenu(hmenu);
+    if (lpm->FocusedItem == wIndex) return;
     if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd );
     else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW);
     if (!top_popup) top_popup = lppop->hWnd;
@@ -1993,29 +2022,29 @@ static void MENU_SelectItem( HWND hwndOw
     SelectObject( hdc, get_menu_font(FALSE));
 
       /* Clear previous highlighted item */
-    if (lppop->FocusedItem != NO_SELECTED_ITEM)
+    if (lpm->FocusedItem != NO_SELECTED_ITEM)
     {
-	lppop->items[lppop->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
-	MENU_DrawMenuItem(lppop->hWnd, hmenu, hwndOwner, hdc,&lppop->items[lppop->FocusedItem],
+	lppop->items[lpm->FocusedItem].fState &= ~(MF_HILITE|MF_MOUSESELECT);
+	MENU_DrawMenuItem(lppop->hWnd, hmenu, hwndOwner, hdc,
+                          &lppop->items[lpm->FocusedItem],
                           lppop->Height, !(lppop->wFlags & MF_POPUP),
 			  ODA_SELECT );
     }
 
       /* Highlight new item (if any) */
-    lppop->FocusedItem = wIndex;
-    MENU_UpdateMenu(hmenu, lppop, SET_MI_FOCUSITEM);
-    if (lppop->FocusedItem != NO_SELECTED_ITEM)
+    lpm->FocusedItem = wIndex;
+    if (lpm->FocusedItem != NO_SELECTED_ITEM)
     {
         if(!(lppop->items[wIndex].fType & MF_SEPARATOR)) {
             lppop->items[wIndex].fState |= MF_HILITE;
-            MENU_EnsureMenuItemVisible(lppop, wIndex, hdc);
+            MENU_EnsureMenuItemVisible(hmenu, wIndex, hdc);
             MENU_DrawMenuItem( lppop->hWnd, hmenu, hwndOwner, hdc,
                     &lppop->items[wIndex], lppop->Height,
                     !(lppop->wFlags & MF_POPUP), ODA_SELECT );
         }
         if (sendMenuSelect)
         {
-            MENUITEM *ip = &lppop->items[lppop->FocusedItem];
+            MENUITEM *ip = &lppop->items[lpm->FocusedItem];
 	    SendMessageW( hwndOwner, WM_MENUSELECT,
                      MAKELONG(ip->fType & MF_POPUP ? wIndex: ip->wID,
                      ip->fType | ip->fState |
@@ -2053,15 +2082,18 @@ static void MENU_MoveSelection( HWND hwn
     INT i;
     POPUPMENU tmpmenu;
     POPUPMENU *menu = &tmpmenu;
+    LOCALPOPUPMENU *lpm;
 
     TRACE("hwnd=%p hmenu=%p off=0x%04x\n", hwndOwner, hmenu, offset);
 
     if ((MENU_GetMenu(hmenu, menu)) || (!menu->items)) return;
 
-    if ( menu->FocusedItem != NO_SELECTED_ITEM )
+    lpm = MENU_GetLocalMenu(hmenu);
+
+    if ( lpm->FocusedItem != NO_SELECTED_ITEM )
     {
 	if( menu->nItems == 1 ) return; else
-	for (i = menu->FocusedItem + offset ; i >= 0 && i < menu->nItems
+	for (i = lpm->FocusedItem + offset ; i >= 0 && i < menu->nItems
 					    ; i += offset)
 	    if (!(menu->items[i].fType & MF_SEPARATOR))
 	    {
@@ -2332,12 +2364,14 @@ static HMENU MENU_GetSubPopup( HMENU hme
 {
     POPUPMENU tmpmenu;
     POPUPMENU *menu = &tmpmenu;
+    LOCALPOPUPMENU *lpm;
     MENUITEM *item;
 
+    lpm = MENU_GetLocalMenu(hmenu);
     if (MENU_GetMenu( hmenu, menu )
-        || (menu->FocusedItem == NO_SELECTED_ITEM)) return 0;
+        || (lpm->FocusedItem == NO_SELECTED_ITEM)) return 0;
 
-    item = &menu->items[menu->FocusedItem];
+    item = &menu->items[lpm->FocusedItem];
     if ((item->fType & MF_POPUP) && (item->fState & MF_MOUSESELECT))
         return item->hSubMenu;
     return 0;
@@ -2364,9 +2398,9 @@ static void MENU_HideSubPopups( HWND hwn
 	POPUPMENU *submenu = &tmpsubmenu;
 	MENUITEM *item;
 
-	if (menu->FocusedItem != NO_SELECTED_ITEM)
+	if (MENU_GetLocalMenu(hmenu)->FocusedItem != NO_SELECTED_ITEM)
 	{
-	    item = &menu->items[menu->FocusedItem];
+	    item = &menu->items[MENU_GetLocalMenu(hmenu)->FocusedItem];
 	    if (!(item->fType & MF_POPUP) ||
 		!(item->fState & MF_MOUSESELECT)) return;
 	    item->fState &= ~MF_MOUSESELECT;
@@ -2402,9 +2436,9 @@ static HMENU MENU_ShowSubPopup( HWND hwn
 
     if (MENU_GetMenu( hmenu, menu )) return hmenu;
 
-    if (menu->FocusedItem == NO_SELECTED_ITEM) return hmenu;
+    if (MENU_GetLocalMenu(hmenu)->FocusedItem == NO_SELECTED_ITEM) return hmenu;
 
-    item = &menu->items[menu->FocusedItem];
+    item = &menu->items[MENU_GetLocalMenu(hmenu)->FocusedItem];
     if (!(item->fType & MF_POPUP) || (item->fState & (MF_GRAYED | MF_DISABLED)))
         return hmenu;
 
@@ -2414,9 +2448,10 @@ static HMENU MENU_ShowSubPopup( HWND hwn
     /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
     if (!(wFlags & TPM_NONOTIFY))
        SendMessageW( hwndOwner, WM_INITMENUPOPUP, (WPARAM)item->hSubMenu,
-                     MAKELONG( menu->FocusedItem, IS_SYSTEM_MENU(menu) ));
+                     MAKELONG( MENU_GetLocalMenu(hmenu)->FocusedItem,
+                               IS_SYSTEM_MENU(menu) ));
 
-    item = &menu->items[menu->FocusedItem];
+    item = &menu->items[MENU_GetLocalMenu(hmenu)->FocusedItem];
     rect = item->rect;
 
     /* correct item if modified as a reaction to WM_INITMENUPOPUP message */
@@ -2454,7 +2489,7 @@ static HMENU MENU_ShowSubPopup( HWND hwn
 	{
             RECT rc = item->rect;
 
-            MENU_AdjustMenuItemRect(menu, &rc);
+            MENU_AdjustMenuItemRect(hmenu, &rc);
 
 	    /* The first item in the popup menu has to be at the
 	       same y position as the focused menu item */
@@ -2473,7 +2508,8 @@ static HMENU MENU_ShowSubPopup( HWND hwn
 	}
     }
 
-    MENU_ShowPopup( hwndOwner, item->hSubMenu, menu->FocusedItem,
+    MENU_ShowPopup( hwndOwner, item->hSubMenu,
+                    MENU_GetLocalMenu(hmenu)->FocusedItem,
 		    rect.left, rect.top, rect.right, rect.bottom );
     if (selectFirst)
         MENU_MoveSelection( hwndOwner, item->hSubMenu, ITEM_NEXT );
@@ -2502,7 +2538,7 @@ static HMENU MENU_PtMenu( HMENU hMenu, P
    UINT item;
    HMENU ret;
    MENU_GetMenu( hMenu, menu );
-   item = menu->FocusedItem;
+   item = MENU_GetLocalMenu(hMenu)->FocusedItem;
 
    /* try subpopup first (if any) */
    ret = (item != NO_SELECTED_ITEM &&
@@ -2544,9 +2580,9 @@ static INT MENU_ExecFocusedItem( MTRACKE
     TRACE("%p hmenu=%p\n", pmt, hMenu);
 
     if (MENU_GetMenu( hMenu, menu ) || !menu->nItems ||
-	(menu->FocusedItem == NO_SELECTED_ITEM)) return -1;
+	(MENU_GetLocalMenu(hMenu)->FocusedItem == NO_SELECTED_ITEM)) return -1;
 
-    item = &menu->items[menu->FocusedItem];
+    item = &menu->items[MENU_GetLocalMenu(hMenu)->FocusedItem];
 
     TRACE("%p %08x %p\n", hMenu, item->wID, item->hSubMenu);
 
@@ -2623,11 +2659,11 @@ static BOOL MENU_ButtonDown( MTRACKER* p
 	if( IS_SYSTEM_MENU(ptmenu) )
 	    item = ptmenu->items;
 	else
-	    item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
+	    item = MENU_FindItemByCoords( hPtMenu, pmt->pt, &id );
 
 	if( item )
 	{
-	    if( ptmenu->FocusedItem != id )
+	    if( MENU_GetLocalMenu(hPtMenu)->FocusedItem != id )
 		MENU_SwitchTracking( pmt, hPtMenu, id );
 
 	    /* If the popup menu is not already "popped" */
@@ -2666,9 +2702,9 @@ static INT MENU_ButtonUp( MTRACKER* pmt,
         if( IS_SYSTEM_MENU(ptmenu) )
             item = ptmenu->items;
         else
-            item = MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
+            item = MENU_FindItemByCoords( hPtMenu, pmt->pt, &id );
 
-	if( item && (ptmenu->FocusedItem == id ))
+	if( item && (MENU_GetLocalMenu(hPtMenu)->FocusedItem == id ))
 	{
 	    if( !(item->fType & MF_POPUP) )
 	    {
@@ -2679,11 +2715,10 @@ static INT MENU_ButtonUp( MTRACKER* pmt,
 	    /* If we are dealing with the top-level menu            */
 	    /* and this is a click on an already "popped" item:     */
 	    /* Stop the menu tracking and close the opened submenus */
-	    if((pmt->hTopMenu == hPtMenu) && ptmenu->bTimeToHide)
+	    if((pmt->hTopMenu == hPtMenu) && MENU_GetLocalMenu(hPtMenu)->bTimeToHide)
 		return 0;
 	}
-	ptmenu->bTimeToHide = TRUE;
-        MENU_UpdateMenu( hPtMenu, ptmenu, SET_MI_TIMETOHIDE );
+	MENU_GetLocalMenu(hPtMenu)->bTimeToHide = TRUE;
     }
     return -1;
 }
@@ -2706,7 +2741,7 @@ static BOOL MENU_MouseMove( MTRACKER* pm
         if( IS_SYSTEM_MENU(ptmenu) )
 	    id = 0;
         else
-            MENU_FindItemByCoords( ptmenu, pmt->pt, &id );
+            MENU_FindItemByCoords( hPtMenu, pmt->pt, &id );
     }
 
     if( id == NO_SELECTED_ITEM )
@@ -2715,7 +2750,7 @@ static BOOL MENU_MouseMove( MTRACKER* pm
 			 NO_SELECTED_ITEM, TRUE, pmt->hTopMenu);
 
     }
-    else if( ptmenu->FocusedItem != id )
+    else if( MENU_GetLocalMenu(hPtMenu)->FocusedItem != id )
     {
 	    MENU_SwitchTracking( pmt, hPtMenu, id );
 	    pmt->hCurrentMenu = MENU_ShowSubPopup(pmt->hOwnerWnd, hPtMenu, FALSE, wFlags);
@@ -2759,8 +2794,8 @@ static LRESULT MENU_DoNextMenu( MTRACKER
     POPUPMENU *menu = &tmpmenu;
     MENU_GetMenu( pmt->hTopMenu, menu );
 
-    if( (vk == VK_LEFT &&  menu->FocusedItem == 0 ) ||
-        (vk == VK_RIGHT && menu->FocusedItem == menu->nItems - 1))
+    if( (vk == VK_LEFT && MENU_GetLocalMenu(pmt->hTopMenu)->FocusedItem == 0 ) ||
+        (vk == VK_RIGHT && MENU_GetLocalMenu(pmt->hTopMenu)->FocusedItem == menu->nItems - 1))
     {
         MDINEXTMENU next_menu;
 	HMENU hNewMenu;
@@ -3238,10 +3273,10 @@ static BOOL MENU_TrackMenu( HMENU hmenu,
 			HELPINFO hi;
 			hi.cbSize = sizeof(HELPINFO);
 			hi.iContextType = HELPINFO_MENUITEM;
-			if (menu->FocusedItem == NO_SELECTED_ITEM)
+			if (MENU_GetLocalMenu(hmenu)->FocusedItem == NO_SELECTED_ITEM)
 			    hi.iCtrlId = 0;
 		        else
-			    hi.iCtrlId = menu->items[menu->FocusedItem].wID;
+			    hi.iCtrlId = menu->items[MENU_GetLocalMenu(hmenu)->FocusedItem].wID;
 			hi.hItemHandle = hmenu;
 			hi.dwContextId = menu->dwContextHelpID;
 			hi.MousePos = msg.pt;
@@ -3328,10 +3363,7 @@ static BOOL MENU_TrackMenu( HMENU hmenu,
 
         /* Reset the variable for hiding menu */
         if( !ret )
-        {
-            menu->bTimeToHide = FALSE;
-            MENU_UpdateMenu(mt.hTopMenu, menu, SET_MI_TIMETOHIDE);
-        }
+            MENU_GetLocalMenu(mt.hTopMenu)->bTimeToHide = FALSE;
     }
 
     /* The return value is only used by TrackPopupMenu */
@@ -3598,7 +3630,7 @@ UINT MENU_GetMenuBarHeight( HWND hwnd, U
     SelectObject( hdc, get_menu_font(FALSE));
     SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+GetSystemMetrics(SM_CYMENU));
     MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
-    MENU_UpdateMenu( GetMenu(hwnd), lppop, SET_MI_WIDTH|SET_MI_HEIGHT|SET_MI_MAXBMPSIZE|SET_MI_TOTALHEIGHT|SET_MI_SCROLLING);
+    MENU_UpdateMenu( GetMenu(hwnd), lppop, SET_MI_WIDTH|SET_MI_HEIGHT|SET_MI_MAXBMPSIZE|SET_MI_TOTALHEIGHT);
     ReleaseDC( hwnd, hdc );
     return lppop->Height;
 }
@@ -3770,7 +3802,7 @@ BOOL WINAPI HiliteMenuItem( HWND hWnd, H
     TRACE("(%p, %p, %04x, %04x);\n", hWnd, hMenu, wItemID, wHilite);
     if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE;
     if (MENU_GetMenu(hMenu, menu)) return FALSE;
-    if (menu->FocusedItem == wItemID) return TRUE;
+    if (MENU_GetLocalMenu(hMenu)->FocusedItem == wItemID) return TRUE;
     MENU_HideSubPopups( hWnd, hMenu, FALSE );
     MENU_SelectItem( hWnd, hMenu, wItemID, TRUE, 0 );
     return TRUE;
@@ -4021,8 +4053,8 @@ HMENU WINAPI CreatePopupMenu(void)
     if (!(hmenu = CreateMenu())) return 0;
     MENU_GetMenu(hmenu, menu);
     menu->wFlags |= MF_POPUP;
-    menu->bTimeToHide = FALSE;
-    MENU_UpdateMenu(hmenu, menu, SET_MI_FLAGS|SET_MI_TIMETOHIDE);
+    MENU_GetLocalMenu(hmenu)->bTimeToHide = FALSE;
+    MENU_UpdateMenu(hmenu, menu, SET_MI_FLAGS);
     return hmenu;
 }
 
@@ -4067,6 +4099,7 @@ BOOL WINAPI SetMenuItemBitmaps( HMENU hM
  */
 HMENU WINAPI CreateMenu(void)
 {
+    int index;
     HMENU hMenu = 0;
 
     SERVER_START_REQ( create_menu )
@@ -4076,6 +4109,12 @@ HMENU WINAPI CreateMenu(void)
     }
     SERVER_END_REQ;
 
+    index = USER_HANDLE_TO_INDEX(hMenu);
+    user_handles[index] = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                     sizeof(LOCALPOPUPMENU));
+    MENU_GetLocalMenu(hMenu)->FocusedItem = NO_SELECTED_ITEM;
+    MENU_GetLocalMenu(hMenu)->bTimeToHide = FALSE;
+
     TRACE("return %p\n", hMenu );
 
     return hMenu;
@@ -4087,6 +4126,7 @@ HMENU WINAPI CreateMenu(void)
  */
 BOOL WINAPI DestroyMenu( HMENU hMenu )
 {
+    int index;
     POPUPMENU tmppop;
     LPPOPUPMENU lppop = &tmppop;
 
@@ -4123,6 +4163,11 @@ BOOL WINAPI DestroyMenu( HMENU hMenu )
         }
     }
     SERVER_END_REQ;
+
+    index = USER_HANDLE_TO_INDEX(hMenu);
+    HeapFree( GetProcessHeap(), 0, user_handles[index]);
+    user_handles[index] = NULL;
+
     return TRUE;
 }
 
@@ -5184,7 +5229,7 @@ INT WINAPI MenuItemFromPoint(HWND hWnd, 
 
     /*FIXME: Do we have to handle hWnd here? */
     if (MENU_GetMenu(hMenu, menu)) return -1;
-    if (!MENU_FindItemByCoords(menu, ptScreen, &pos)) return -1;
+    if (!MENU_FindItemByCoords(hMenu, ptScreen, &pos)) return -1;
     return pos;
 }
 
diff --git a/dlls/user/user_private.h b/dlls/user/user_private.h
index ffb2796..906edb1 100644
--- a/dlls/user/user_private.h
+++ b/dlls/user/user_private.h
@@ -28,6 +28,7 @@ #include "wingdi.h"
 #include "winuser.h"
 #include "winreg.h"
 #include "winternl.h"
+#include "wine/server.h"
 #include "wine/windef16.h"
 #include "wine/winbase16.h"
 
@@ -280,4 +281,8 @@ #include "poppack.h"
 
 extern void CURSORICON_FreeModuleIcons( HMODULE16 hModule );
 
+#define NB_USER_HANDLES  ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
+#define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
+extern void *user_handles[NB_USER_HANDLES];
+
 #endif /* __WINE_USER_PRIVATE_H */
diff --git a/dlls/user/win.c b/dlls/user/win.c
index fa2af00..6d26ffc 100644
--- a/dlls/user/win.c
+++ b/dlls/user/win.c
@@ -41,13 +41,10 @@ #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(win);
 
-#define NB_USER_HANDLES  ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
-#define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
-
 /**********************************************************************/
 
 
-static void *user_handles[NB_USER_HANDLES];
+void *user_handles[NB_USER_HANDLES];
 
 /***********************************************************************
  *           create_window_handle
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index c34a34f..829ebf1 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -32,7 +32,7 @@ struct reply_header
 
 struct request_max_size
 {
-    int pad[25];
+    int pad[21];
 };
 
 typedef void *obj_handle_t;
@@ -3514,11 +3514,7 @@ struct get_menu_info_reply
     unsigned int nitems;
     user_handle_t hwnd;
     void* items;
-    unsigned int focuseditem;
     user_handle_t hwndowner;
-    unsigned short timetohide;
-    unsigned short scrolling;
-    unsigned int scrollpos;
     unsigned int totalheight;
 
     unsigned long style;
@@ -3544,11 +3540,7 @@ struct set_menu_info_request
     unsigned int nitems;
     user_handle_t hwnd;
     void* items;
-    unsigned int focuseditem;
     user_handle_t hwndowner;
-    unsigned short timetohide;
-    unsigned short scrolling;
-    unsigned int scrollpos;
     unsigned int totalheight;
 
     unsigned long style;
@@ -3590,16 +3582,12 @@ #define SET_MI_FLAGS       0x80000000
 #define SET_MI_HWND        0x40000000
 #define SET_MI_SYSMENU     0x20000000
 #define SET_MI_OWNER       0x10000000
-#define SET_MI_FOCUSITEM   0x08000000
-#define SET_MI_TIMETOHIDE  0x04000000
-#define SET_MI_WIDTH       0x02000000
-#define SET_MI_HEIGHT      0x01000000
-#define SET_MI_SCROLLING   0x00800000
-#define SET_MI_SCROLLPOS   0x00400000
-#define SET_MI_TOTALHEIGHT 0x00200000
-#define SET_MI_MAXBMPSIZE  0x00100000
-#define SET_MI_ITEMS       0x00080000
-#define SET_MI_NITEMS      0x00040000
+#define SET_MI_WIDTH       0x08000000
+#define SET_MI_HEIGHT      0x04000000
+#define SET_MI_TOTALHEIGHT 0x02000000
+#define SET_MI_MAXBMPSIZE  0x01000000
+#define SET_MI_ITEMS       0x00800000
+#define SET_MI_NITEMS      0x00400000
 
 
 struct adjust_token_privileges_request
@@ -4504,6 +4492,6 @@ union generic_reply
     struct query_symlink_reply query_symlink_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 238
+#define SERVER_PROTOCOL_VERSION 239
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/menu.c b/server/menu.c
index ec4d403..9a49a62 100644
--- a/server/menu.c
+++ b/server/menu.c
@@ -47,12 +47,7 @@ struct menu {
     unsigned int nitems;       /* Number of items in the menu */
     user_handle_t hwnd;        /* Window containing the menu */
     void *items;               /* Array of menu items */
-    unsigned int focuseditem;  /* Currently focused item */
     user_handle_t hwndowner;   /* window receiving the messages for ownerdraw */
-    unsigned short timetohide; /* Request hiding when receiving a second
-                                  click in the top-level menu item */
-    unsigned short scrolling;  /* Scroll arrows are active */
-    unsigned int scrollpos;    /* Current scroll position */
     unsigned int totalheight;  /* Total height of menu items inside menu */
 
     unsigned long style;         /* Extended menu style */
@@ -115,11 +110,7 @@ DECL_HANDLER(create_menu)
     reply->handle = 0;
 
     if ((menu = create_menu()))
-    {
-        menu->focuseditem = NO_SELECTED_ITEM;
-        menu->timetohide = FALSE;
         reply->handle = menu->handle;
-    }
 }
 
 
@@ -147,11 +138,7 @@ DECL_HANDLER(get_menu_info)
     reply->nitems = menu->nitems;
     reply->hwnd = menu->hwnd;
     reply->items = menu->items;
-    reply->focuseditem = menu->focuseditem;
     reply->hwndowner = menu->hwndowner;
-    reply->timetohide = menu->timetohide;
-    reply->scrolling = menu->scrolling;
-    reply->scrollpos = menu->scrollpos;
     reply->totalheight = menu->totalheight;
 
     reply->style = menu->style;
@@ -178,11 +165,7 @@ DECL_HANDLER(set_menu_info)
     if (req->mask & SET_MI_NITEMS) menu->nitems = req->nitems;
     if (req->mask & SET_MI_HWND) menu->hwnd = req->hwnd;
     if (req->mask & SET_MI_ITEMS) menu->items = req->items;
-    if (req->mask & SET_MI_FOCUSITEM) menu->focuseditem = req->focuseditem;
     if (req->mask & SET_MI_OWNER) menu->hwndowner = req->hwndowner;
-    if (req->mask & SET_MI_TIMETOHIDE) menu->timetohide = req->timetohide;
-    if (req->mask & SET_MI_SCROLLING) menu->scrolling = req->scrolling;
-    if (req->mask & SET_MI_SCROLLPOS) menu->scrollpos = req->scrollpos;
     if (req->mask & SET_MI_TOTALHEIGHT) menu->totalheight = req->totalheight;
 
     if (req->mask & MIM_STYLE) menu->style = req->style;
diff --git a/server/protocol.def b/server/protocol.def
index 5a3a36d..7b3fa42 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -48,7 +48,7 @@ struct reply_header
 /* this is used to construct the generic_request union */
 struct request_max_size
 {
-    int pad[25]; /* the max request size is 25 ints */
+    int pad[21]; /* the max request size is 21 ints */
 };
 
 typedef void *obj_handle_t;
@@ -2474,11 +2474,7 @@ #define SET_GLOBAL_TASKMAN_WINDOW  0x04
     unsigned int nitems;
     user_handle_t hwnd;
     void* items;
-    unsigned int focuseditem;
     user_handle_t hwndowner;
-    unsigned short timetohide;
-    unsigned short scrolling;
-    unsigned int scrollpos;
     unsigned int totalheight;
 
     unsigned long style;
@@ -2502,11 +2498,7 @@ #define SET_GLOBAL_TASKMAN_WINDOW  0x04
     unsigned int nitems;
     user_handle_t hwnd;
     void* items;
-    unsigned int focuseditem;
     user_handle_t hwndowner;
-    unsigned short timetohide;
-    unsigned short scrolling;
-    unsigned int scrollpos;
     unsigned int totalheight;
 
     unsigned long style;
@@ -2535,16 +2527,12 @@ #define SET_MI_FLAGS       0x80000000
 #define SET_MI_HWND        0x40000000
 #define SET_MI_SYSMENU     0x20000000
 #define SET_MI_OWNER       0x10000000
-#define SET_MI_FOCUSITEM   0x08000000
-#define SET_MI_TIMETOHIDE  0x04000000
-#define SET_MI_WIDTH       0x02000000
-#define SET_MI_HEIGHT      0x01000000
-#define SET_MI_SCROLLING   0x00800000
-#define SET_MI_SCROLLPOS   0x00400000
-#define SET_MI_TOTALHEIGHT 0x00200000
-#define SET_MI_MAXBMPSIZE  0x00100000
-#define SET_MI_ITEMS       0x00080000
-#define SET_MI_NITEMS      0x00040000
+#define SET_MI_WIDTH       0x08000000
+#define SET_MI_HEIGHT      0x04000000
+#define SET_MI_TOTALHEIGHT 0x02000000
+#define SET_MI_MAXBMPSIZE  0x01000000
+#define SET_MI_ITEMS       0x00800000
+#define SET_MI_NITEMS      0x00400000
 
 /* Adjust the privileges held by a token */
 @REQ(adjust_token_privileges)
diff --git a/server/trace.c b/server/trace.c
index e98026c..4a05044 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3063,11 +3063,7 @@ static void dump_get_menu_info_reply( co
     fprintf( stderr, " nitems=%08x,", req->nitems );
     fprintf( stderr, " hwnd=%p,", req->hwnd );
     fprintf( stderr, " items=%p,", req->items );
-    fprintf( stderr, " focuseditem=%08x,", req->focuseditem );
     fprintf( stderr, " hwndowner=%p,", req->hwndowner );
-    fprintf( stderr, " timetohide=%04x,", req->timetohide );
-    fprintf( stderr, " scrolling=%04x,", req->scrolling );
-    fprintf( stderr, " scrollpos=%08x,", req->scrollpos );
     fprintf( stderr, " totalheight=%08x,", req->totalheight );
     fprintf( stderr, " style=%lx,", req->style );
     fprintf( stderr, " cymax=%08x,", req->cymax );
@@ -3090,11 +3086,7 @@ static void dump_set_menu_info_request( 
     fprintf( stderr, " nitems=%08x,", req->nitems );
     fprintf( stderr, " hwnd=%p,", req->hwnd );
     fprintf( stderr, " items=%p,", req->items );
-    fprintf( stderr, " focuseditem=%08x,", req->focuseditem );
     fprintf( stderr, " hwndowner=%p,", req->hwndowner );
-    fprintf( stderr, " timetohide=%04x,", req->timetohide );
-    fprintf( stderr, " scrolling=%04x,", req->scrolling );
-    fprintf( stderr, " scrollpos=%08x,", req->scrollpos );
     fprintf( stderr, " totalheight=%08x,", req->totalheight );
     fprintf( stderr, " style=%lx,", req->style );
     fprintf( stderr, " cymax=%08x,", req->cymax );

