From fa407130aaf427956a50adf6b31781d26e8fb52d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 24 Aug 2006 09:52:12 +0000 Subject: [PATCH] Now this should nail down bug #762 pretty well: BView::GetMouse() no calls the private BWindow::_StealMouseMessage() which makes sure only messages for the preferred handler are stolen, and also, that nothing gets lost that shouldn't get lost. Also updates the fLastMouseMoved view in case the message is actually removed due to GetMouse(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18601 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/interface/Window.h | 2 ++ src/kits/interface/View.cpp | 24 ++++++++------ src/kits/interface/Window.cpp | 61 +++++++++++++++++++++++++++++++++-- 3 files changed, 75 insertions(+), 12 deletions(-) diff --git a/headers/os/interface/Window.h b/headers/os/interface/Window.h index 072ef913ed..9f65bac427 100644 --- a/headers/os/interface/Window.h +++ b/headers/os/interface/Window.h @@ -310,6 +310,8 @@ private: void _SanitizeMessage(BMessage* message, BHandler* target, bool usePreferred); + bool _StealMouseMessage(BMessage* message, + bool& deleteMessage); bool InUpdate(); void _DequeueAll(); diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index b0599057f0..ec74c9011d 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -1337,21 +1337,27 @@ BView::GetMouse(BPoint *location, uint32 *buttons, bool checkMessageQueue) // Look out for mouse update messages - BMessage *msg; - for (int32 i = 0; (msg = queue->FindMessage(i)) != NULL; i++) { - switch (msg->what) { + BMessage *message; + for (int32 i = 0; (message = queue->FindMessage(i)) != NULL; i++) { + switch (message->what) { + case B_MOUSE_MOVED: case B_MOUSE_UP: case B_MOUSE_DOWN: - case B_MOUSE_MOVED: - msg->FindPoint("screen_where", location); - msg->FindInt32("buttons", (int32 *)buttons); + bool deleteMessage; + if (!Window()->_StealMouseMessage(message, deleteMessage)) + continue; + + message->FindPoint("screen_where", location); + message->FindInt32("buttons", (int32 *)buttons); + queue->Unlock(); + // we need to hold the queue lock until here, because + // the message might still be used for something else ConvertFromScreen(location); - queue->RemoveMessage(msg); - delete msg; + if (deleteMessage) + delete message; - queue->Unlock(); return; } } diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp index b356e6f282..89910d7e69 100644 --- a/src/kits/interface/Window.cpp +++ b/src/kits/interface/Window.cpp @@ -2530,8 +2530,7 @@ BWindow::task_looper() while (_UnpackMessage(cookie, &fLastMessage, &handler, &usePreferred)) { // if there is no target handler, the message is dropped if (handler != NULL) { - if (handler != NULL) - _SanitizeMessage(fLastMessage, handler, usePreferred); + _SanitizeMessage(fLastMessage, handler, usePreferred); // Is this a scripting message? if (fLastMessage->HasSpecifiers()) { @@ -2802,8 +2801,10 @@ BWindow::_UnpackMessage(unpack_cookie& cookie, BMessage** _message, BHandler** _ return false; if (cookie.index == 0 && !cookie.tokens_scanned) { + // We were called the first time for this message + if (!*_usePreferred) { - // we only consider messages targeted at the preferred handler + // only consider messages targeted at the preferred handler cookie.message = NULL; return true; } @@ -2964,6 +2965,60 @@ BWindow::_SanitizeMessage(BMessage* message, BHandler* target, bool usePreferred } +/*! + This is called by BView::GetMouse() when a B_MOUSE_MOVED message + is removed from the queue. + It allows the window to update the last mouse moved view, and + let it decide if this message should be kept. It will also remove + the message from the queue. + You need to hold the message queue lock when calling this method! + + \return true if this message can be used to get the mouse data from, + \return false if this is not meant for the public. +*/ +bool +BWindow::_StealMouseMessage(BMessage* message, bool& deleteMessage) +{ + BMessage::Private messagePrivate(fLastMessage); + if (!messagePrivate.UsePreferredTarget()) { + // this message is targeted at a specific handler, so we should + // not steal it + return false; + } + + int32 token; + if (message->FindInt32("_token", 0, &token) == B_OK) { + // This message has other targets, so we can't remove it; + // just prevent it from being sent to the preferred handler + // again (if it should have gotten it at all). + bool feedFocus; + if (message->FindBool("_feed_focus", &feedFocus) == B_OK && feedFocus) + return false; + + message->RemoveName("_feed_focus"); + deleteMessage = false; + } else { + // The message is only thought for the preferred handler, so we + // can just remove it. + MessageQueue()->RemoveMessage(message); + deleteMessage = true; + + if (message->what == B_MOUSE_MOVED) { + // We need to update the last mouse moved view, as this message + // won't make it to _SanitizeMessage() anymore + BView* viewUnderMouse = NULL; + int32 token; + if (message->FindInt32("_view_token", &token) == B_OK) + viewUnderMouse = _FindView(token); + + fLastMouseMovedView = viewUnderMouse; + } + } + + return true; +} + + /*! Handles keyboard input before it gets forwarded to the target handler. This includes shortcut evaluation, keyboard navigation, etc.