From 92b292f540c9d73b8fe35519a82ad2b86f8974ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 11 Jan 2006 12:25:06 +0000 Subject: [PATCH] Implemented B_NO_POINTER_HISTORY. Window moving/resizing uses this mechanism as well now, and makes quite a difference in Qemu. Not tested for standard BViews, though. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15907 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/Desktop.cpp | 12 ++--- src/servers/app/EventDispatcher.cpp | 68 +++++++++++++++++++++-------- src/servers/app/EventDispatcher.h | 6 ++- src/servers/app/EventStream.cpp | 25 ++++++++--- src/servers/app/EventStream.h | 5 +++ src/servers/app/WindowLayer.cpp | 14 +++--- src/servers/app/WindowLayer.h | 3 +- 7 files changed, 96 insertions(+), 37 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index f0c6d2eea0..a06f7fac9e 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -53,7 +53,7 @@ class KeyboardFilter : public EventFilter { KeyboardFilter(Desktop* desktop); virtual filter_result Filter(BMessage* message, EventTarget** _target, - int32* _viewToken); + int32* _viewToken, BMessage* latestMouseMoved); private: Desktop* fDesktop; @@ -66,7 +66,7 @@ class MouseFilter : public EventFilter { MouseFilter(Desktop* desktop); virtual filter_result Filter(BMessage* message, EventTarget** _target, - int32* _viewToken); + int32* _viewToken, BMessage* latestMouseMoved); private: Desktop* fDesktop; @@ -87,7 +87,7 @@ KeyboardFilter::KeyboardFilter(Desktop* desktop) filter_result KeyboardFilter::Filter(BMessage* message, EventTarget** _target, - int32* /*_viewToken*/) + int32* /*_viewToken*/, BMessage* /*latestMouseMoved*/) { int32 key; int32 modifiers; @@ -190,7 +190,8 @@ MouseFilter::MouseFilter(Desktop* desktop) filter_result -MouseFilter::Filter(BMessage* message, EventTarget** _target, int32* _viewToken) +MouseFilter::Filter(BMessage* message, EventTarget** _target, int32* _viewToken, + BMessage* latestMouseMoved) { BPoint where; if (message->FindPoint("where", &where) != B_OK) @@ -216,7 +217,8 @@ MouseFilter::Filter(BMessage* message, EventTarget** _target, int32* _viewToken) break; case B_MOUSE_MOVED: - window->MouseMoved(message, where, _viewToken); + window->MouseMoved(message, where, _viewToken, + latestMouseMoved == NULL || latestMouseMoved == message); break; } diff --git a/src/servers/app/EventDispatcher.cpp b/src/servers/app/EventDispatcher.cpp index 2e177f219d..7363fd2a13 100644 --- a/src/servers/app/EventDispatcher.cpp +++ b/src/servers/app/EventDispatcher.cpp @@ -61,6 +61,7 @@ struct event_listener { uint32 temporary_options; uint32 EffectiveEventMask() const { return event_mask | temporary_event_mask; } + uint32 EffectiveOptions() const { return options | temporary_options; } }; static const char* kTokenName = "_token"; @@ -220,6 +221,7 @@ EventDispatcher::EventDispatcher() fMouseFilter(NULL), fKeyboardFilter(NULL), fTargets(10), + fNextLatestMouseMoved(NULL), fCursorLock("cursor loop lock"), fHWInterface(NULL) { @@ -550,25 +552,36 @@ EventDispatcher::_SendMessage(BMessenger& messenger, BMessage* message, bool -EventDispatcher::_AddTokens(BMessage* message, EventTarget* target, uint32 eventMask) +EventDispatcher::_AddTokens(BMessage* message, EventTarget* target, + uint32 eventMask, BMessage* nextMouseMoved, int32* _viewToken) { _RemoveTokens(message); int32 count = target->CountListeners(); - for (int32 i = count; i-- > 0;) { + int32 added = 0; + + for (int32 i = 0; i < count; i++) { event_listener* listener = target->ListenerAt(i); - if ((listener->EffectiveEventMask() & eventMask) == 0) { - count--; + if ((listener->EffectiveEventMask() & eventMask) == 0) + continue; + + if (nextMouseMoved != NULL + && (listener->EffectiveOptions() & B_NO_POINTER_HISTORY) != 0 + && message != nextMouseMoved) { + if (listener->token == *_viewToken) { + // focus view doesn't want to get pointer history + *_viewToken = B_NULL_TOKEN; + } continue; } ETRACE((" add token %ld\n", listener->token)); - if (message->AddInt32(kTokenName, listener->token) != B_OK) - count--; + if (message->AddInt32(kTokenName, listener->token) == B_OK) + added++; } - return count != 0; + return added != 0; } @@ -664,14 +677,17 @@ EventDispatcher::_EventLoop() } } - // TODO: this drops older mouse events, but should probably work - // a bit different (ie. don't drop the last event) - bigtime_t eventTime; - if (event->FindInt64("when", &eventTime) == B_OK) { - if (system_time() - eventTime > 25000) { - // the server itself lags behind too much - // -> drop the event - break; + // This is for B_NO_POINTER_HISTORY - we always want the + // latest mouse moved event in the queue only + if (fNextLatestMouseMoved == NULL) + fNextLatestMouseMoved = fStream->PeekLatestMouseMoved(); + else if (fNextLatestMouseMoved != event) { + // Drop older mouse moved messages if the server is lagging too + // much (if the message is older than 100 msecs) + bigtime_t eventTime; + if (event->FindInt64("when", &eventTime) == B_OK) { + if (system_time() - eventTime > 100000) + break; } } @@ -691,7 +707,8 @@ EventDispatcher::_EventLoop() EventTarget* mouseTarget = fPreviousMouseTarget; int32 viewToken = B_NULL_TOKEN; - if (fMouseFilter->Filter(event, &mouseTarget, &viewToken) == B_SKIP_MESSAGE) { + if (fMouseFilter->Filter(event, &mouseTarget, &viewToken, + fNextLatestMouseMoved) == B_SKIP_MESSAGE) { // this is a work-around if the wrong B_MOUSE_UP // event is filtered out if (event->what == B_MOUSE_UP) { @@ -728,11 +745,21 @@ EventDispatcher::_EventLoop() current = fPreviousMouseTarget = mouseTarget; if (current != NULL) { - addedTokens |= _AddTokens(event, current, B_POINTER_EVENTS); + int32 focusView = viewToken; + addedTokens |= _AddTokens(event, current, B_POINTER_EVENTS, + fNextLatestMouseMoved, &focusView); + + bool noPointerHistoryFocus = focusView != viewToken; + if (viewToken != B_NULL_TOKEN) event->AddInt32("_view_token", viewToken); - if (addedTokens) + + if (addedTokens && !noPointerHistoryFocus) _SetFeedFocus(event); + else if (noPointerHistoryFocus) { + // no tokens were added or the focus shouldn't get a mouse moved + break; + } _SendMessage(current->Messenger(), event, event->what == B_MOUSE_MOVED ? kMouseMovedImportance : kStandardImportance); @@ -801,7 +828,8 @@ EventDispatcher::_EventLoop() // don't send the message if there are no tokens for this event if (!_AddTokens(event, target, - keyboardEvent ? B_KEYBOARD_EVENTS : B_POINTER_EVENTS)) + keyboardEvent ? B_KEYBOARD_EVENTS : B_POINTER_EVENTS, + event->what == B_MOUSE_MOVED ? fNextLatestMouseMoved : NULL)) continue; if (!_SendMessage(target->Messenger(), event, event->what == B_MOUSE_MOVED @@ -819,6 +847,8 @@ EventDispatcher::_EventLoop() } } + if (fNextLatestMouseMoved == event) + fNextLatestMouseMoved = NULL; delete event; } } diff --git a/src/servers/app/EventDispatcher.h b/src/servers/app/EventDispatcher.h index 72c73d0658..fad06667f7 100644 --- a/src/servers/app/EventDispatcher.h +++ b/src/servers/app/EventDispatcher.h @@ -55,7 +55,7 @@ class EventTarget { class EventFilter { public: virtual filter_result Filter(BMessage* event, EventTarget** _target, - int32* _viewToken = NULL) = 0; + int32* _viewToken = NULL, BMessage* latestMouseMoved = NULL) = 0; }; class EventDispatcher : public BLocker { @@ -96,7 +96,8 @@ class EventDispatcher : public BLocker { bool _SendMessage(BMessenger& messenger, BMessage* message, float importance); - bool _AddTokens(BMessage* message, EventTarget* target, uint32 eventMask); + bool _AddTokens(BMessage* message, EventTarget* target, uint32 eventMask, + BMessage* nextMouseMoved = NULL, int32* _viewToken = NULL); void _RemoveTokens(BMessage* message); void _SetFeedFocus(BMessage* message); void _UnsetFeedFocus(BMessage* message); @@ -130,6 +131,7 @@ class EventDispatcher : public BLocker { BObjectList fTargets; + BMessage* fNextLatestMouseMoved; BPoint fLastCursorPosition; int32 fLastButtons; diff --git a/src/servers/app/EventStream.cpp b/src/servers/app/EventStream.cpp index 6284c01060..4af3f6cb1c 100644 --- a/src/servers/app/EventStream.cpp +++ b/src/servers/app/EventStream.cpp @@ -49,7 +49,8 @@ InputServerStream::InputServerStream(BMessenger& messenger) : fInputServer(messenger), fPort(-1), - fQuitting(false) + fQuitting(false), + fLatestMouseMoved(NULL) { BMessage message(IS_ACQUIRE_INPUT); fCursorArea = create_area("shared cursor", (void **)&fCursorBuffer, B_ANY_ADDRESS, @@ -72,7 +73,8 @@ InputServerStream::InputServerStream(BMessenger& messenger) InputServerStream::InputServerStream() : fQuitting(false), - fCursorSemaphore(-1) + fCursorSemaphore(-1), + fLatestMouseMoved(NULL) { fPort = find_port(SERVER_INPUT_PORT); } @@ -122,9 +124,12 @@ InputServerStream::GetNextEvent(BMessage** _event) // wait for new events BMessage* event; status_t status = _MessageFromPort(&event); - if (status == B_OK) + if (status == B_OK) { + if (event->what == B_MOUSE_MOVED) + fLatestMouseMoved = event; + fEvents.AddMessage(event); - else if (status == B_BAD_PORT_ID) { + } else if (status == B_BAD_PORT_ID) { // our port got deleted - the input_server must have died fPort = -1; return false; @@ -134,8 +139,11 @@ InputServerStream::GetNextEvent(BMessage** _event) if (count > 0) { // empty port queue completely while we're at it for (int32 i = 0; i < count; i++) { - if (_MessageFromPort(&event, 0) == B_OK) + if (_MessageFromPort(&event, 0) == B_OK) { + if (event->what == B_MOUSE_MOVED) + fLatestMouseMoved = event; fEvents.AddMessage(event); + } } } } @@ -183,6 +191,13 @@ InputServerStream::GetNextCursorPosition(BPoint &where) } +BMessage* +InputServerStream::PeekLatestMouseMoved() +{ + return fLatestMouseMoved; +} + + status_t InputServerStream::_MessageFromPort(BMessage** _message, bigtime_t timeout) { diff --git a/src/servers/app/EventStream.h b/src/servers/app/EventStream.h index d24d51531e..4cc78fb792 100644 --- a/src/servers/app/EventStream.h +++ b/src/servers/app/EventStream.h @@ -31,6 +31,8 @@ class EventStream { virtual bool GetNextEvent(BMessage** _event) = 0; virtual bool GetNextCursorPosition(BPoint& where); + + virtual BMessage* PeekLatestMouseMoved() = 0; }; @@ -53,6 +55,8 @@ class InputServerStream : public EventStream { virtual bool GetNextEvent(BMessage** _event); virtual bool GetNextCursorPosition(BPoint& where); + virtual BMessage* PeekLatestMouseMoved(); + private: status_t _MessageFromPort(BMessage** _message, bigtime_t timeout = B_INFINITE_TIMEOUT); @@ -64,6 +68,7 @@ class InputServerStream : public EventStream { sem_id fCursorSemaphore; area_id fCursorArea; shared_cursor* fCursorBuffer; + BMessage* fLatestMouseMoved; }; #endif /* EVENT_STREAM_H */ diff --git a/src/servers/app/WindowLayer.cpp b/src/servers/app/WindowLayer.cpp index 1be14bf19b..817048a543 100644 --- a/src/servers/app/WindowLayer.cpp +++ b/src/servers/app/WindowLayer.cpp @@ -905,10 +905,17 @@ WindowLayer::MouseUp(BMessage* msg, BPoint where, int32* _viewToken) void -WindowLayer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken) +WindowLayer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken, + bool isLatestMouseMoved) { - if (fDecorator) { + if (ViewLayer* view = ViewAt(where)) + *_viewToken = view->Token(); + // ignore pointer history + if (!isLatestMouseMoved) + return; + + if (fDecorator) { BRegion visibleBorder; GetBorderRegion(&visibleBorder); visibleBorder.IntersectWith(&VisibleRegion()); @@ -971,9 +978,6 @@ WindowLayer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken) if (desktopSettings.MouseMode() != B_NORMAL_MOUSE && !IsFocus()) fDesktop->SetFocusWindow(this); - - if (ViewLayer* view = ViewAt(where)) - *_viewToken = view->Token(); } diff --git a/src/servers/app/WindowLayer.h b/src/servers/app/WindowLayer.h index 0e12781efc..b8ecde570d 100644 --- a/src/servers/app/WindowLayer.h +++ b/src/servers/app/WindowLayer.h @@ -118,7 +118,8 @@ class WindowLayer { void MouseDown(BMessage* message, BPoint where, int32* _viewToken); void MouseUp(BMessage* message, BPoint where, int32* _viewToken); - void MouseMoved(BMessage* message, BPoint where, int32* _viewToken); + void MouseMoved(BMessage* message, BPoint where, int32* _viewToken, + bool isLatestMouseMoved); // some hooks to inform the client window // TODO: move this to ServerWindow maybe?