Ticket #1621: menus.diff

File menus.diff, 27.1 KB (added by jackburton, 17 years ago)

Patch against latest revision (22965), after changes in Menu.cpp

  • src/kits/interface/MenuField.cpp

     
    88 *      Ingo Weinhold <bonefish@cs.tu-berlin.de>
    99 */
    1010
     11#include <stdio.h>
    1112#include <stdlib.h>
    1213#include <string.h>
    1314
     
    296297void
    297298BMenuField::MouseDown(BPoint where)
    298299{
     300    printf("BMenuField::MouseDown()\n");
    299301    if (!fMenuBar->Frame().Contains(where))
    300302        return;
    301303
     304    printf("Inside menubar's frame\n");
    302305    BRect bounds = fMenuBar->ConvertFromParent(Bounds());
    303306
    304307    fMenuBar->StartMenuBar(0, false, true, &bounds);
  • src/kits/interface/PopUpMenu.cpp

     
    1616
    1717#include <new>
    1818
     19#include <stdio.h>
    1920
    2021struct popup_menu_data {
    2122    BPopUpMenu *object;
     
    110111void
    111112BPopUpMenu::MouseDown(BPoint point)
    112113{
    113     BView::MouseDown(point);
     114    BMenu::MouseDown(point);
    114115}
    115116
    116117
    117118void
    118119BPopUpMenu::MouseUp(BPoint point)
    119120{
    120     BView::MouseUp(point);
     121    BMenu::MouseUp(point);
    121122}
    122123
    123124
    124125void
    125126BPopUpMenu::MouseMoved(BPoint point, uint32 code, const BMessage *msg)
    126127{
    127     BView::MouseMoved(point, code, msg);
     128    BMenu::MouseMoved(point, code, msg);
    128129}
    129130
    130131
     
    388389            window->UpdateIfNeeded();
    389390    }
    390391
    391     status_t unused;
     392    status_t unused;
    392393    while (wait_for_thread(fTrackThread, &unused) == B_INTERRUPTED)
    393394        ;
    394395   
  • src/kits/interface/BMCPrivate.cpp

     
    3535filter_result
    3636_BMCFilter_::Filter(BMessage *message, BHandler **handler)
    3737{
    38     if (message->what == B_MOUSE_DOWN) {
     38    /*if (message->what == B_MOUSE_DOWN) {
    3939        if (BView *view = dynamic_cast<BView *>(*handler)) {
    4040            BPoint point;
    4141            message->FindPoint("be:view_where", &point);
    42             view->ConvertToParent(&point);
    43             message->ReplacePoint("be:view_where", point);
    44             *handler = fMenuField;
     42            if (view->Bounds().Contains(point)) {           
     43                view->ConvertToParent(&point);
     44                message->ReplacePoint("be:view_where", point);
     45                *handler = fMenuField;
     46            }       
    4547        }
    46     }
     48    }*/
    4749
    4850    return B_DISPATCH_MESSAGE;
    4951}
     
    228230
    229231
    230232void
     233_BMCMenuBar_::MouseDown(BPoint where)
     234{
     235    thread_info info;
     236    if (fMenuField->fMenuTaskID >= 0
     237        && get_thread_info(fMenuField->fMenuTaskID, &info) == B_OK
     238        && !Bounds().Contains(where)) {
     239        BMenu::MouseDown(where);
     240    } else if (Bounds().Contains(where)) {
     241        BPoint point = where;
     242        ConvertToParent(&point);       
     243        fMenuField->MouseDown(point);
     244    }   
     245}
     246
     247
     248void
     249_BMCMenuBar_::MouseUp(BPoint where)
     250{
     251    if (!Bounds().Contains(where))
     252        BMenu::MouseUp(where);
     253}
     254
     255
     256void
     257_BMCMenuBar_::MouseMoved(BPoint where, uint32 code, const BMessage *message)
     258{
     259    printf("BMC MouseMoved\n");
     260    // Eat the first mousemoved event   
     261    /*if (!fMoved)
     262        fMoved = true; 
     263    else
     264        BMenuBar::MouseMoved(where, code, message);*/
     265}
     266
     267
     268void
    231269_BMCMenuBar_::FrameResized(float width, float height)
    232270{
    233271    // we need to take care of resizing and cleaning up
  • src/kits/interface/Menu.cpp

     
    44 *
    55 * Authors:
    66 *      Marc Flerackers (mflerackers@androme.be)
    7  *      Stefano Ceccherini (burton666@libero.it)
     7 *      Stefano Ceccherini (stefano.ceccherini@gmail.com)
    88 */
    99
    1010#include <new>
    1111#include <ctype.h>
    1212#include <string.h>
    1313
     14#define DEBUG 1
     15
     16#include <Application.h>
    1417#include <Debug.h>
    1518#include <File.h>
    1619#include <FindDirectory.h>
     
    183186    fAscent(-1.0f),
    184187    fDescent(-1.0f),
    185188    fFontHeight(-1.0f),
    186     fState(0),
     189    fTrackingMenu(NULL),
    187190    fLayout(layout),
    188191    fExtraRect(NULL),
    189192    fMaxContentWidth(0.0f),
    190193    fInitMatrixSize(NULL),
    191194    fExtraMenuData(NULL),
     195    fTrackData(NULL),
    192196    fTrigger(0),
    193197    fResizeToFit(true),
    194198    fUseCachedMenuLayout(false),
     
    216220    fAscent(-1.0f),
    217221    fDescent(-1.0f),
    218222    fFontHeight(-1.0f),
    219     fState(0),
     223    fTrackingMenu(NULL),
    220224    fLayout(B_ITEMS_IN_MATRIX),
    221225    fExtraRect(NULL),
    222226    fMaxContentWidth(0.0f),
    223227    fInitMatrixSize(NULL),
    224228    fExtraMenuData(NULL),
     229    fTrackData(NULL),
    225230    fTrigger(0),
    226231    fResizeToFit(true),
    227232    fUseCachedMenuLayout(false),
     
    248253    delete fInitMatrixSize;
    249254    delete fExtraMenuData;
    250255    delete fLayoutData;
     256    delete fTrackData;
    251257}
    252258
    253259
     
    262268    fAscent(-1.0f),
    263269    fDescent(-1.0f),
    264270    fFontHeight(-1.0f),
    265     fState(0),
     271    fTrackingMenu(NULL),
    266272    fLayout(B_ITEMS_IN_ROW),
    267273    fExtraRect(NULL),
    268274    fMaxContentWidth(0.0f),
    269275    fInitMatrixSize(NULL),
    270276    fExtraMenuData(NULL),
     277    fTrackData(NULL),
    271278    fTrigger(0),
    272279    fResizeToFit(true),
    273280    fUseCachedMenuLayout(false),
     
    285292}
    286293
    287294
    288 BArchivable*
     295BArchivable *
    289296BMenu::Instantiate(BMessage* archive)
    290297{
    291298    if (validate_instantiation(archive, "BMenu"))
     
    877884}
    878885
    879886
     887void
     888BMenu::MouseDown(BPoint where)
     889{
     890    PRINT(("%s MouseDown()\n", Name()));
     891    if (!Bounds().Contains(where)) {
     892        // The only case where this can happen is in the tracking menu,
     893        // as it's the only one with an event mask set to receive
     894        // mouse events outside its bounds.         
     895        ASSERT(fTrackingMenu == this); 
     896        if (fTrackData && !fTrackData->InsideMenu())
     897            _StopTracking();
     898    }
     899}
     900
     901
     902void
     903BMenu::MouseUp(BPoint where)
     904{
     905    PRINT(("%s MouseUp(). fTrackingMenu = %p\n", Name(), fTrackingMenu));
     906    if (fTrackingMenu == NULL)
     907        return;
     908
     909    if (_CustomTrackingWantsToQuit()) {
     910        fTrackingMenu->_StopTracking();
     911        return;
     912    }
     913
     914    BRect *extraRect = fExtraRect;
     915    fExtraRect = NULL;
     916   
     917    if (extraRect != NULL && extraRect->Contains(where)) {
     918        printf("BMenu Inside the extra rect\n");
     919        //fTrackingMenu->_SetStickyMode(true);
     920        return;
     921    }
     922   
     923    // Either we are inside our own bounds, or we are the tracking menu.
     924    // In both cases, we need to stop tracking.
     925    if (Bounds().Contains(where)
     926        || (fTrackData && !fTrackData->InsideMenu()))   
     927        fTrackingMenu->_StopTracking(fSelected);
     928}
     929
     930
     931void
     932BMenu::MouseMoved(BPoint where, uint32 code, const BMessage* message)
     933{
     934    PRINT(("%s MouseMoved (code: %ld)\n", Name(), code));
     935    if (fTrackingMenu != NULL && fTrackingMenu != this) {       
     936        ASSERT(fTrackingMenu->fTrackData != NULL);
     937        if (code == B_ENTERED_VIEW)
     938            fTrackingMenu->fTrackData->SetInsideMenu(true);
     939        else if (code == B_EXITED_VIEW)
     940            fTrackingMenu->fTrackData->SetInsideMenu(false);
     941    }
     942   
     943    BMenuItem *item = _HitTestItems(where);
     944    if (item != NULL)
     945        _SelectItem(item);
     946   
     947    if (fTrackingMenu != NULL && _CustomTrackingWantsToQuit())
     948        fTrackingMenu->_StopTracking();
     949}
     950
     951
    880952BSize
    881953BMenu::MinSize()
    882954{
     
    10801152    fAscent(-1.0f),
    10811153    fDescent(-1.0f),
    10821154    fFontHeight(-1.0f),
    1083     fState(0),
     1155    fTrackingMenu(NULL),
    10841156    fLayout(layout),
    10851157    fExtraRect(NULL),
    10861158    fMaxContentWidth(0.0f),
    10871159    fInitMatrixSize(NULL),
    10881160    fExtraMenuData(NULL),
     1161    fTrackData(NULL),
    10891162    fTrigger(0),
    10901163    fResizeToFit(resizeToFit),
    10911164    fUseCachedMenuLayout(false),
     
    12511324        archive->FindFloat("_maxwidth", &fMaxContentWidth);
    12521325
    12531326        BMessage msg;
    1254         for (int32 i = 0; archive->FindMessage("_items", i, &msg) == B_OK; i++) {
     1327        for (int32 i = 0; archive->FindMessage("_items", i, &msg) == B_OK; i++) {
    12551328            BArchivable *object = instantiate_object(&msg);
    12561329            if (BMenuItem *item = dynamic_cast<BMenuItem *>(object)) {
    12571330                BRect bounds;
     
    12841357    if (window == NULL) {
    12851358        // Menu windows get the BMenu's handler name
    12861359        window = new (nothrow) BMenuWindow(Name());
    1287         ourWindow = true;
     1360            ourWindow = true;
    12881361    }
    12891362
    12901363    if (window == NULL)
     
    13131386
    13141387        _UpdateWindowViewSize(true);
    13151388        window->Show();
    1316 
     1389        window->Activate();
     1390       
    13171391        if (selectFirstItem)
    13181392            _SelectItem(ItemAt(0));
    13191393
     
    13541428
    13551429
    13561430BMenuItem *
    1357 BMenu::_Track(int *action, long start)
     1431BMenu::_Track(int *action, long startIndex)
    13581432{
    1359     // TODO: cleanup
    1360     BMenuItem *item = NULL;
    1361     bigtime_t openTime = system_time();
    1362     bigtime_t closeTime = 0;
     1433    PRINT(("%s _Track()\n", Name()));
    13631434
    1364     fState = MENU_STATE_TRACKING;
    1365     if (fSuper != NULL)
    1366         fSuper->fState = MENU_STATE_TRACKING_SUBMENU;
     1435    fTrackData = new (std::nothrow) BPrivate::TrackData();
     1436    if (fTrackData == NULL)
     1437        return NULL;
    13671438
    1368     while (true) {
    1369         if (_CustomTrackingWantsToQuit())
    1370             break;
     1439    fTrackingMenu = this;
     1440    fChosenItem = NULL;
    13711441
    1372         bool locked = LockLooper();
    1373         if (!locked)
    1374             break;
    1375 
    1376         bigtime_t snoozeAmount = 50000;
    1377         BPoint location;
    1378         uint32 buttons;
    1379         GetMouse(&location, &buttons, true);
    1380 
    1381         BMenuWindow *window = static_cast<BMenuWindow *>(Window());
    1382 
    1383         BPoint screenLocation = ConvertToScreen(location);
    1384         if (window->CheckForScrolling(screenLocation)) {
    1385             item = NULL;
    1386         } else {
    1387             item = _HitTestItems(location, B_ORIGIN);
    1388             if (item != NULL)
    1389                 _UpdateStateOpenSelect(item, openTime, closeTime);
    1390         }
    1391 
    1392         // Track the submenu
    1393         if (_OverSubmenu(fSelected, screenLocation)) {
    1394             UnlockLooper();
    1395             locked = false;
    1396             int submenuAction = MENU_STATE_TRACKING;
    1397             BMenu *submenu = fSelected->Submenu();
    1398             bool wasSticky = _IsStickyMode();
    1399             if (wasSticky)
    1400                 submenu->_SetStickyMode(true);
    1401             BMenuItem *submenuItem = submenu->_Track(&submenuAction);
    1402 
    1403             // check if the user started holding down a mouse button in a submenu
    1404             if (wasSticky && !_IsStickyMode()) {
    1405                 buttons = 1;
    1406                     // buttons must have been pressed in the meantime
    1407             }
    1408 
    1409             if (submenuAction == MENU_STATE_CLOSED) {
    1410                 item = submenuItem;
    1411                 fState = submenuAction;
    1412                 break;
    1413             }
    1414 
    1415             locked = LockLooper();
    1416             if (!locked)
    1417                 break;
    1418         } else if (item == NULL) {
    1419             if (_OverSuper(screenLocation)) {
    1420                 fState = MENU_STATE_TRACKING;
    1421                 UnlockLooper();
    1422                 break;
    1423             }
    1424 
    1425             if (!_OverSubmenu(fSelected, screenLocation)
    1426                 && system_time() > closeTime + kHysteresis
    1427                 && fState != MENU_STATE_TRACKING_SUBMENU) {
    1428                 _SelectItem(NULL);
    1429                 fState = MENU_STATE_TRACKING;
    1430             }
    1431 
    1432             if (fSuper != NULL) {
    1433                 // Give supermenu the chance to continue tracking
    1434                 *action = fState;
    1435                 if (locked)
    1436                     UnlockLooper();
    1437 
    1438                 return NULL;
    1439             }
    1440         }
    1441 
    1442         if (locked)
    1443             UnlockLooper();
    1444 
    1445         _UpdateStateClose(item, location, buttons);
    1446 
    1447         if (fState == MENU_STATE_CLOSED)
    1448             break;
    1449 
    1450         snooze(snoozeAmount);
    1451     }
    1452 
    1453     if (action != NULL)
    1454         *action = fState;
    1455 
    1456     if (fSelected != NULL && LockLooper()) {
    1457         _SelectItem(NULL);
     1442    if (startIndex != -1)
     1443        be_app->ObscureCursor();
     1444    if (LockLooper()) {
     1445        if (startIndex != -1)
     1446            _SelectItem(ItemAt(startIndex), true, true);
     1447        SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);   
    14581448        UnlockLooper();
    1459     }
     1449    }   
     1450   
     1451    fTrackData->Block();
     1452        // Will be released from another thread
    14601453
    1461     if (_IsStickyMode())
    1462         _SetStickyMode(false);
     1454    _Hide();
    14631455
    1464     // delete the menu window recycled for all the child menus
    1465     _DeleteMenuWindow();
     1456    delete fTrackData;
     1457    fTrackData = NULL;
     1458    fTrackingMenu = NULL;
    14661459
    1467     return item;
     1460    PRINT(("%s _Track exits\n", Name()));
     1461    return fChosenItem;
    14681462}
    14691463
    14701464
    14711465void
    1472 BMenu::_UpdateStateOpenSelect(BMenuItem* item, bigtime_t& openTime,
    1473     bigtime_t& closeTime)
     1466BMenu::_StopTracking(BMenuItem *chosen)
    14741467{
    1475     if (fState == MENU_STATE_CLOSED)
     1468    // TODO: Added mostly for debugging reasons.
     1469    // We might want to be less strict, and just
     1470    // call _StopTracking on the correct menu ourselves
     1471    if (fTrackingMenu == NULL || fTrackingMenu != this)
    14761472        return;
    14771473
    1478     if (item != fSelected && system_time() > closeTime + kHysteresis) {
    1479         _SelectItem(item, false);
    1480         openTime = system_time();
    1481     } else if (system_time() > kHysteresis + openTime && item->Submenu() != NULL
    1482         && item->Submenu()->Window() == NULL) {
    1483         // Open the submenu if it's not opened yet, but only if
    1484         // the mouse pointer stayed over there for some time
    1485         // (hysteresis)
    1486         _SelectItem(item);
    1487         closeTime = system_time();
     1474   
     1475    fChosenItem = chosen;
     1476   
     1477    if (LockLooper()) {
     1478        SetEventMask(0, 0);
     1479        UnlockLooper();
    14881480    }
    1489     if (fState != MENU_STATE_TRACKING)
    1490         fState = MENU_STATE_TRACKING;
    1491 }
    14921481
    1493 
    1494 void
    1495 BMenu::_UpdateStateClose(BMenuItem* item, const BPoint& where,
    1496     const uint32& buttons)
    1497 {
    1498     if (fState == MENU_STATE_CLOSED)
    1499         return;
    1500 
    1501     if (buttons != 0 && _IsStickyMode()) {
    1502         if (item == NULL)
    1503             fState = MENU_STATE_CLOSED;
    1504         else {
    1505             BMenu *supermenu = Supermenu();
    1506             for(; supermenu; supermenu = supermenu->Supermenu())
    1507                 supermenu->_SetStickyMode(false);
    1508             _SetStickyMode(false);
    1509         }
    1510     } else if (buttons == 0 && !_IsStickyMode()) {
    1511         if (fExtraRect != NULL && fExtraRect->Contains(where)) {
    1512             _SetStickyMode(true);
    1513             fExtraRect = NULL;
    1514                 // This code should be executed only once
    1515         } else
    1516             fState = MENU_STATE_CLOSED;
    1517     }
     1482    if (fTrackData)
     1483        fTrackData->Release();
    15181484}
    15191485
    15201486
     
    19201886int
    19211887BMenu::State(BMenuItem **item) const
    19221888{
    1923     if (fState == MENU_STATE_TRACKING || fState == MENU_STATE_CLOSED)
    1924         return fState;
    1925 
    1926     if (fSelected != NULL && fSelected->Submenu() != NULL)
    1927         return fSelected->Submenu()->State(item);
    1928 
    1929     return fState;
     1889    return 0;
    19301890}
    19311891
    19321892
     
    19911951    if (fCachedMenuWindow == NULL) {
    19921952        char windowName[64];
    19931953        snprintf(windowName, 64, "%s cached menu", Name());
    1994         fCachedMenuWindow = new (nothrow) BMenuWindow(windowName);
     1954        fCachedMenuWindow = new (std::nothrow) BMenuWindow(windowName);
    19951955    }
    19961956
    19971957    return fCachedMenuWindow;
     
    20892049        if (fSelected != NULL) {
    20902050            fSelected->Select(false);
    20912051            BMenu *subMenu = fSelected->Submenu();
    2092             if (subMenu != NULL && subMenu->Window() != NULL)
     2052            if (subMenu != NULL)
    20932053                subMenu->_Hide();
    20942054        }
    20952055
     
    21012061    if (fSelected != NULL && showSubmenu) {
    21022062        BMenu *subMenu = fSelected->Submenu();
    21032063        if (subMenu != NULL && subMenu->Window() == NULL) {
    2104             if (!subMenu->_Show(selectFirstItem)) {
     2064            if (subMenu->_Show(selectFirstItem)) {
     2065                subMenu->fTrackingMenu = fTrackingMenu;
     2066            } else {
    21052067                // something went wrong, deselect the item
    21062068                fSelected->Select(false);
    21072069                fSelected = NULL;
     
    21582120{
    21592121    if (fStickyMode != on) {
    21602122        // TODO: Ugly hack, but it needs to be done right here in this method
    2161         BMenuBar *menuBar = dynamic_cast<BMenuBar *>(this);
     2123        /*BMenuBar *menuBar = dynamic_cast<BMenuBar *>(this);
    21622124        if (on && menuBar != NULL && menuBar->LockLooper()) {
    21632125            // Steal the focus from the current focus view
    21642126            // (needed to handle keyboard navigation)
    21652127            menuBar->_StealFocus();
    21662128            menuBar->UnlockLooper();
    2167         }
     2129        }*/
    21682130
    21692131        fStickyMode = on;
    21702132    }
     
    23352297        menuBar->_RestoreFocus();
    23362298
    23372299    fChosenItem = NULL;
    2338     fState = MENU_STATE_CLOSED;
    23392300}
    23402301
    23412302
     2303// TrackData
     2304namespace BPrivate {
     2305
     2306TrackData::TrackData()
     2307{
     2308    fQuitSem = create_sem(0, "PSYCHO menu quit sem");
     2309    fInside = 0;   
     2310}
     2311
     2312
     2313TrackData::~TrackData()
     2314{
     2315    Release();
     2316}
     2317
     2318
     2319void
     2320TrackData::SetInsideMenu(bool inside)
     2321{
     2322    int32 value = inside ? 1 : -1;
     2323    atomic_add(&fInside, value);
     2324}
     2325
     2326
     2327bool
     2328TrackData::InsideMenu() const
     2329{
     2330    return fInside > 0;
     2331}
     2332
     2333
     2334void
     2335TrackData::Block()
     2336{   
     2337    while (acquire_sem(fQuitSem) == B_INTERRUPTED)
     2338        ;
     2339}
     2340
     2341
     2342void
     2343TrackData::Release()
     2344{
     2345    if (fQuitSem >= 0) {
     2346        delete_sem(fQuitSem);
     2347        fQuitSem = -1;     
     2348    }   
     2349}
     2350
     2351};
     2352
    23422353//  #pragma mark -
    23432354
    23442355
  • src/kits/interface/Window.cpp

     
    10411041           
    10421042            // Close an eventually opened menu, if this click targets the
    10431043            // preferred handler, and unless the target is the menu itself
    1044             BMenu *menu = dynamic_cast<BMenu *>(fFocus);
     1044            /*BMenu *menu = dynamic_cast<BMenu *>(fFocus);
    10451045            if (menu != NULL && menu != view && PreferredHandler() == target
    10461046                && menu->State() != MENU_STATE_CLOSED) {
    10471047                menu->QuitTracking();
    10481048                return;         
    1049             }
     1049            }*/
    10501050           
    10511051            if (view != NULL) {
    10521052                BPoint where;
  • src/kits/interface/MenuBar.cpp

     
    202202void
    203203BMenuBar::MouseDown(BPoint where)
    204204{
    205     if (fTracking)
    206         return;
     205    if (!fTracking) {   
     206        BWindow *window = Window();
     207        if (!window->IsActive() || !window->IsFront()) {
     208            window->Activate();
     209            window->UpdateIfNeeded();
     210        }
     211   
     212        StartMenuBar(-1, false, false);
    207213
    208     BWindow *window = Window();
    209     if (!window->IsActive() || !window->IsFront()) {
    210         window->Activate();
    211         window->UpdateIfNeeded();
     214    } else if (!Bounds().Contains(where)) {
     215        if (fTrackData && !fTrackData->InsideMenu())       
     216            _StopTracking();
     217        return;
    212218    }
    213    
    214     StartMenuBar(-1, false, false);
     219
     220    MouseMoved(where, B_INSIDE_VIEW, NULL);
    215221}
    216222
    217223
    218224void
    219 BMenuBar::WindowActivated(bool state)
     225BMenuBar::MouseUp(BPoint where)
    220226{
    221     BView::WindowActivated(state);
     227    if (fTracking) {
     228        BRect *extraRect = fExtraRect;
     229        fExtraRect = NULL;
     230        if (extraRect != NULL && extraRect->Contains(where)) {
     231            printf("Inside the extra rect\n");     
     232            // do nothing.
     233        } else if ((fTrackData && !fTrackData->InsideMenu())
     234            && (!Bounds().Contains(where)
     235            || (fSelected == NULL || fSelected->Submenu() == NULL))) {
     236            // If mouse was released outside the menubar,
     237            // or inside in a zone where there are no items,
     238            // or on an item which doesn't have a submenu
     239            // (cf. Menu preflet), stop tracking.
     240            _StopTracking(fSelected);
     241        }
     242    } else
     243        BView::MouseUp(where);
    222244}
    223245
    224246
     247void
     248BMenuBar::MouseMoved(BPoint where, uint32 code, const BMessage* message)
     249{
     250    BMessage *currentMessage = Window()->CurrentMessage();
     251    int32 buttons = 0;
     252    currentMessage->FindInt32("buttons", &buttons);
     253   
     254    if (fTracking && buttons != 0) {
     255        BMenuItem *item = _HitTestItems(where);
     256        if (item != NULL)
     257            _SelectItem(item);
     258    } else
     259        BView::MouseMoved(where, code, message);
     260}
     261
     262
    225263void
    226 BMenuBar::MouseUp(BPoint where)
     264BMenuBar::WindowActivated(bool state)
    227265{
    228     BView::MouseUp(where);
     266    BView::WindowActivated(state);
    229267}
    230268
    231269
     
    384422   
    385423    fPrevFocusToken = -1;
    386424    fTracking = true;
    387        
     425
    388426    window->MenusBeginning();
    389    
     427
    390428    fMenuSem = create_sem(0, "window close sem");
    391429    _set_menu_sem_(window, fMenuSem);
    392430   
     
    459497
    460498BMenuItem *
    461499BMenuBar::_Track(int32 *action, int32 startIndex, bool showMenu)
    462 {   
    463     // TODO: Cleanup, merge some "if" blocks if possible
    464     fChosenItem = NULL;
     500{
     501    BMenuItem *item = BMenu::_Track((int*)action, (int)startIndex);
    465502   
    466503    BWindow *window = Window();
    467     fState = MENU_STATE_TRACKING;
    468 
    469     if (startIndex != -1) {
    470         be_app->ObscureCursor();
    471         if (window->Lock()) {
    472             _SelectItem(ItemAt(startIndex), true, true);
    473             window->Unlock();
    474         }
    475     }
    476 
    477     while (true) {
    478         bigtime_t snoozeAmount = 40000;
    479         bool locked = (Window() != NULL && window->Lock());//WithTimeout(200000)
    480         if (!locked)
    481             break;
    482 
    483         BPoint where;
    484         uint32 buttons;
    485         GetMouse(&where, &buttons, true);
    486 
    487         BMenuItem *menuItem = _HitTestItems(where, B_ORIGIN);
    488         if (menuItem != NULL) {
    489             // Select item if:
    490             // - no previous selection
    491             // - nonsticky mode and different selection,
    492             // - clicked in sticky mode
    493             if (fSelected == NULL
    494                 || (!_IsStickyMode() && menuItem != fSelected)
    495                 || (buttons != 0 && _IsStickyMode())) {
    496                 if (menuItem->Submenu() != NULL) {
    497                     if (menuItem->Submenu()->Window() == NULL) {
    498                         // open the menu if it's not opened yet
    499                         _SelectItem(menuItem);
    500                         if (_IsStickyMode())
    501                             _SetStickyMode(false);
    502                     } else {
    503                         // Menu was already opened, close it and bail
    504                         _SelectItem(NULL);
    505                         fState = MENU_STATE_CLOSED;
    506                         fChosenItem = NULL;
    507                     }
    508                 } else {
    509                     // No submenu, just select the item
    510                     _SelectItem(menuItem);                 
    511                 }
    512             }
    513         }
    514 
    515         if (_OverSubmenu(fSelected, ConvertToScreen(where))) {
    516             // call _Track() from the selected sub-menu when the mouse cursor
    517             // is over its window
    518             BMenu *menu = fSelected->Submenu();
    519             window->Unlock();
    520             locked = false;
    521             snoozeAmount = 30000;
    522             bool wasSticky = _IsStickyMode();
    523             if (wasSticky)
    524                 menu->_SetStickyMode(true);
    525             int localAction;
    526             fChosenItem = menu->_Track(&localAction);
    527             if (menu->State(NULL) == MENU_STATE_TRACKING
    528                 && menu->_IsStickyMode())
    529                 menu->_SetStickyMode(false);
    530 
    531             // check if the user started holding down a mouse button in a submenu
    532             if (wasSticky && !_IsStickyMode()) {
    533                 buttons = 1;
    534                     // buttons must have been pressed in the meantime
    535             }
    536 
    537             // This code is needed to make menus
    538             // that are children of BMenuFields "sticky" (see ticket #953)
    539             if (localAction == MENU_STATE_CLOSED) {
    540                 // The mouse could have meen moved since the last time we
    541                 // checked its position. Unfortunately our child menus don't tell
    542                 // us the new position.
    543                 // TODO: Maybe have a shared struct between all menus
    544                 // where to store the current mouse position ?             
    545                 BPoint newWhere;
    546                 uint32 newButtons;
    547                 if (window->Lock()) {
    548                     GetMouse(&newWhere, &newButtons);
    549                     window->Unlock();
    550                 }
    551 
    552                 if (fExtraRect != NULL && fExtraRect->Contains(where)
    553                     // 9 = 3 pixels ^ 2 (since point_distance() returns the square of the distance)                 
    554                     && point_distance(newWhere, where) < 9) {
    555                     _SetStickyMode(true);
    556                     fExtraRect = NULL;             
    557                 } else
    558                     fState = MENU_STATE_CLOSED;
    559             }
    560         } else if (menuItem == NULL && fSelected != NULL
    561             && !_IsStickyMode() && fState != MENU_STATE_TRACKING_SUBMENU) {
    562             _SelectItem(NULL);
    563             fState = MENU_STATE_TRACKING;
    564         }
    565 
    566         if (locked)
    567             window->Unlock();
    568 
    569         if (fState == MENU_STATE_CLOSED
    570             || (buttons != 0 && _IsStickyMode() && menuItem == NULL))
    571             break;
    572         else if (buttons == 0 && !_IsStickyMode()) {
    573             if ((fSelected != NULL && fSelected->Submenu() == NULL)
    574                 || menuItem == NULL) {
    575                 fChosenItem = fSelected;
    576                 break;
    577             } else
    578                 _SetStickyMode(true);
    579         }
    580 
    581         if (snoozeAmount > 0)
    582             snooze(snoozeAmount);       
    583     }
    584 
    585504    if (window->Lock()) {
    586         if (fSelected != NULL)
    587             _SelectItem(NULL); 
    588 
    589         if (fChosenItem != NULL)
    590             fChosenItem->Invoke();
    591         _RestoreFocus();
     505        _SelectItem(NULL);
     506        if (item != NULL)   
     507            item->Invoke();
     508        SetEventMask(0, 0);
     509        //_RestoreFocus();
    592510        window->Unlock();
    593511    }
    594 
    595     if (_IsStickyMode())
    596         _SetStickyMode(false);
    597 
    598     _DeleteMenuWindow();
    599 
    600     if (action != NULL)
    601         *action = fState;
    602 
    603     return fChosenItem;
     512    return item;
    604513}
    605514
    606515
  • headers/os/interface/Menu.h

     
    1818namespace BPrivate {
    1919    class BMenuWindow;
    2020    class ExtraMenuData;
     21    class TrackData;
    2122    class TriggerList;
    2223}
    2324
     
    104105    virtual void            MessageReceived(BMessage* message);
    105106    virtual void            KeyDown(const char* bytes, int32 numBytes);
    106107    virtual void            Draw(BRect updateRect);
     108    virtual void            MouseDown(BPoint where);
     109    virtual void            MouseUp(BPoint where);
     110    virtual void            MouseMoved(BPoint where, uint32 code,
     111                            const BMessage* message);
    107112    virtual BSize           MinSize();
    108113    virtual BSize           MaxSize();
    109114    virtual BSize           PreferredSize();
     
    178183            void            _InitData(BMessage* archive);
    179184            bool            _Show(bool selectFirstItem = false);
    180185            void            _Hide();
     186           
    181187            BMenuItem*      _Track(int* action, long start = -1);
     188            void            _StopTracking(BMenuItem *chosen = NULL);
    182189
    183             void            _UpdateStateOpenSelect(BMenuItem* item,
    184                                 bigtime_t& openTime, bigtime_t& closeTime);
    185             void            _UpdateStateClose(BMenuItem* item,
    186                                 const BPoint& where, const uint32& buttons);
    187 
    188190            bool            _AddItem(BMenuItem* item, int32 index);
    189191            bool            _RemoveItems(int32 index, int32 count,
    190192                                BMenuItem* item, bool deleteItems = false);
     
    250252            float           fAscent;
    251253            float           fDescent;
    252254            float           fFontHeight;
    253             uint32          fState;
     255            BMenu*          fTrackingMenu;
    254256            menu_layout     fLayout;
    255257            BRect*          fExtraRect;
    256258            float           fMaxContentWidth;
     
    259261
    260262            LayoutData*     fLayoutData;
    261263
    262             int32           _reserved;
    263 
     264            BPrivate::TrackData*    fTrackData;
     265           
    264266            char            fTrigger;
    265267            bool            fResizeToFit;
    266268            bool            fUseCachedMenuLayout;
  • headers/os/interface/MenuBar.h

     
    4747        virtual void        MouseDown(BPoint where);
    4848        virtual void        WindowActivated(bool state);
    4949        virtual void        MouseUp(BPoint where);
     50        virtual void        MouseMoved(BPoint where, uint32 state,
     51                            const BMessage *message);
    5052        virtual void        FrameMoved(BPoint newPosition);
    5153        virtual void        FrameResized(float newWidth, float newHeight);
    5254   
  • headers/private/interface/BMCPrivate.h

     
    4141
    4242    virtual void    AttachedToWindow();
    4343    virtual void    Draw(BRect updateRect);
     44    virtual void    MouseDown(BPoint where);
     45    virtual void    MouseUp(BPoint where);
     46    virtual void    MouseMoved(BPoint where, uint32 code, const BMessage *message);
    4447    virtual void    FrameResized(float width, float height);
    4548    virtual void    MessageReceived(BMessage* msg);
    4649    virtual void    MakeFocus(bool focused = true);
     
    5558
    5659        BMenuField  *fMenuField;
    5760        bool        fFixedSize;
    58         BMessageRunner *fRunner;
    5961        bool        fShowPopUpMarker;
     62        bool        fMoved;
     63        BMessageRunner *fRunner;               
    6064        float       fPreviousWidth;
     65       
    6166};
    6267
    6368#endif // _BMC_PRIVATE_H
  • headers/private/interface/MenuPrivate.h

     
     1/*
     2 * Copyright 2001-2006, Haiku, Inc.
     3 * Distributed under the terms of the MIT License.
     4 *
     5 * Authors:
     6 *      Stefano Ceccherini (stefano.ceccherini@gmail.com)
     7 */
    18#ifndef __MENU_PRIVATE_H
    29#define __MENU_PRIVATE_H
    310
     
    815    MENU_STATE_CLOSED = 5
    916};
    1017
     18namespace BPrivate {
    1119
     20class TrackData {
     21public:
     22    TrackData();
     23    ~TrackData();
     24
     25    void SetInsideMenu(bool inside);
     26    bool InsideMenu() const;
     27   
     28    void Block();
     29    void Release();
     30private:
     31    sem_id  fQuitSem;
     32    int32   fInside;
     33};
     34
     35};
     36
    1237extern const char *kEmptyMenuLabel;
    1338
    14 
    1539#endif // __MENU_PRIVATE_H
  • src/servers/app/WindowLayer.cpp

     
    855855                    fDesktop->ActivateWindow(this);
    856856
    857857                // eat the click if we don't accept first click
    858                 if ((Flags() & B_WILL_ACCEPT_FIRST_CLICK) == 0
    859                     || (Flags() & B_AVOID_FOCUS) != 0)
     858                if (fFeel != kMenuWindowFeel
     859                    && ((Flags() & B_WILL_ACCEPT_FIRST_CLICK) == 0
     860                    || (Flags() & B_AVOID_FOCUS) != 0))
    860861                    return;
    861862            }
    862863
  • src/servers/app/Desktop.cpp

     
    11711171EventTarget*
    11721172Desktop::KeyboardEventTarget()
    11731173{
     1174#if 0
    11741175    WindowLayer* window = _CurrentWindows().LastWindow();
    11751176    if (window != NULL && window->Feel() == kMenuWindowFeel)
    11761177        return &window->EventTarget();
    1177 
     1178#endif
    11781179    if (FocusWindow() != NULL)
    11791180        return &FocusWindow()->EventTarget();
    11801181