From d01f3af185a87ddb6f2b71a0609fc4c0869ad846 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Tue, 15 Jan 2008 13:40:13 +0000 Subject: [PATCH] Menu tracking now ignores mouse movements if they are too fast (suggested by stippi). The movement threshold will be subject to changes, as I only tested on vmware and it's probably too high. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23528 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/interface/Menu.h | 2 +- src/kits/interface/Menu.cpp | 42 +++++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/headers/os/interface/Menu.h b/headers/os/interface/Menu.h index ccb11ccbb4..9223fcc0c2 100644 --- a/headers/os/interface/Menu.h +++ b/headers/os/interface/Menu.h @@ -181,7 +181,7 @@ private: BMenuItem* _Track(int* action, long start = -1); void _UpdateStateOpenSelect(BMenuItem* item, - bigtime_t& openTime, bigtime_t& closeTime); + bigtime_t& openTime, const int32 &mouseSpeed); void _UpdateStateClose(BMenuItem* item, const BPoint& where, const uint32& buttons); diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index 49e228199c..c04ba527fd 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -1384,7 +1384,9 @@ BMenu::_Hide() } -const bigtime_t kHysteresis = 200000; // TODO: Test and reduce if needed. +const static bigtime_t kHysteresis = 200000; // TODO: Test and reduce if needed. +const static int32 kMouseMotionThreshold = 15; + // TODO: Same as above. Actually, we could get rid of the kHysteresis BMenuItem * @@ -1406,6 +1408,8 @@ BMenu::_Track(int *action, long start) UnlockLooper(); } + int32 mouseSpeed = 0; + bigtime_t pollTime = system_time(); bool releasedOnce = buttons == 0; while (fState != MENU_STATE_CLOSED) { if (_CustomTrackingWantsToQuit()) @@ -1423,7 +1427,7 @@ BMenu::_Track(int *action, long start) item = _HitTestItems(location, B_ORIGIN); if (item != NULL) { - _UpdateStateOpenSelect(item, openTime, closeTime); + _UpdateStateOpenSelect(item, openTime, mouseSpeed); if (!releasedOnce) releasedOnce = true; @@ -1477,16 +1481,33 @@ BMenu::_Track(int *action, long start) BPoint newLocation; uint32 newButtons; + + bigtime_t newPollTime = system_time(); if (LockLooper()) { GetMouse(&newLocation, &newButtons, true); - UnlockLooper(); + UnlockLooper(); } + +#if 1 + // TODO: on vmware, looks like the second system_time() could return + // a value smaller than the first call. Bug in VMWare or haiku ? + if (newPollTime <= pollTime) + newPollTime = pollTime + 100000; +#endif + //printf("newPollTime - pollTime: %lld\n", newPollTime - pollTime); + // mouseSpeed in px per ms + // (actually point_distance returns the square of the distance, + // so it's more px^2 per ms) + mouseSpeed = (int32)(point_distance(newLocation, location) * 1000 / (newPollTime - pollTime)); + pollTime = newPollTime; + + //printf("mouseSpeed = %ld\n", mouseSpeed); if (newLocation != location || newButtons != buttons) { if (!releasedOnce && newButtons == 0 && buttons != 0) releasedOnce = true; location = newLocation; - buttons = newButtons; + buttons = newButtons; } if (releasedOnce) @@ -1511,21 +1532,24 @@ BMenu::_Track(int *action, long start) void BMenu::_UpdateStateOpenSelect(BMenuItem* item, bigtime_t& openTime, - bigtime_t& closeTime) + const int32 &mouseSpeed) { if (fState == MENU_STATE_CLOSED) return; - if (item != fSelected && system_time() > closeTime + kHysteresis) { - _SelectItem(item, false); - openTime = system_time(); + if (item != fSelected) { + if (mouseSpeed < kMouseMotionThreshold) { + _SelectItem(item, false); + openTime = system_time(); + } else { + //printf("Mouse moving too fast (%ld), ignoring...\n", mouseSpeed); + } } 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(); } if (fState != MENU_STATE_TRACKING) fState = MENU_STATE_TRACKING;