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:
parent
9e54316c52
commit
75e5739772
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user