BWindow: Do not invoke BView handlers directly

When dispatching a message to a BView, pass the message on to the view's
MessageReceived() method rather than invoking one of its handlers (e.g.
KeyDown() or MouseDown()) directly.

This commit moves the existing handler-invoking logic from
BWindow::DispatchMessage() into BView::MessageReceived(), preserving the
existing functionality.

Fixes #15254.

Change-Id: I230c0781df13e54e08573a5a31d7550520c060d5
Reviewed-on: https://review.haiku-os.org/c/haiku/+/1723
Reviewed-by: Stephan Aßmus <superstippi@gmx.de>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Reviewed-by: Ryan Leavengood <leavengood@gmail.com>
This commit is contained in:
Simon South 2019-08-16 07:49:35 -04:00 committed by waddlesplash
parent 9e54316c52
commit 75e5739772
2 changed files with 122 additions and 149 deletions

View File

@ -4905,6 +4905,40 @@ BView::MessageReceived(BMessage* message)
{
if (!message->HasSpecifiers()) {
switch (message->what) {
case B_INVALIDATE:
{
BRect rect;
if (message->FindRect("be:area", &rect) == B_OK)
Invalidate(rect);
else
Invalidate();
break;
}
case B_KEY_DOWN:
{
// TODO: cannot use "string" here if we support having different
// font encoding per view (it's supposed to be converted by
// BWindow::_HandleKeyDown() one day)
const char* string;
ssize_t bytes;
if (message->FindData("bytes", B_STRING_TYPE,
(const void**)&string, &bytes) == B_OK)
KeyDown(string, bytes - 1);
break;
}
case B_KEY_UP:
{
// TODO: same as above
const char* string;
ssize_t bytes;
if (message->FindData("bytes", B_STRING_TYPE,
(const void**)&string, &bytes) == B_OK)
KeyUp(string, bytes - 1);
break;
}
case B_VIEW_RESIZED:
FrameResized(message->GetInt32("width", 0),
message->GetInt32("height", 0));
@ -4914,6 +4948,14 @@ BView::MessageReceived(BMessage* message)
FrameMoved(fParentOffset);
break;
case B_MOUSE_DOWN:
{
BPoint where;
message->FindPoint("be:view_where", &where);
MouseDown(where);
break;
}
case B_MOUSE_IDLE:
{
BPoint where;
@ -4928,6 +4970,85 @@ BView::MessageReceived(BMessage* message)
break;
}
case B_MOUSE_MOVED:
{
uint32 eventOptions = fEventOptions | fMouseEventOptions;
bool noHistory = eventOptions & B_NO_POINTER_HISTORY;
bool dropIfLate = !(eventOptions & B_FULL_POINTER_HISTORY);
bigtime_t eventTime;
if (message->FindInt64("when", (int64*)&eventTime) < B_OK)
eventTime = system_time();
uint32 transit;
message->FindInt32("be:transit", (int32*)&transit);
// don't drop late messages with these important transit values
if (transit == B_ENTERED_VIEW || transit == B_EXITED_VIEW)
dropIfLate = false;
// TODO: The dropping code may have the following problem: On
// slower computers, 20ms may just be to abitious a delay.
// There, we might constantly check the message queue for a
// newer message, not find any, and still use the only but later
// than 20ms message, which of course makes the whole thing
// later than need be. An adaptive delay would be kind of neat,
// but would probably use additional BWindow members to count
// the successful versus fruitless queue searches and the delay
// value itself or something similar.
if (noHistory
|| (dropIfLate && (system_time() - eventTime > 20000))) {
// filter out older mouse moved messages in the queue
BWindow* window = Window();
window->_DequeueAll();
BMessageQueue* queue = window->MessageQueue();
queue->Lock();
BMessage* moved;
for (int32 i = 0; (moved = queue->FindMessage(i)) != NULL;
i++) {
if (moved != message && moved->what == B_MOUSE_MOVED) {
// there is a newer mouse moved message in the
// queue, just ignore the current one, the newer one
// will be handled here eventually
queue->Unlock();
return;
}
}
queue->Unlock();
}
BPoint where;
uint32 buttons;
message->FindPoint("be:view_where", &where);
message->FindInt32("buttons", (int32*)&buttons);
if (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW)
HideToolTip();
BMessage* dragMessage = NULL;
if (message->HasMessage("be:drag_message")) {
dragMessage = new BMessage();
if (message->FindMessage("be:drag_message", dragMessage)
!= B_OK) {
delete dragMessage;
dragMessage = NULL;
}
}
MouseMoved(where, transit, dragMessage);
delete dragMessage;
break;
}
case B_MOUSE_UP:
{
BPoint where;
message->FindPoint("be:view_where", &where);
fMouseEventOptions = 0;
MouseUp(where);
break;
}
case B_MOUSE_WHEEL_CHANGED:
{
BScrollBar* horizontal = ScrollBar(B_HORIZONTAL);

View File

@ -1148,163 +1148,15 @@ FrameMoved(origin);
target->MessageReceived(message);
break;
case B_INVALIDATE:
{
if (BView* view = dynamic_cast<BView*>(target)) {
BRect rect;
if (message->FindRect("be:area", &rect) == B_OK)
view->Invalidate(rect);
else
view->Invalidate();
} else
target->MessageReceived(message);
break;
}
case B_KEY_DOWN:
{
if (!_HandleKeyDown(message)) {
if (BView* view = dynamic_cast<BView*>(target)) {
// TODO: cannot use "string" here if we support having
// different font encoding per view (it's supposed to be
// converted by _HandleKeyDown() one day)
const char* string;
ssize_t bytes;
if (message->FindData("bytes", B_STRING_TYPE,
(const void**)&string, &bytes) == B_OK) {
view->KeyDown(string, bytes - 1);
}
} else
target->MessageReceived(message);
}
break;
}
case B_KEY_UP:
{
// TODO: same as above
if (BView* view = dynamic_cast<BView*>(target)) {
const char* string;
ssize_t bytes;
if (message->FindData("bytes", B_STRING_TYPE,
(const void**)&string, &bytes) == B_OK) {
view->KeyUp(string, bytes - 1);
}
} else
if (!_HandleKeyDown(message))
target->MessageReceived(message);
break;
}
case B_UNMAPPED_KEY_DOWN:
{
if (!_HandleUnmappedKeyDown(message))
target->MessageReceived(message);
break;
}
case B_MOUSE_DOWN:
{
BView* view = dynamic_cast<BView*>(target);
if (view != NULL) {
BPoint where;
message->FindPoint("be:view_where", &where);
view->MouseDown(where);
} else
target->MessageReceived(message);
break;
}
case B_MOUSE_UP:
{
if (BView* view = dynamic_cast<BView*>(target)) {
BPoint where;
message->FindPoint("be:view_where", &where);
view->fMouseEventOptions = 0;
view->MouseUp(where);
} else
target->MessageReceived(message);
break;
}
case B_MOUSE_MOVED:
{
if (BView* view = dynamic_cast<BView*>(target)) {
uint32 eventOptions = view->fEventOptions
| view->fMouseEventOptions;
bool noHistory = eventOptions & B_NO_POINTER_HISTORY;
bool dropIfLate = !(eventOptions & B_FULL_POINTER_HISTORY);
bigtime_t eventTime;
if (message->FindInt64("when", (int64*)&eventTime) < B_OK)
eventTime = system_time();
uint32 transit;
message->FindInt32("be:transit", (int32*)&transit);
// don't drop late messages with these important transit values
if (transit == B_ENTERED_VIEW || transit == B_EXITED_VIEW)
dropIfLate = false;
// TODO: The dropping code may have the following problem:
// On slower computers, 20ms may just be to abitious a delay.
// There, we might constantly check the message queue for a
// newer message, not find any, and still use the only but
// later than 20ms message, which of course makes the whole
// thing later than need be. An adaptive delay would be
// kind of neat, but would probably use additional BWindow
// members to count the successful versus fruitless queue
// searches and the delay value itself or something similar.
if (noHistory
|| (dropIfLate && (system_time() - eventTime > 20000))) {
// filter out older mouse moved messages in the queue
_DequeueAll();
BMessageQueue* queue = MessageQueue();
queue->Lock();
BMessage* moved;
for (int32 i = 0; (moved = queue->FindMessage(i)) != NULL;
i++) {
if (moved != message && moved->what == B_MOUSE_MOVED) {
// there is a newer mouse moved message in the
// queue, just ignore the current one, the newer one
// will be handled here eventually
queue->Unlock();
return;
}
}
queue->Unlock();
}
BPoint where;
uint32 buttons;
message->FindPoint("be:view_where", &where);
message->FindInt32("buttons", (int32*)&buttons);
if (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW) {
if (dynamic_cast<BPrivate::ToolTipWindow*>(this) == NULL)
BToolTipManager::Manager()->HideTip();
}
BMessage* dragMessage = NULL;
if (message->HasMessage("be:drag_message")) {
dragMessage = new BMessage();
if (message->FindMessage("be:drag_message", dragMessage)
!= B_OK) {
delete dragMessage;
dragMessage = NULL;
}
}
view->MouseMoved(where, transit, dragMessage);
delete dragMessage;
} else
target->MessageReceived(message);
break;
}
case B_PULSE:
if (target == this && fPulseRunner) {