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
This commit is contained in:
Axel Dörfler 2006-08-24 09:52:12 +00:00
parent c944ee6c2d
commit fa407130aa
3 changed files with 75 additions and 12 deletions

View File

@ -310,6 +310,8 @@ private:
void _SanitizeMessage(BMessage* message,
BHandler* target,
bool usePreferred);
bool _StealMouseMessage(BMessage* message,
bool& deleteMessage);
bool InUpdate();
void _DequeueAll();

View File

@ -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;
}
}

View File

@ -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.