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 <[email protected]> Reviewed-by: waddlesplash <[email protected]> Reviewed-by: Ryan Leavengood <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
9e54316c52
commit
75e5739772
@@ -4905,6 +4905,40 @@ BView::MessageReceived(BMessage* message)
|
|||||||
{
|
{
|
||||||
if (!message->HasSpecifiers()) {
|
if (!message->HasSpecifiers()) {
|
||||||
switch (message->what) {
|
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:
|
case B_VIEW_RESIZED:
|
||||||
FrameResized(message->GetInt32("width", 0),
|
FrameResized(message->GetInt32("width", 0),
|
||||||
message->GetInt32("height", 0));
|
message->GetInt32("height", 0));
|
||||||
@@ -4914,6 +4948,14 @@ BView::MessageReceived(BMessage* message)
|
|||||||
FrameMoved(fParentOffset);
|
FrameMoved(fParentOffset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case B_MOUSE_DOWN:
|
||||||
|
{
|
||||||
|
BPoint where;
|
||||||
|
message->FindPoint("be:view_where", &where);
|
||||||
|
MouseDown(where);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case B_MOUSE_IDLE:
|
case B_MOUSE_IDLE:
|
||||||
{
|
{
|
||||||
BPoint where;
|
BPoint where;
|
||||||
@@ -4928,6 +4970,85 @@ BView::MessageReceived(BMessage* message)
|
|||||||
break;
|
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:
|
case B_MOUSE_WHEEL_CHANGED:
|
||||||
{
|
{
|
||||||
BScrollBar* horizontal = ScrollBar(B_HORIZONTAL);
|
BScrollBar* horizontal = ScrollBar(B_HORIZONTAL);
|
||||||
|
|||||||
@@ -1148,163 +1148,15 @@ FrameMoved(origin);
|
|||||||
target->MessageReceived(message);
|
target->MessageReceived(message);
|
||||||
break;
|
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:
|
case B_KEY_DOWN:
|
||||||
{
|
if (!_HandleKeyDown(message))
|
||||||
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
|
|
||||||
target->MessageReceived(message);
|
target->MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case B_UNMAPPED_KEY_DOWN:
|
case B_UNMAPPED_KEY_DOWN:
|
||||||
{
|
|
||||||
if (!_HandleUnmappedKeyDown(message))
|
if (!_HandleUnmappedKeyDown(message))
|
||||||
target->MessageReceived(message);
|
target->MessageReceived(message);
|
||||||
break;
|
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:
|
case B_PULSE:
|
||||||
if (target == this && fPulseRunner) {
|
if (target == this && fPulseRunner) {
|
||||||
|
|||||||
Reference in New Issue
Block a user