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
This commit is contained in:
Stefano Ceccherini
2008-01-15 13:40:13 +00:00
parent 48044dcc41
commit d01f3af185
2 changed files with 34 additions and 10 deletions
+1 -1
View File
@@ -181,7 +181,7 @@ private:
BMenuItem* _Track(int* action, long start = -1); BMenuItem* _Track(int* action, long start = -1);
void _UpdateStateOpenSelect(BMenuItem* item, void _UpdateStateOpenSelect(BMenuItem* item,
bigtime_t& openTime, bigtime_t& closeTime); bigtime_t& openTime, const int32 &mouseSpeed);
void _UpdateStateClose(BMenuItem* item, const BPoint& where, void _UpdateStateClose(BMenuItem* item, const BPoint& where,
const uint32& buttons); const uint32& buttons);
+33 -9
View File
@@ -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 * BMenuItem *
@@ -1406,6 +1408,8 @@ BMenu::_Track(int *action, long start)
UnlockLooper(); UnlockLooper();
} }
int32 mouseSpeed = 0;
bigtime_t pollTime = system_time();
bool releasedOnce = buttons == 0; bool releasedOnce = buttons == 0;
while (fState != MENU_STATE_CLOSED) { while (fState != MENU_STATE_CLOSED) {
if (_CustomTrackingWantsToQuit()) if (_CustomTrackingWantsToQuit())
@@ -1423,7 +1427,7 @@ BMenu::_Track(int *action, long start)
item = _HitTestItems(location, B_ORIGIN); item = _HitTestItems(location, B_ORIGIN);
if (item != NULL) { if (item != NULL) {
_UpdateStateOpenSelect(item, openTime, closeTime); _UpdateStateOpenSelect(item, openTime, mouseSpeed);
if (!releasedOnce) if (!releasedOnce)
releasedOnce = true; releasedOnce = true;
@@ -1477,16 +1481,33 @@ BMenu::_Track(int *action, long start)
BPoint newLocation; BPoint newLocation;
uint32 newButtons; uint32 newButtons;
bigtime_t newPollTime = system_time();
if (LockLooper()) { if (LockLooper()) {
GetMouse(&newLocation, &newButtons, true); 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 (newLocation != location || newButtons != buttons) {
if (!releasedOnce && newButtons == 0 && buttons != 0) if (!releasedOnce && newButtons == 0 && buttons != 0)
releasedOnce = true; releasedOnce = true;
location = newLocation; location = newLocation;
buttons = newButtons; buttons = newButtons;
} }
if (releasedOnce) if (releasedOnce)
@@ -1511,21 +1532,24 @@ BMenu::_Track(int *action, long start)
void void
BMenu::_UpdateStateOpenSelect(BMenuItem* item, bigtime_t& openTime, BMenu::_UpdateStateOpenSelect(BMenuItem* item, bigtime_t& openTime,
bigtime_t& closeTime) const int32 &mouseSpeed)
{ {
if (fState == MENU_STATE_CLOSED) if (fState == MENU_STATE_CLOSED)
return; return;
if (item != fSelected && system_time() > closeTime + kHysteresis) { if (item != fSelected) {
_SelectItem(item, false); if (mouseSpeed < kMouseMotionThreshold) {
openTime = system_time(); _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 } else if (system_time() > kHysteresis + openTime && item->Submenu() != NULL
&& item->Submenu()->Window() == NULL) { && item->Submenu()->Window() == NULL) {
// Open the submenu if it's not opened yet, but only if // Open the submenu if it's not opened yet, but only if
// the mouse pointer stayed over there for some time // the mouse pointer stayed over there for some time
// (hysteresis) // (hysteresis)
_SelectItem(item); _SelectItem(item);
closeTime = system_time();
} }
if (fState != MENU_STATE_TRACKING) if (fState != MENU_STATE_TRACKING)
fState = MENU_STATE_TRACKING; fState = MENU_STATE_TRACKING;