Index: src/kits/interface/MenuField.cpp
===================================================================
--- src/kits/interface/MenuField.cpp	(revisione 22965)
+++ src/kits/interface/MenuField.cpp	(copia locale)
@@ -8,6 +8,7 @@
  *		Ingo Weinhold <bonefish@cs.tu-berlin.de>
  */
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -296,9 +297,11 @@
 void
 BMenuField::MouseDown(BPoint where)
 {
+	printf("BMenuField::MouseDown()\n");
 	if (!fMenuBar->Frame().Contains(where))
 		return;
 
+	printf("Inside menubar's frame\n");
 	BRect bounds = fMenuBar->ConvertFromParent(Bounds());
 
 	fMenuBar->StartMenuBar(0, false, true, &bounds);
Index: src/kits/interface/PopUpMenu.cpp
===================================================================
--- src/kits/interface/PopUpMenu.cpp	(revisione 22960)
+++ src/kits/interface/PopUpMenu.cpp	(copia locale)
@@ -16,6 +16,7 @@
 
 #include <new>
 
+#include <stdio.h>
 
 struct popup_menu_data {
 	BPopUpMenu *object;
@@ -110,21 +111,21 @@
 void
 BPopUpMenu::MouseDown(BPoint point)
 {
-	BView::MouseDown(point);
+	BMenu::MouseDown(point);
 }
 
 
 void
 BPopUpMenu::MouseUp(BPoint point)
 {
-	BView::MouseUp(point);
+	BMenu::MouseUp(point);
 }
 
 
 void
 BPopUpMenu::MouseMoved(BPoint point, uint32 code, const BMessage *msg)
 {
-	BView::MouseMoved(point, code, msg);
+	BMenu::MouseMoved(point, code, msg);
 }
 
 
@@ -388,7 +389,7 @@
 			window->UpdateIfNeeded();
 	}
 
- 	status_t unused;
+	status_t unused;
 	while (wait_for_thread(fTrackThread, &unused) == B_INTERRUPTED)
 		;
 	
Index: src/kits/interface/BMCPrivate.cpp
===================================================================
--- src/kits/interface/BMCPrivate.cpp	(revisione 22964)
+++ src/kits/interface/BMCPrivate.cpp	(copia locale)
@@ -35,15 +35,17 @@
 filter_result
 _BMCFilter_::Filter(BMessage *message, BHandler **handler)
 {
-	if (message->what == B_MOUSE_DOWN) {
+	/*if (message->what == B_MOUSE_DOWN) {
 		if (BView *view = dynamic_cast<BView *>(*handler)) {
 			BPoint point;
 			message->FindPoint("be:view_where", &point);
-			view->ConvertToParent(&point);
-			message->ReplacePoint("be:view_where", point);
-			*handler = fMenuField;
+			if (view->Bounds().Contains(point)) {			
+				view->ConvertToParent(&point);
+				message->ReplacePoint("be:view_where", point);
+				*handler = fMenuField;
+			}		
 		}
-	}
+	}*/
 
 	return B_DISPATCH_MESSAGE;
 }
@@ -228,6 +230,42 @@
 
 
 void
+_BMCMenuBar_::MouseDown(BPoint where)
+{
+	thread_info info;
+	if (fMenuField->fMenuTaskID >= 0
+		&& get_thread_info(fMenuField->fMenuTaskID, &info) == B_OK
+		&& !Bounds().Contains(where)) {
+		BMenu::MouseDown(where);
+ 	} else if (Bounds().Contains(where)) {
+		BPoint point = where;
+		ConvertToParent(&point);		
+		fMenuField->MouseDown(point);
+	}	
+}
+
+
+void
+_BMCMenuBar_::MouseUp(BPoint where)
+{
+	if (!Bounds().Contains(where))
+		BMenu::MouseUp(where);
+}
+
+
+void
+_BMCMenuBar_::MouseMoved(BPoint where, uint32 code, const BMessage *message)
+{
+	printf("BMC MouseMoved\n");
+	// Eat the first mousemoved event	
+	/*if (!fMoved)
+		fMoved = true;	
+	else
+		BMenuBar::MouseMoved(where, code, message);*/
+}
+
+
+void
 _BMCMenuBar_::FrameResized(float width, float height)
 {
 	// we need to take care of resizing and cleaning up
Index: src/kits/interface/Menu.cpp
===================================================================
--- src/kits/interface/Menu.cpp	(revisione 22963)
+++ src/kits/interface/Menu.cpp	(copia locale)
@@ -4,13 +4,16 @@
  *
  * Authors:
  *		Marc Flerackers (mflerackers@androme.be)
- *		Stefano Ceccherini (burton666@libero.it)
+ *		Stefano Ceccherini (stefano.ceccherini@gmail.com)
  */
 
 #include <new>
 #include <ctype.h>
 #include <string.h>
 
+#define DEBUG 1
+
+#include <Application.h>
 #include <Debug.h>
 #include <File.h>
 #include <FindDirectory.h>
@@ -183,12 +186,13 @@
 	fAscent(-1.0f),
 	fDescent(-1.0f),
 	fFontHeight(-1.0f),
-	fState(0),
+	fTrackingMenu(NULL),
 	fLayout(layout),
 	fExtraRect(NULL),
 	fMaxContentWidth(0.0f),
 	fInitMatrixSize(NULL),
 	fExtraMenuData(NULL),
+	fTrackData(NULL),
 	fTrigger(0),
 	fResizeToFit(true),
 	fUseCachedMenuLayout(false),
@@ -216,12 +220,13 @@
 	fAscent(-1.0f),
 	fDescent(-1.0f),
 	fFontHeight(-1.0f),
-	fState(0),
+	fTrackingMenu(NULL),
 	fLayout(B_ITEMS_IN_MATRIX),
 	fExtraRect(NULL),
 	fMaxContentWidth(0.0f),
 	fInitMatrixSize(NULL),
 	fExtraMenuData(NULL),
+	fTrackData(NULL),
 	fTrigger(0),
 	fResizeToFit(true),
 	fUseCachedMenuLayout(false),
@@ -248,6 +253,7 @@
 	delete fInitMatrixSize;
 	delete fExtraMenuData;
 	delete fLayoutData;
+	delete fTrackData;
 }
 
 
@@ -262,12 +268,13 @@
 	fAscent(-1.0f),
 	fDescent(-1.0f),
 	fFontHeight(-1.0f),
-	fState(0),
+	fTrackingMenu(NULL),
 	fLayout(B_ITEMS_IN_ROW),
 	fExtraRect(NULL),
 	fMaxContentWidth(0.0f),
 	fInitMatrixSize(NULL),
 	fExtraMenuData(NULL),
+	fTrackData(NULL),
 	fTrigger(0),
 	fResizeToFit(true),
 	fUseCachedMenuLayout(false),
@@ -285,7 +292,7 @@
 }
 
 
-BArchivable*
+BArchivable *
 BMenu::Instantiate(BMessage* archive)
 {
 	if (validate_instantiation(archive, "BMenu"))
@@ -877,6 +884,71 @@
 }
 
 
+void
+BMenu::MouseDown(BPoint where)
+{
+	PRINT(("%s MouseDown()\n", Name()));
+	if (!Bounds().Contains(where)) {
+		// The only case where this can happen is in the tracking menu,
+		// as it's the only one with an event mask set to receive
+		// mouse events outside its bounds.			
+		ASSERT(fTrackingMenu == this);	
+		if (fTrackData && !fTrackData->InsideMenu())
+			_StopTracking();
+	}
+}
+
+
+void
+BMenu::MouseUp(BPoint where)
+{
+	PRINT(("%s MouseUp(). fTrackingMenu = %p\n", Name(), fTrackingMenu));
+	if (fTrackingMenu == NULL)
+		return;
+
+	if (_CustomTrackingWantsToQuit()) {
+		fTrackingMenu->_StopTracking();
+		return;	
+	}
+
+	BRect *extraRect = fExtraRect;
+	fExtraRect = NULL;
+	
+	if (extraRect != NULL && extraRect->Contains(where)) {
+		printf("BMenu Inside the extra rect\n");
+		//fTrackingMenu->_SetStickyMode(true);
+		return;
+	}
+	
+	// Either we are inside our own bounds, or we are the tracking menu.
+	// In both cases, we need to stop tracking.
+	if (Bounds().Contains(where)
+		|| (fTrackData && !fTrackData->InsideMenu()))	
+		fTrackingMenu->_StopTracking(fSelected);
+}
+
+
+void
+BMenu::MouseMoved(BPoint where, uint32 code, const BMessage* message)
+{
+	PRINT(("%s MouseMoved (code: %ld)\n", Name(), code));
+	if (fTrackingMenu != NULL && fTrackingMenu != this) {		
+		ASSERT(fTrackingMenu->fTrackData != NULL);
+		if (code == B_ENTERED_VIEW)
+			fTrackingMenu->fTrackData->SetInsideMenu(true);
+		else if (code == B_EXITED_VIEW)
+			fTrackingMenu->fTrackData->SetInsideMenu(false);
+	}
+	
+	BMenuItem *item = _HitTestItems(where);
+	if (item != NULL)
+		_SelectItem(item);
+	
+	if (fTrackingMenu != NULL && _CustomTrackingWantsToQuit())
+		fTrackingMenu->_StopTracking();
+}
+
+
 BSize
 BMenu::MinSize()
 {
@@ -1080,12 +1152,13 @@
 	fAscent(-1.0f),
 	fDescent(-1.0f),
 	fFontHeight(-1.0f),
-	fState(0),
+	fTrackingMenu(NULL),
 	fLayout(layout),
 	fExtraRect(NULL),
 	fMaxContentWidth(0.0f),
 	fInitMatrixSize(NULL),
 	fExtraMenuData(NULL),
+	fTrackData(NULL),
 	fTrigger(0),
 	fResizeToFit(resizeToFit),
 	fUseCachedMenuLayout(false),
@@ -1251,7 +1324,7 @@
 		archive->FindFloat("_maxwidth", &fMaxContentWidth);
 
 		BMessage msg;
-       	for (int32 i = 0; archive->FindMessage("_items", i, &msg) == B_OK; i++) {
+		for (int32 i = 0; archive->FindMessage("_items", i, &msg) == B_OK; i++) {
 			BArchivable *object = instantiate_object(&msg);
 			if (BMenuItem *item = dynamic_cast<BMenuItem *>(object)) {
 				BRect bounds;
@@ -1284,7 +1357,7 @@
 	if (window == NULL) {
 		// Menu windows get the BMenu's handler name
 		window = new (nothrow) BMenuWindow(Name());
-		ourWindow = true;
+			ourWindow = true;
 	}
 
 	if (window == NULL)
@@ -1313,7 +1386,8 @@
 
 		_UpdateWindowViewSize(true);
 		window->Show();
-
+		window->Activate();
+		
 		if (selectFirstItem)
 			_SelectItem(ItemAt(0));
 
@@ -1354,167 +1428,59 @@
 
 
 BMenuItem *
-BMenu::_Track(int *action, long start)
+BMenu::_Track(int *action, long startIndex)
 {
-	// TODO: cleanup
-	BMenuItem *item = NULL;
-	bigtime_t openTime = system_time();
-	bigtime_t closeTime = 0;
+	PRINT(("%s _Track()\n", Name()));
 
-	fState = MENU_STATE_TRACKING;
-	if (fSuper != NULL)
-		fSuper->fState = MENU_STATE_TRACKING_SUBMENU;
+	fTrackData = new (std::nothrow) BPrivate::TrackData();
+	if (fTrackData == NULL)
+		return NULL;
 
-	while (true) {
-		if (_CustomTrackingWantsToQuit())
-			break;
+	fTrackingMenu = this;
+	fChosenItem = NULL;
 
-		bool locked = LockLooper();
-		if (!locked)
-			break;
-
-		bigtime_t snoozeAmount = 50000;
-		BPoint location;
-		uint32 buttons;
-		GetMouse(&location, &buttons, true);
-
-		BMenuWindow *window = static_cast<BMenuWindow *>(Window());
-
-		BPoint screenLocation = ConvertToScreen(location);
-		if (window->CheckForScrolling(screenLocation)) {
-			item = NULL;
-		} else {
-			item = _HitTestItems(location, B_ORIGIN);
-			if (item != NULL)
-				_UpdateStateOpenSelect(item, openTime, closeTime);
-		}
-
-		// Track the submenu
-		if (_OverSubmenu(fSelected, screenLocation)) {
-			UnlockLooper();
-			locked = false;
-			int submenuAction = MENU_STATE_TRACKING;
-			BMenu *submenu = fSelected->Submenu();
-			bool wasSticky = _IsStickyMode();
-			if (wasSticky)
-				submenu->_SetStickyMode(true);
-			BMenuItem *submenuItem = submenu->_Track(&submenuAction);
-
-			// check if the user started holding down a mouse button in a submenu
-			if (wasSticky && !_IsStickyMode()) {
-				buttons = 1;
-					// buttons must have been pressed in the meantime
-			}
-
-			if (submenuAction == MENU_STATE_CLOSED) {
-				item = submenuItem;
-				fState = submenuAction;
-				break;
-			}
-
-			locked = LockLooper();
-			if (!locked)
-				break;
-		} else if (item == NULL) {
-			if (_OverSuper(screenLocation)) {
-				fState = MENU_STATE_TRACKING;
-				UnlockLooper();
-				break;
-			}
-
-			if (!_OverSubmenu(fSelected, screenLocation)
-				&& system_time() > closeTime + kHysteresis
-				&& fState != MENU_STATE_TRACKING_SUBMENU) {
-				_SelectItem(NULL);
-				fState = MENU_STATE_TRACKING;
-			}
-
-			if (fSuper != NULL) {
-				// Give supermenu the chance to continue tracking
-				*action = fState;
-				if (locked)
-					UnlockLooper();
-
-				return NULL;
-			}
-		}
-
-		if (locked)
-			UnlockLooper();
-
-		_UpdateStateClose(item, location, buttons);
-
-		if (fState == MENU_STATE_CLOSED)
-			break;
-
-		snooze(snoozeAmount);
-	}
-
-	if (action != NULL)
-		*action = fState;
-
-	if (fSelected != NULL && LockLooper()) {
-		_SelectItem(NULL);
+	if (startIndex != -1)
+		be_app->ObscureCursor();
+	if (LockLooper()) {
+		if (startIndex != -1)
+			_SelectItem(ItemAt(startIndex), true, true);
+		SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);	
 		UnlockLooper();
-	}
+	}	
+	
+	fTrackData->Block();
+		// Will be released from another thread
 
-	if (_IsStickyMode())
-		_SetStickyMode(false);
+	_Hide();
 
-	// delete the menu window recycled for all the child menus
-	_DeleteMenuWindow();
+	delete fTrackData;
+	fTrackData = NULL;
+	fTrackingMenu = NULL;
 
-	return item;
+	PRINT(("%s _Track exits\n", Name()));
+	return fChosenItem;
 }
 
 
 void
-BMenu::_UpdateStateOpenSelect(BMenuItem* item, bigtime_t& openTime,
-	bigtime_t& closeTime)
+BMenu::_StopTracking(BMenuItem *chosen)
 {
-	if (fState == MENU_STATE_CLOSED)
+	// TODO: Added mostly for debugging reasons.
+	// We might want to be less strict, and just
+	// call _StopTracking on the correct menu ourselves	
+	if (fTrackingMenu == NULL || fTrackingMenu != this)
 		return;
 
-	if (item != fSelected && system_time() > closeTime + kHysteresis) {
-		_SelectItem(item, false);
-		openTime = system_time();
-	} else if (system_time() > kHysteresis + openTime && item->Submenu() != NULL
-		&& item->Submenu()->Window() == NULL) {
-		// Open the submenu if it's not opened yet, but only if
-		// the mouse pointer stayed over there for some time
-		// (hysteresis)
-		_SelectItem(item);
-		closeTime = system_time();
+	
+	fChosenItem = chosen;
+	
+	if (LockLooper()) {	
+		SetEventMask(0, 0);
+		UnlockLooper();
 	}
-	if (fState != MENU_STATE_TRACKING)
-		fState = MENU_STATE_TRACKING;
-}
 
-
-void
-BMenu::_UpdateStateClose(BMenuItem* item, const BPoint& where,
-	const uint32& buttons)
-{
-	if (fState == MENU_STATE_CLOSED)
-		return;
-
-	if (buttons != 0 && _IsStickyMode()) {
-		if (item == NULL)
-			fState = MENU_STATE_CLOSED;
-		else {
-			BMenu *supermenu = Supermenu();
-			for(; supermenu; supermenu = supermenu->Supermenu())
-				supermenu->_SetStickyMode(false);
-			_SetStickyMode(false);
-		}
-	} else if (buttons == 0 && !_IsStickyMode()) {
-		if (fExtraRect != NULL && fExtraRect->Contains(where)) {
-			_SetStickyMode(true);
-			fExtraRect = NULL;
-				// This code should be executed only once
-		} else
-			fState = MENU_STATE_CLOSED;
-	}
+	if (fTrackData)
+		fTrackData->Release();
 }
 
 
@@ -1920,13 +1886,7 @@
 int
 BMenu::State(BMenuItem **item) const
 {
-	if (fState == MENU_STATE_TRACKING || fState == MENU_STATE_CLOSED)
-		return fState;
-
-	if (fSelected != NULL && fSelected->Submenu() != NULL)
-		return fSelected->Submenu()->State(item);
-
-	return fState;
+	return 0;
 }
 
 
@@ -1991,7 +1951,7 @@
 	if (fCachedMenuWindow == NULL) {
 		char windowName[64];
 		snprintf(windowName, 64, "%s cached menu", Name());
-		fCachedMenuWindow = new (nothrow) BMenuWindow(windowName);
+		fCachedMenuWindow = new (std::nothrow) BMenuWindow(windowName);
 	}
 
 	return fCachedMenuWindow;
@@ -2089,7 +2049,7 @@
 		if (fSelected != NULL) {
 			fSelected->Select(false);
 			BMenu *subMenu = fSelected->Submenu();
-			if (subMenu != NULL && subMenu->Window() != NULL)
+			if (subMenu != NULL)
 				subMenu->_Hide();
 		}
 
@@ -2101,7 +2061,9 @@
 	if (fSelected != NULL && showSubmenu) {
 		BMenu *subMenu = fSelected->Submenu();
 		if (subMenu != NULL && subMenu->Window() == NULL) {
-			if (!subMenu->_Show(selectFirstItem)) {
+			if (subMenu->_Show(selectFirstItem)) {
+				subMenu->fTrackingMenu = fTrackingMenu;
+			} else {
 				// something went wrong, deselect the item
 				fSelected->Select(false);
 				fSelected = NULL;
@@ -2158,13 +2120,13 @@
 {
 	if (fStickyMode != on) {
 		// TODO: Ugly hack, but it needs to be done right here in this method
-		BMenuBar *menuBar = dynamic_cast<BMenuBar *>(this);
+		/*BMenuBar *menuBar = dynamic_cast<BMenuBar *>(this);
 		if (on && menuBar != NULL && menuBar->LockLooper()) {
 			// Steal the focus from the current focus view
 			// (needed to handle keyboard navigation)
 			menuBar->_StealFocus();
 			menuBar->UnlockLooper();
-		}
+		}*/
 
 		fStickyMode = on;
 	}
@@ -2335,10 +2297,59 @@
 		menuBar->_RestoreFocus();
 
 	fChosenItem = NULL;
-	fState = MENU_STATE_CLOSED;
 }
 
 
+// TrackData
+namespace BPrivate {
+
+TrackData::TrackData()
+{
+	fQuitSem = create_sem(0, "PSYCHO menu quit sem");
+	fInside = 0;	
+}
+
+
+TrackData::~TrackData()
+{
+	Release();
+}
+
+
+void
+TrackData::SetInsideMenu(bool inside)
+{
+	int32 value = inside ? 1 : -1;
+	atomic_add(&fInside, value);
+}
+
+
+bool
+TrackData::InsideMenu() const
+{
+	return fInside > 0;
+}
+
+
+void
+TrackData::Block()
+{	
+	while (acquire_sem(fQuitSem) == B_INTERRUPTED)
+		;
+}
+
+
+void
+TrackData::Release()
+{
+	if (fQuitSem >= 0) {
+		delete_sem(fQuitSem);
+		fQuitSem = -1;		
+	}	
+}
+
+};
+
 //	#pragma mark -
 
 
Index: src/kits/interface/Window.cpp
===================================================================
--- src/kits/interface/Window.cpp	(revisione 22960)
+++ src/kits/interface/Window.cpp	(copia locale)
@@ -1041,12 +1041,12 @@
 			
 			// Close an eventually opened menu, if this click targets the
 			// preferred handler, and unless the target is the menu itself
-			BMenu *menu = dynamic_cast<BMenu *>(fFocus);
+			/*BMenu *menu = dynamic_cast<BMenu *>(fFocus);
 			if (menu != NULL && menu != view && PreferredHandler() == target
 				&& menu->State() != MENU_STATE_CLOSED) {
 				menu->QuitTracking();
 				return;			
-			}
+			}*/
 			
 			if (view != NULL) {
 				BPoint where;
Index: src/kits/interface/MenuBar.cpp
===================================================================
--- src/kits/interface/MenuBar.cpp	(revisione 22960)
+++ src/kits/interface/MenuBar.cpp	(copia locale)
@@ -202,30 +202,68 @@
 void 
 BMenuBar::MouseDown(BPoint where)
 {
-	if (fTracking)
-		return;
+	if (!fTracking) {	
+		BWindow *window = Window();
+		if (!window->IsActive() || !window->IsFront()) {
+			window->Activate();
+			window->UpdateIfNeeded();
+		}
+	
+		StartMenuBar(-1, false, false);
 
-	BWindow *window = Window();
-	if (!window->IsActive() || !window->IsFront()) {
-		window->Activate();
-		window->UpdateIfNeeded();
+	} else if (!Bounds().Contains(where)) {
+		if (fTrackData && !fTrackData->InsideMenu())		
+			_StopTracking();
+		return;
 	}
-	
-	StartMenuBar(-1, false, false);
+
+	MouseMoved(where, B_INSIDE_VIEW, NULL);	
 }
 
 
 void 
-BMenuBar::WindowActivated(bool state)
+BMenuBar::MouseUp(BPoint where)
 {
-	BView::WindowActivated(state);
+	if (fTracking) {
+		BRect *extraRect = fExtraRect;
+		fExtraRect = NULL;
+		if (extraRect != NULL && extraRect->Contains(where)) {
+			printf("Inside the extra rect\n");		
+			// do nothing.
+		} else if ((fTrackData && !fTrackData->InsideMenu())
+			&& (!Bounds().Contains(where)
+			|| (fSelected == NULL || fSelected->Submenu() == NULL))) {
+			// If mouse was released outside the menubar,
+			// or inside in a zone where there are no items,
+			// or on an item which doesn't have a submenu
+			// (cf. Menu preflet), stop tracking.
+			_StopTracking(fSelected);
+		}
+	} else
+		BView::MouseUp(where);
 }
 
 
+void
+BMenuBar::MouseMoved(BPoint where, uint32 code, const BMessage* message)
+{
+	BMessage *currentMessage = Window()->CurrentMessage();
+	int32 buttons = 0;
+	currentMessage->FindInt32("buttons", &buttons);
+	
+	if (fTracking && buttons != 0) {
+		BMenuItem *item = _HitTestItems(where);
+		if (item != NULL)
+			_SelectItem(item);
+	} else
+		BView::MouseMoved(where, code, message);
+}
+
+
 void 
-BMenuBar::MouseUp(BPoint where)
+BMenuBar::WindowActivated(bool state)
 {
-	BView::MouseUp(where);
+	BView::WindowActivated(state);
 }
 
 
@@ -384,9 +422,9 @@
 	
 	fPrevFocusToken = -1;
 	fTracking = true;
-		
+
 	window->MenusBeginning();
-	
+
 	fMenuSem = create_sem(0, "window close sem");
 	_set_menu_sem_(window, fMenuSem);
 	
@@ -459,148 +497,19 @@
 
 BMenuItem *
 BMenuBar::_Track(int32 *action, int32 startIndex, bool showMenu)
-{	
-	// TODO: Cleanup, merge some "if" blocks if possible
-	fChosenItem = NULL;
+{
+	BMenuItem *item = BMenu::_Track((int*)action, (int)startIndex);
 	
 	BWindow *window = Window();
-	fState = MENU_STATE_TRACKING;
-
-	if (startIndex != -1) {
-		be_app->ObscureCursor();
-		if (window->Lock()) {
-			_SelectItem(ItemAt(startIndex), true, true);
-			window->Unlock();
-		}
-	}
-
-	while (true) {
-		bigtime_t snoozeAmount = 40000;
-		bool locked = (Window() != NULL && window->Lock());//WithTimeout(200000)
-		if (!locked)
-			break;
-
-		BPoint where;
-		uint32 buttons;
-		GetMouse(&where, &buttons, true);
-
-		BMenuItem *menuItem = _HitTestItems(where, B_ORIGIN);
-		if (menuItem != NULL) {
-			// Select item if:
-			// - no previous selection
-			// - nonsticky mode and different selection,
-			// - clicked in sticky mode
-			if (fSelected == NULL
-				|| (!_IsStickyMode() && menuItem != fSelected)
-				|| (buttons != 0 && _IsStickyMode())) {
-				if (menuItem->Submenu() != NULL) {
-					if (menuItem->Submenu()->Window() == NULL) {
-						// open the menu if it's not opened yet
-						_SelectItem(menuItem);
-						if (_IsStickyMode())
-							_SetStickyMode(false);
-					} else {
-						// Menu was already opened, close it and bail
-						_SelectItem(NULL);
-						fState = MENU_STATE_CLOSED;
-						fChosenItem = NULL;
-					}
-				} else {
-					// No submenu, just select the item
-					_SelectItem(menuItem);					
-				}
-			}
-		}
-
-		if (_OverSubmenu(fSelected, ConvertToScreen(where))) {
-			// call _Track() from the selected sub-menu when the mouse cursor
-			// is over its window
-			BMenu *menu = fSelected->Submenu();
-			window->Unlock();
-			locked = false;
-			snoozeAmount = 30000;
-			bool wasSticky = _IsStickyMode();
-			if (wasSticky)
-				menu->_SetStickyMode(true);
-			int localAction;
-			fChosenItem = menu->_Track(&localAction);
-			if (menu->State(NULL) == MENU_STATE_TRACKING
-				&& menu->_IsStickyMode())
-				menu->_SetStickyMode(false);
-
-			// check if the user started holding down a mouse button in a submenu
-			if (wasSticky && !_IsStickyMode()) {
-				buttons = 1;
-					// buttons must have been pressed in the meantime
-			}
-
-			// This code is needed to make menus
-			// that are children of BMenuFields "sticky" (see ticket #953)
-			if (localAction == MENU_STATE_CLOSED) {
-				// The mouse could have meen moved since the last time we
-				// checked its position. Unfortunately our child menus don't tell
-				// us the new position.
-				// TODO: Maybe have a shared struct between all menus
-				// where to store the current mouse position ? 				
-				BPoint newWhere;
-				uint32 newButtons;
-				if (window->Lock()) {
-					GetMouse(&newWhere, &newButtons);
-					window->Unlock();
-				}
-
-				if (fExtraRect != NULL && fExtraRect->Contains(where)
-					// 9 = 3 pixels ^ 2 (since point_distance() returns the square of the distance)					
-					&& point_distance(newWhere, where) < 9) {
-					_SetStickyMode(true);
-					fExtraRect = NULL;				
-				} else
-					fState = MENU_STATE_CLOSED;
-			}
-		} else if (menuItem == NULL && fSelected != NULL
-			&& !_IsStickyMode() && fState != MENU_STATE_TRACKING_SUBMENU) {
-			_SelectItem(NULL);
-			fState = MENU_STATE_TRACKING;
-		}
-
-		if (locked)
-			window->Unlock();
-
-		if (fState == MENU_STATE_CLOSED 
-			|| (buttons != 0 && _IsStickyMode() && menuItem == NULL))
-			break;
-		else if (buttons == 0 && !_IsStickyMode()) {
-			if ((fSelected != NULL && fSelected->Submenu() == NULL)
-				|| menuItem == NULL) {
-				fChosenItem = fSelected;
-				break;
-			} else
-				_SetStickyMode(true);
-		}
-
-		if (snoozeAmount > 0)
-			snooze(snoozeAmount);		
-	}
-
 	if (window->Lock()) {
-		if (fSelected != NULL)
-			_SelectItem(NULL);	
-
-		if (fChosenItem != NULL)
-			fChosenItem->Invoke();
-		_RestoreFocus();
+		_SelectItem(NULL);
+		if (item != NULL)	
+			item->Invoke();
+		SetEventMask(0, 0);
+		//_RestoreFocus();
 		window->Unlock();
 	}
-
-	if (_IsStickyMode())
-		_SetStickyMode(false);
-
-	_DeleteMenuWindow();
-
-	if (action != NULL)
-		*action = fState;
-
-	return fChosenItem;
+	return item;
 }
 
 
Index: headers/os/interface/Menu.h
===================================================================
--- headers/os/interface/Menu.h	(revisione 22960)
+++ headers/os/interface/Menu.h	(copia locale)
@@ -18,6 +18,7 @@
 namespace BPrivate {
 	class BMenuWindow;
 	class ExtraMenuData;
+	class TrackData;
 	class TriggerList;
 }
 
@@ -104,6 +105,10 @@
 	virtual void			MessageReceived(BMessage* message);
 	virtual	void			KeyDown(const char* bytes, int32 numBytes);
 	virtual void			Draw(BRect updateRect);
+	virtual	void			MouseDown(BPoint where);
+	virtual	void			MouseUp(BPoint where);
+	virtual	void			MouseMoved(BPoint where, uint32 code,
+							const BMessage* message);
 	virtual	BSize			MinSize();
 	virtual	BSize			MaxSize();
 	virtual	BSize			PreferredSize();
@@ -178,13 +183,10 @@
 			void			_InitData(BMessage* archive);
 			bool			_Show(bool selectFirstItem = false);
 			void			_Hide();
+			
 			BMenuItem*		_Track(int* action, long start = -1);
+			void			_StopTracking(BMenuItem *chosen = NULL);
 
-			void			_UpdateStateOpenSelect(BMenuItem* item,
-								bigtime_t& openTime, bigtime_t& closeTime);
-			void			_UpdateStateClose(BMenuItem* item,
-								const BPoint& where, const uint32& buttons);
-
 			bool			_AddItem(BMenuItem* item, int32 index);
 			bool			_RemoveItems(int32 index, int32 count,
 								BMenuItem* item, bool deleteItems = false);
@@ -250,7 +252,7 @@
 			float			fAscent;
 			float			fDescent;
 			float			fFontHeight;
-			uint32			fState;
+			BMenu*			fTrackingMenu;
 			menu_layout		fLayout;
 			BRect*			fExtraRect;
 			float			fMaxContentWidth;
@@ -259,8 +261,8 @@
 
 			LayoutData*		fLayoutData;
 
-			int32			_reserved;
-
+			BPrivate::TrackData*	fTrackData;
+			
 			char			fTrigger;
 			bool			fResizeToFit;
 			bool			fUseCachedMenuLayout;
Index: headers/os/interface/MenuBar.h
===================================================================
--- headers/os/interface/MenuBar.h	(revisione 22960)
+++ headers/os/interface/MenuBar.h	(copia locale)
@@ -47,6 +47,8 @@
 		virtual	void		MouseDown(BPoint where);
 		virtual void		WindowActivated(bool state);
 		virtual	void		MouseUp(BPoint where);
+		virtual void		MouseMoved(BPoint where, uint32 state,
+							const BMessage *message);
 		virtual	void		FrameMoved(BPoint newPosition);
 		virtual	void		FrameResized(float newWidth, float newHeight);
 	
Index: headers/private/interface/BMCPrivate.h
===================================================================
--- headers/private/interface/BMCPrivate.h	(revisione 22960)
+++ headers/private/interface/BMCPrivate.h	(copia locale)
@@ -41,6 +41,9 @@
 
 	virtual	void	AttachedToWindow();
 	virtual	void	Draw(BRect updateRect);
+	virtual void	MouseDown(BPoint where);
+	virtual void	MouseUp(BPoint where);
+	virtual void	MouseMoved(BPoint where, uint32 code, const BMessage *message);
 	virtual	void	FrameResized(float width, float height);
 	virtual	void	MessageReceived(BMessage* msg);
 	virtual	void	MakeFocus(bool focused = true);
@@ -55,9 +58,11 @@
 
 		BMenuField	*fMenuField;
 		bool		fFixedSize;	
-		BMessageRunner *fRunner;
 		bool		fShowPopUpMarker;
+		bool		fMoved;
+		BMessageRunner *fRunner;				
 		float		fPreviousWidth;
+		
 };
 
 #endif // _BMC_PRIVATE_H
Index: headers/private/interface/MenuPrivate.h
===================================================================
--- headers/private/interface/MenuPrivate.h	(revisione 22960)
+++ headers/private/interface/MenuPrivate.h	(copia locale)
@@ -1,3 +1,10 @@
+/*
+ * Copyright 2001-2006, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *		Stefano Ceccherini (stefano.ceccherini@gmail.com)
+ */
 #ifndef __MENU_PRIVATE_H
 #define __MENU_PRIVATE_H
 
@@ -8,8 +15,25 @@
 	MENU_STATE_CLOSED = 5
 };
 
+namespace BPrivate {
 
+class TrackData {
+public:
+	TrackData();
+	~TrackData();
+
+	void SetInsideMenu(bool inside);
+	bool InsideMenu() const;
+	
+	void Block();
+	void Release();
+private:
+	sem_id	fQuitSem;
+	int32	fInside;
+};
+
+};
+
 extern const char *kEmptyMenuLabel;
 
-
 #endif // __MENU_PRIVATE_H
Index: src/servers/app/WindowLayer.cpp
===================================================================
--- src/servers/app/WindowLayer.cpp	(revisione 22960)
+++ src/servers/app/WindowLayer.cpp	(copia locale)
@@ -855,8 +855,9 @@
 					fDesktop->ActivateWindow(this);
 
 				// eat the click if we don't accept first click
-				if ((Flags() & B_WILL_ACCEPT_FIRST_CLICK) == 0
-					|| (Flags() & B_AVOID_FOCUS) != 0)
+				if (fFeel != kMenuWindowFeel 
+					&& ((Flags() & B_WILL_ACCEPT_FIRST_CLICK) == 0
+					|| (Flags() & B_AVOID_FOCUS) != 0))
 					return;
 			}
 
Index: src/servers/app/Desktop.cpp
===================================================================
--- src/servers/app/Desktop.cpp	(revisione 22960)
+++ src/servers/app/Desktop.cpp	(copia locale)
@@ -1171,10 +1171,11 @@
 EventTarget*
 Desktop::KeyboardEventTarget()
 {
+#if 0
 	WindowLayer* window = _CurrentWindows().LastWindow();
 	if (window != NULL && window->Feel() == kMenuWindowFeel)
 		return &window->EventTarget();
-
+#endif
 	if (FocusWindow() != NULL)
 		return &FocusWindow()->EventTarget();
 
