Next big step in the event handling:
* RootLayer's mouse event processing is now at its minimum - the EventDispatcher handles them now. As a result, a window will now get only one message per event. * RootLayer adds "_view_token" to mouse moved messages that specify the view currently under the cursor. * There is now a mouse event layer in RootLayer that gets preferred when it's set - this is now used for the window moving instead of the previous mechanism. * changed the previous DistributeMessage() to an UnpackMessage() method following Adi's suggestion. * caveat: some things might be functionally broken in RootLayer now because of removing the mouse notification stuff. * "be:transit" handling is now done completely client side by BWindow::_SanitizeMessage(() (similar to what the input_server does). This should also make the mechanism pretty robust, since every B_MOUSE_MOVED message can now trigger the view transit (in case a message is lost). B_WINDOW_ACTIVATED messages should be generated client side as well. * renamed AS_LAYER_GET_MOUSE_COORDS to AS_GET_MOUSE as it's not a layer specific command, and also gets the mouse buttons. * B_MOUSE_* messages from the up server now contain only a "screen_where" field; "where" (in window's coordinates) and "be:view_where" are added in BMessage::_SanitizeMessage(). * messages that don't have a valid target in the looper are now dropped instead of being sent to the looper - this should be done in BLooper as well, though. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15087 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -226,6 +226,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
typedef BLooper inherited;
|
typedef BLooper inherited;
|
||||||
|
struct unpack_cookie;
|
||||||
class Shortcut;
|
class Shortcut;
|
||||||
|
|
||||||
friend class BApplication;
|
friend class BApplication;
|
||||||
@@ -267,7 +268,10 @@ private:
|
|||||||
void AddShortcut(uint32 key, uint32 modifiers,
|
void AddShortcut(uint32 key, uint32 modifiers,
|
||||||
BMenuItem* item);
|
BMenuItem* item);
|
||||||
BHandler* _DetermineTarget(BMessage* message, BHandler* target);
|
BHandler* _DetermineTarget(BMessage* message, BHandler* target);
|
||||||
bool _DistributeMessage(BMessage* message, BHandler* target);
|
bool _UnpackMessage(unpack_cookie& state, BMessage** _message,
|
||||||
|
BHandler** _target, bool* _usePreferred);
|
||||||
|
void _SanitizeMessage(BMessage* message, BHandler* target,
|
||||||
|
bool usePreferred);
|
||||||
|
|
||||||
bool InUpdate();
|
bool InUpdate();
|
||||||
void _DequeueAll();
|
void _DequeueAll();
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ enum {
|
|||||||
AS_RUN_BE_ABOUT,
|
AS_RUN_BE_ABOUT,
|
||||||
AS_SET_MOUSE_MODE,
|
AS_SET_MOUSE_MODE,
|
||||||
AS_GET_MOUSE_MODE,
|
AS_GET_MOUSE_MODE,
|
||||||
|
AS_GET_MOUSE,
|
||||||
|
|
||||||
// Hook function messages
|
// Hook function messages
|
||||||
AS_WORKSPACE_ACTIVATED,
|
AS_WORKSPACE_ACTIVATED,
|
||||||
@@ -260,7 +261,6 @@ enum {
|
|||||||
AS_LAYER_END_RECT_TRACK,
|
AS_LAYER_END_RECT_TRACK,
|
||||||
AS_LAYER_DRAG_RECT,
|
AS_LAYER_DRAG_RECT,
|
||||||
AS_LAYER_DRAG_IMAGE,
|
AS_LAYER_DRAG_IMAGE,
|
||||||
AS_LAYER_GET_MOUSE_COORDS,
|
|
||||||
AS_LAYER_SCROLL,
|
AS_LAYER_SCROLL,
|
||||||
AS_LAYER_SET_LINE_MODE,
|
AS_LAYER_SET_LINE_MODE,
|
||||||
AS_LAYER_GET_LINE_MODE,
|
AS_LAYER_GET_LINE_MODE,
|
||||||
|
|||||||
@@ -1353,12 +1353,9 @@ BView::GetMouse(BPoint *location, uint32 *buttons, bool checkMessageQueue)
|
|||||||
case B_MOUSE_UP:
|
case B_MOUSE_UP:
|
||||||
case B_MOUSE_DOWN:
|
case B_MOUSE_DOWN:
|
||||||
case B_MOUSE_MOVED:
|
case B_MOUSE_MOVED:
|
||||||
{
|
msg->FindPoint("screen_where", location);
|
||||||
msg->FindPoint("where", location);
|
|
||||||
msg->FindInt32("buttons", (int32 *)buttons);
|
msg->FindInt32("buttons", (int32 *)buttons);
|
||||||
|
|
||||||
// ToDo: the "where" coordinates are screen coordinates
|
|
||||||
// unlike R5 - this might break applications!
|
|
||||||
ConvertFromScreen(location);
|
ConvertFromScreen(location);
|
||||||
|
|
||||||
queue->RemoveMessage(msg);
|
queue->RemoveMessage(msg);
|
||||||
@@ -1366,7 +1363,6 @@ BView::GetMouse(BPoint *location, uint32 *buttons, bool checkMessageQueue)
|
|||||||
|
|
||||||
queue->Unlock();
|
queue->Unlock();
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queue->Unlock();
|
queue->Unlock();
|
||||||
@@ -1375,7 +1371,7 @@ BView::GetMouse(BPoint *location, uint32 *buttons, bool checkMessageQueue)
|
|||||||
// If no mouse update message has been found in the message queue,
|
// If no mouse update message has been found in the message queue,
|
||||||
// we get the current mouse location and buttons from the app_server
|
// we get the current mouse location and buttons from the app_server
|
||||||
|
|
||||||
fOwner->fLink->StartMessage(AS_LAYER_GET_MOUSE_COORDS);
|
fOwner->fLink->StartMessage(AS_GET_MOUSE);
|
||||||
|
|
||||||
int32 code;
|
int32 code;
|
||||||
if (fOwner->fLink->FlushWithReply(code) == B_OK
|
if (fOwner->fLink->FlushWithReply(code) == B_OK
|
||||||
|
|||||||
+226
-117
@@ -43,6 +43,18 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct BWindow::unpack_cookie {
|
||||||
|
unpack_cookie();
|
||||||
|
|
||||||
|
BMessage* message;
|
||||||
|
int32 index;
|
||||||
|
BHandler* focus;
|
||||||
|
int32 focus_token;
|
||||||
|
int32 last_view_token;
|
||||||
|
bool found_focus;
|
||||||
|
bool tokens_scanned;
|
||||||
|
};
|
||||||
|
|
||||||
class BWindow::Shortcut {
|
class BWindow::Shortcut {
|
||||||
public:
|
public:
|
||||||
Shortcut(uint32 key, uint32 modifiers, BMenuItem* item);
|
Shortcut(uint32 key, uint32 modifiers, BMenuItem* item);
|
||||||
@@ -135,6 +147,22 @@ _set_menu_sem_(BWindow *window, sem_id sem)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
BWindow::unpack_cookie::unpack_cookie()
|
||||||
|
:
|
||||||
|
message((BMessage*)~0UL),
|
||||||
|
// message == NULL is our exit condition
|
||||||
|
index(0),
|
||||||
|
focus_token(B_NULL_TOKEN),
|
||||||
|
last_view_token(B_NULL_TOKEN),
|
||||||
|
found_focus(false),
|
||||||
|
tokens_scanned(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
BWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMenuItem* item)
|
BWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMenuItem* item)
|
||||||
:
|
:
|
||||||
fKey(PrepareKey(key)),
|
fKey(PrepareKey(key)),
|
||||||
@@ -810,38 +838,24 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target)
|
|||||||
case B_MOUSE_DOWN:
|
case B_MOUSE_DOWN:
|
||||||
{
|
{
|
||||||
BPoint where;
|
BPoint where;
|
||||||
uint32 modifiers;
|
msg->FindPoint("be:view_where", &where);
|
||||||
uint32 buttons;
|
|
||||||
int32 clicks;
|
|
||||||
msg->FindPoint("where", &where);
|
|
||||||
msg->FindInt32("modifiers", (int32 *)&modifiers);
|
|
||||||
msg->FindInt32("buttons", (int32 *)&buttons);
|
|
||||||
msg->FindInt32("clicks", &clicks);
|
|
||||||
|
|
||||||
if (target && target != this && target != fTopView) {
|
if (BView *view = dynamic_cast<BView *>(target))
|
||||||
if (BView *view = dynamic_cast<BView *>(target)) {
|
view->MouseDown(where);
|
||||||
view->ConvertFromScreen(&where);
|
else
|
||||||
view->MouseDown(where);
|
target->MessageReceived(msg);
|
||||||
} else
|
|
||||||
target->MessageReceived(msg);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_MOUSE_UP:
|
case B_MOUSE_UP:
|
||||||
{
|
{
|
||||||
BPoint where;
|
BPoint where;
|
||||||
uint32 modifiers;
|
msg->FindPoint("be:view_where", &where);
|
||||||
msg->FindPoint("where", &where);
|
|
||||||
msg->FindInt32("modifiers", (int32 *)&modifiers);
|
|
||||||
|
|
||||||
if (target && target != this && target != fTopView) {
|
if (BView *view = dynamic_cast<BView *>(target))
|
||||||
if (BView *view = dynamic_cast<BView *>(target)) {
|
view->MouseUp(where);
|
||||||
view->ConvertFromScreen(&where);
|
else
|
||||||
view->MouseUp(where);
|
target->MessageReceived(msg);
|
||||||
} else
|
|
||||||
target->MessageReceived(msg);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -850,24 +864,14 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target)
|
|||||||
BPoint where;
|
BPoint where;
|
||||||
uint32 buttons;
|
uint32 buttons;
|
||||||
uint32 transit;
|
uint32 transit;
|
||||||
msg->FindPoint("where", &where);
|
msg->FindPoint("be:view_where", &where);
|
||||||
msg->FindInt32("buttons", (int32 *)&buttons);
|
msg->FindInt32("buttons", (int32 *)&buttons);
|
||||||
msg->FindInt32("transit", (int32 *)&transit);
|
msg->FindInt32("be:transit", (int32 *)&transit);
|
||||||
if (target && target != this && target != fTopView) {
|
|
||||||
if (BView *view = dynamic_cast<BView *>(target)) {
|
if (BView *view = dynamic_cast<BView *>(target))
|
||||||
if (fLastMouseMovedView != view) {
|
view->MouseMoved(where, transit, NULL);
|
||||||
if (fLastMouseMovedView) {
|
else
|
||||||
BPoint p(where);
|
target->MessageReceived(msg);
|
||||||
fLastMouseMovedView->ConvertFromScreen(&p);
|
|
||||||
fLastMouseMovedView->MouseMoved(p, B_EXITED_VIEW, NULL);
|
|
||||||
}
|
|
||||||
fLastMouseMovedView = view;
|
|
||||||
}
|
|
||||||
view->ConvertFromScreen(&where);
|
|
||||||
view->MouseMoved(where, transit, NULL);
|
|
||||||
} else
|
|
||||||
target->MessageReceived(msg);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2167,36 +2171,39 @@ BWindow::_DequeueAll()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This here is a nearly full code duplication to BLooper::task_looper()
|
/*! This here is an almost complete code duplication to BLooper::task_looper()
|
||||||
but with one little difference: It uses the _DetermineTarget() method
|
but with some important differences:
|
||||||
to tell what the later target of a message will be, if no explicit target
|
a) it uses the _DetermineTarget() method to tell what the later target of
|
||||||
is supplied.
|
a message will be, if no explicit target is supplied.
|
||||||
This is important because the app_server sends all events to the preferred
|
b) it calls _UnpackMessage() and _SanitizeMessage() to duplicate the message
|
||||||
handler, and these must be correctly retargeted and eventually distributed
|
to all of its intended targets, and to add all fields the target would
|
||||||
to several handlers using _DistributeMessage().
|
expect in such a message.
|
||||||
|
|
||||||
|
This is important because the app_server sends all input events to the
|
||||||
|
preferred handler, and expects them to be correctly distributed to their
|
||||||
|
intended targets.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
BWindow::task_looper()
|
BWindow::task_looper()
|
||||||
{
|
{
|
||||||
STRACE(("info: BWindow::task_looper() started.\n"));
|
STRACE(("info: BWindow::task_looper() started.\n"));
|
||||||
|
|
||||||
// Check that looper is locked (should be)
|
// Check that looper is locked (should be)
|
||||||
AssertLocked();
|
AssertLocked();
|
||||||
// Unlock the looper
|
|
||||||
Unlock();
|
Unlock();
|
||||||
|
|
||||||
if (IsLocked())
|
if (IsLocked())
|
||||||
debugger("window must not be locked!");
|
debugger("window must not be locked!");
|
||||||
|
|
||||||
// loop: As long as we are not terminating.
|
// loop: As long as we are not terminating.
|
||||||
while (!fTerminating) {
|
while (!fTerminating) {
|
||||||
// TODO: timeout determination algo
|
// TODO: timeout determination algo
|
||||||
// Read from message port (how do we determine what the timeout is?)
|
// Read from message port (how do we determine what the timeout is?)
|
||||||
BMessage* msg = MessageFromPort();
|
BMessage* msg = MessageFromPort();
|
||||||
|
|
||||||
// Did we get a message?
|
// Did we get a message?
|
||||||
if (msg) {
|
if (msg) {
|
||||||
// Add to queue
|
// Add to queue
|
||||||
fQueue->AddMessage(msg);
|
fQueue->AddMessage(msg);
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
@@ -2204,22 +2211,22 @@ BWindow::task_looper()
|
|||||||
// Get message count from port
|
// Get message count from port
|
||||||
int32 msgCount = port_count(fMsgPort);
|
int32 msgCount = port_count(fMsgPort);
|
||||||
for (int32 i = 0; i < msgCount; ++i) {
|
for (int32 i = 0; i < msgCount; ++i) {
|
||||||
// Read 'count' messages from port (so we will not block)
|
// Read 'count' messages from port (so we will not block)
|
||||||
// We use zero as our timeout since we know there is stuff there
|
// We use zero as our timeout since we know there is stuff there
|
||||||
msg = MessageFromPort(0);
|
msg = MessageFromPort(0);
|
||||||
// Add messages to queue
|
// Add messages to queue
|
||||||
if (msg)
|
if (msg)
|
||||||
fQueue->AddMessage(msg);
|
fQueue->AddMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop: As long as there are messages in the queue and the port is
|
// loop: As long as there are messages in the queue and the port is
|
||||||
// empty... and we are not terminating, of course.
|
// empty... and we are not terminating, of course.
|
||||||
bool dispatchNextMessage = true;
|
bool dispatchNextMessage = true;
|
||||||
while (!fTerminating && dispatchNextMessage) {
|
while (!fTerminating && dispatchNextMessage) {
|
||||||
// Get next message from queue (assign to fLastMessage)
|
// Get next message from queue (assign to fLastMessage)
|
||||||
fLastMessage = fQueue->NextMessage();
|
fLastMessage = fQueue->NextMessage();
|
||||||
|
|
||||||
// Lock the looper
|
// Lock the looper
|
||||||
Lock();
|
Lock();
|
||||||
if (!fLastMessage) {
|
if (!fLastMessage) {
|
||||||
// No more messages: Unlock the looper and terminate the
|
// No more messages: Unlock the looper and terminate the
|
||||||
@@ -2241,40 +2248,41 @@ BWindow::task_looper()
|
|||||||
B_HANDLER_TOKEN, (void **)&handler);
|
B_HANDLER_TOKEN, (void **)&handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if a target was given, and we should not use the preferred
|
|
||||||
// handler, we can just use that one
|
|
||||||
if (handler == NULL || usePreferred)
|
if (handler == NULL || usePreferred)
|
||||||
handler = _DetermineTarget(fLastMessage, handler);
|
handler = _DetermineTarget(fLastMessage, handler);
|
||||||
if (!usePreferred || _DistributeMessage(fLastMessage, handler)) {
|
|
||||||
if (handler == NULL)
|
|
||||||
handler = this;
|
|
||||||
|
|
||||||
// Is this a scripting message? (BMessage::HasSpecifiers())
|
unpack_cookie cookie;
|
||||||
if (fLastMessage->HasSpecifiers()) {
|
while (_UnpackMessage(cookie, &fLastMessage, &handler, &usePreferred)) {
|
||||||
int32 index = 0;
|
// if there is no target handler, the message is dropped
|
||||||
// Make sure the current specifier is kosher
|
if (handler != NULL) {
|
||||||
if (fLastMessage->GetCurrentSpecifier(&index) == B_OK)
|
// Is this a scripting message?
|
||||||
handler = resolve_specifier(handler, fLastMessage);
|
if (fLastMessage->HasSpecifiers()) {
|
||||||
}
|
int32 index = 0;
|
||||||
|
// Make sure the current specifier is kosher
|
||||||
|
if (fLastMessage->GetCurrentSpecifier(&index) == B_OK)
|
||||||
|
handler = resolve_specifier(handler, fLastMessage);
|
||||||
|
}
|
||||||
|
|
||||||
if (handler) {
|
if (handler != NULL)
|
||||||
// Do filtering and dispatch message
|
handler = _TopLevelFilter(fLastMessage, handler);
|
||||||
handler = _TopLevelFilter(fLastMessage, handler);
|
|
||||||
if (handler && handler->Looper() == this)
|
if (handler != NULL) {
|
||||||
|
_SanitizeMessage(fLastMessage, handler, usePreferred);
|
||||||
DispatchMessage(fLastMessage, handler);
|
DispatchMessage(fLastMessage, handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete the current message
|
||||||
|
delete fLastMessage;
|
||||||
|
fLastMessage = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Unlock();
|
Unlock();
|
||||||
|
|
||||||
// Delete the current message (fLastMessage)
|
// Are any messages on the port?
|
||||||
delete fLastMessage;
|
|
||||||
fLastMessage = NULL;
|
|
||||||
|
|
||||||
// Are any messages on the port?
|
|
||||||
if (port_count(fMsgPort) > 0) {
|
if (port_count(fMsgPort) > 0) {
|
||||||
// Do outer loop
|
// Do outer loop
|
||||||
dispatchNextMessage = false;
|
dispatchNextMessage = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2409,8 +2417,6 @@ BWindow::_SetFocus(BView *focusView, bool notifyInputServer)
|
|||||||
BHandler *
|
BHandler *
|
||||||
BWindow::_DetermineTarget(BMessage *message, BHandler *target)
|
BWindow::_DetermineTarget(BMessage *message, BHandler *target)
|
||||||
{
|
{
|
||||||
// TODO: this is mostly guessed; check for correctness.
|
|
||||||
|
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case B_KEY_DOWN:
|
case B_KEY_DOWN:
|
||||||
case B_KEY_UP:
|
case B_KEY_UP:
|
||||||
@@ -2428,14 +2434,24 @@ BWindow::_DetermineTarget(BMessage *message, BHandler *target)
|
|||||||
case B_UNMAPPED_KEY_DOWN:
|
case B_UNMAPPED_KEY_DOWN:
|
||||||
case B_UNMAPPED_KEY_UP:
|
case B_UNMAPPED_KEY_UP:
|
||||||
case B_MODIFIERS_CHANGED:
|
case B_MODIFIERS_CHANGED:
|
||||||
// these messages will be dispatched by the focus view later
|
// these messages should be dispatched by the focus view
|
||||||
return CurrentFocus();
|
return CurrentFocus();
|
||||||
|
|
||||||
case B_MOUSE_DOWN:
|
case B_MOUSE_DOWN:
|
||||||
case B_MOUSE_UP:
|
case B_MOUSE_UP:
|
||||||
case B_MOUSE_MOVED:
|
case B_MOUSE_MOVED:
|
||||||
case B_MOUSE_WHEEL_CHANGED:
|
case B_MOUSE_WHEEL_CHANGED:
|
||||||
// TODO: the app_server should tell us which view is the target
|
// is there a token of the view that is currently under the mouse?
|
||||||
|
int32 token;
|
||||||
|
if (message->FindInt32("_view_token", &token) == B_OK) {
|
||||||
|
BHandler* handler;
|
||||||
|
if (gDefaultTokens.GetToken(token, B_HANDLER_TOKEN,
|
||||||
|
(void**)&handler) == B_OK) {
|
||||||
|
BView* view = dynamic_cast<BView*>(handler);
|
||||||
|
if (view != NULL)
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_PULSE:
|
case B_PULSE:
|
||||||
@@ -2443,19 +2459,6 @@ BWindow::_DetermineTarget(BMessage *message, BHandler *target)
|
|||||||
// TODO: test wether R5 will let BView dispatch these messages
|
// TODO: test wether R5 will let BView dispatch these messages
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
case B_VIEW_RESIZED:
|
|
||||||
case B_VIEW_MOVED:
|
|
||||||
{
|
|
||||||
int32 token;
|
|
||||||
if (message->FindInt32("_token", &token) != B_OK)
|
|
||||||
token = B_NULL_TOKEN;
|
|
||||||
|
|
||||||
BView *view = _FindView(token);
|
|
||||||
if (view)
|
|
||||||
return view;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2471,44 +2474,150 @@ BWindow::_DetermineTarget(BMessage *message, BHandler *target)
|
|||||||
Returns \c true in case the message should still be dispatched
|
Returns \c true in case the message should still be dispatched
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
BWindow::_DistributeMessage(BMessage* message, BHandler* focus)
|
BWindow::_UnpackMessage(unpack_cookie& cookie, BMessage** _message, BHandler** _target,
|
||||||
|
bool* _usePreferred)
|
||||||
{
|
{
|
||||||
bool foundFocus = false;
|
if (cookie.message == NULL)
|
||||||
int32 focusToken = B_NULL_TOKEN;
|
return false;
|
||||||
if (focus != NULL)
|
|
||||||
focusToken = _get_object_token_(focus);
|
|
||||||
|
|
||||||
int32 index = 0;
|
if (cookie.index == 0 && !cookie.tokens_scanned) {
|
||||||
int32 token;
|
if (!*_usePreferred) {
|
||||||
for (; message->FindInt32("_token", index, &token) == B_OK; index++) {
|
// we only consider messages targeted at the preferred handler
|
||||||
if (token == focusToken)
|
cookie.message = NULL;
|
||||||
foundFocus = true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize our cookie
|
||||||
|
cookie.message = *_message;
|
||||||
|
cookie.focus = *_target;
|
||||||
|
|
||||||
|
if (cookie.focus != NULL)
|
||||||
|
cookie.focus_token = _get_object_token_(*_target);
|
||||||
|
|
||||||
|
if (fLastMouseMovedView != NULL && cookie.message->what == B_MOUSE_MOVED)
|
||||||
|
cookie.last_view_token = _get_object_token_(fLastMouseMovedView);
|
||||||
|
|
||||||
|
*_usePreferred = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_DequeueAll();
|
||||||
|
|
||||||
|
// distribute the message to all targets specified in the
|
||||||
|
// message directly (but not to the focus view)
|
||||||
|
|
||||||
|
for (int32 token; !cookie.tokens_scanned
|
||||||
|
&& cookie.message->FindInt32("_token", cookie.index, &token) == B_OK;
|
||||||
|
cookie.index++) {
|
||||||
|
// focus view is preferred and should get its message directly
|
||||||
|
if (token == cookie.focus_token) {
|
||||||
|
cookie.found_focus = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (token == cookie.last_view_token)
|
||||||
|
continue;
|
||||||
|
|
||||||
BView* target = _FindView(token);
|
BView* target = _FindView(token);
|
||||||
if (target == NULL)
|
if (target == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
BMessenger messenger(target);
|
*_message = new BMessage(*cookie.message);
|
||||||
messenger.SendMessage(message);
|
*_target = target;
|
||||||
|
cookie.index++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index > 0) {
|
cookie.tokens_scanned = true;
|
||||||
if (foundFocus) {
|
|
||||||
// the focus view already got this message
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// if there is a last mouse moved view, and the new focus is
|
||||||
|
// different, the previous view wants to get its B_EXITED_VIEW
|
||||||
|
// message
|
||||||
|
if (cookie.last_view_token != B_NULL_TOKEN && fLastMouseMovedView != cookie.focus) {
|
||||||
|
*_message = new BMessage(*cookie.message);
|
||||||
|
*_target = fLastMouseMovedView;
|
||||||
|
cookie.last_view_token = B_NULL_TOKEN;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cookie.index > 0) {
|
||||||
// should this message still be dispatched by the focus view?
|
// should this message still be dispatched by the focus view?
|
||||||
bool feedFocus;
|
bool feedFocus;
|
||||||
if (message->FindBool("_feed_focus", &feedFocus) != B_OK
|
if (!cookie.found_focus
|
||||||
|| feedFocus == false)
|
&& (cookie.message->FindBool("_feed_focus", &feedFocus) != B_OK
|
||||||
|
|| feedFocus == false)) {
|
||||||
|
delete cookie.message;
|
||||||
|
cookie.message = NULL;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*_message = cookie.message;
|
||||||
|
*_target = cookie.focus;
|
||||||
|
*_usePreferred = true;
|
||||||
|
cookie.message = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BWindow::_SanitizeMessage(BMessage* message, BHandler* target, bool usePreferred)
|
||||||
|
{
|
||||||
|
if (target == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (message->what) {
|
||||||
|
case B_MOUSE_MOVED:
|
||||||
|
case B_MOUSE_UP:
|
||||||
|
case B_MOUSE_DOWN:
|
||||||
|
BPoint where;
|
||||||
|
if (message->FindPoint("screen_where", &where) != B_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// add local window coordinates
|
||||||
|
message->AddPoint("where", ConvertFromScreen(where));
|
||||||
|
|
||||||
|
BView* view = dynamic_cast<BView*>(target);
|
||||||
|
if (view != NULL) {
|
||||||
|
// add local view coordinates
|
||||||
|
message->AddPoint("be:view_where", view->ConvertFromScreen(where));
|
||||||
|
|
||||||
|
// is there a token of the view that is currently under the mouse?
|
||||||
|
BView* viewUnderMouse = NULL;
|
||||||
|
int32 token;
|
||||||
|
if (message->FindInt32("_view_token", &token) == B_OK) {
|
||||||
|
BHandler* handler;
|
||||||
|
if (gDefaultTokens.GetToken(token, B_HANDLER_TOKEN,
|
||||||
|
(void**)&handler) == B_OK)
|
||||||
|
viewUnderMouse = dynamic_cast<BView*>(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add transit information
|
||||||
|
int32 transit;
|
||||||
|
if (message->FindInt32("be:transit", &transit) != B_OK) {
|
||||||
|
if (viewUnderMouse == view) {
|
||||||
|
// the mouse is over the target view
|
||||||
|
if (fLastMouseMovedView != view)
|
||||||
|
transit = B_ENTERED_VIEW;
|
||||||
|
else
|
||||||
|
transit = B_INSIDE_VIEW;
|
||||||
|
} else {
|
||||||
|
// the mouse is not over the target view
|
||||||
|
if (view == fLastMouseMovedView)
|
||||||
|
transit = B_EXITED_VIEW;
|
||||||
|
else
|
||||||
|
transit = B_OUTSIDE_VIEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
message->AddInt32("be:transit", transit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usePreferred || viewUnderMouse == NULL)
|
||||||
|
fLastMouseMovedView = viewUnderMouse;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BWindow::_HandleKeyDown(char key, uint32 modifiers)
|
BWindow::_HandleKeyDown(char key, uint32 modifiers)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ Desktop::Init()
|
|||||||
fRootLayer->Lock();
|
fRootLayer->Lock();
|
||||||
fRootLayer->MouseEventHandler(message);
|
fRootLayer->MouseEventHandler(message);
|
||||||
fRootLayer->Unlock();
|
fRootLayer->Unlock();
|
||||||
return B_SKIP_MESSAGE;
|
return B_DISPATCH_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
+19
-18
@@ -424,7 +424,7 @@ Layer::SetName(const char* name)
|
|||||||
fName.SetTo(name);
|
fName.SetTo(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUserClipping
|
|
||||||
void
|
void
|
||||||
Layer::SetUserClipping(const BRegion& region)
|
Layer::SetUserClipping(const BRegion& region)
|
||||||
{
|
{
|
||||||
@@ -434,7 +434,7 @@ Layer::SetUserClipping(const BRegion& region)
|
|||||||
_RebuildDrawingRegion();
|
_RebuildDrawingRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFlags
|
|
||||||
void
|
void
|
||||||
Layer::SetFlags(uint32 flags)
|
Layer::SetFlags(uint32 flags)
|
||||||
{
|
{
|
||||||
@@ -442,7 +442,15 @@ Layer::SetFlags(uint32 flags)
|
|||||||
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
|
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw
|
|
||||||
|
void
|
||||||
|
Layer::SetEventMask(uint32 eventMask, uint32 options)
|
||||||
|
{
|
||||||
|
fEventMask = eventMask;
|
||||||
|
fEventOptions = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::Draw(const BRect &rect)
|
Layer::Draw(const BRect &rect)
|
||||||
{
|
{
|
||||||
@@ -823,55 +831,46 @@ Layer::CopyBits(BRect& src, BRect& dst, int32 xOffset, int32 yOffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::MouseDown(const BMessage *msg)
|
Layer::MouseDown(const BMessage *msg)
|
||||||
{
|
{
|
||||||
if (Window() && !IsTopLayer()) {
|
|
||||||
Window()->SendMessageToClient(msg, fViewToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::MouseUp(const BMessage *msg)
|
Layer::MouseUp(const BMessage *msg)
|
||||||
{
|
{
|
||||||
if (Window() && !IsTopLayer()) {
|
|
||||||
Window()->SendMessageToClient(msg, fViewToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::MouseMoved(const BMessage *msg)
|
Layer::MouseMoved(const BMessage *msg)
|
||||||
{
|
{
|
||||||
if (Window() && !IsTopLayer()) {
|
|
||||||
Window()->SendMessageToClient(msg, fViewToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::MouseWheelChanged(const BMessage *msg)
|
Layer::MouseWheelChanged(const BMessage *msg)
|
||||||
{
|
{
|
||||||
if (Window() && !IsTopLayer()) {
|
|
||||||
Window()->SendMessageToClient(msg, fViewToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::WorkspaceActivated(int32 index, bool active)
|
Layer::WorkspaceActivated(int32 index, bool active)
|
||||||
{
|
{
|
||||||
// Empty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces)
|
Layer::WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces)
|
||||||
{
|
{
|
||||||
// Empty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::Activated(bool active)
|
Layer::Activated(bool active)
|
||||||
{
|
{
|
||||||
// Empty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -881,6 +880,7 @@ Layer::ScrollingOffset() const
|
|||||||
return fScrollingOffset;
|
return fScrollingOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::SetDrawingOrigin(BPoint origin)
|
Layer::SetDrawingOrigin(BPoint origin)
|
||||||
{
|
{
|
||||||
@@ -1497,6 +1497,7 @@ Layer::_AllRedraw(const BRegion &invalid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Layer::_AddToViewsWithInvalidCoords() const
|
Layer::_AddToViewsWithInvalidCoords() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -182,15 +182,12 @@ class Layer {
|
|||||||
DrawingEngine* GetDrawingEngine() const
|
DrawingEngine* GetDrawingEngine() const
|
||||||
{ return fDriver; }
|
{ return fDriver; }
|
||||||
|
|
||||||
// flags
|
void SetEventMask(uint32 eventMask, uint32 options);
|
||||||
uint32 EventMask() const
|
uint32 EventMask() const
|
||||||
{ return fEventMask; }
|
{ return fEventMask; }
|
||||||
uint32 EventOptions() const
|
uint32 EventOptions() const
|
||||||
{ return fEventOptions; }
|
{ return fEventOptions; }
|
||||||
inline void QuietlySetEventMask(uint32 em)
|
|
||||||
{ fEventMask = em; }
|
|
||||||
inline void QuietlySetEventOptions(uint32 eo)
|
|
||||||
{ fEventOptions = eo; }
|
|
||||||
inline uint32 ResizeMode() const
|
inline uint32 ResizeMode() const
|
||||||
{ return fResizeMode; }
|
{ return fResizeMode; }
|
||||||
inline uint32 Flags() const
|
inline uint32 Flags() const
|
||||||
|
|||||||
+46
-275
@@ -61,17 +61,13 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount,
|
|||||||
|
|
||||||
fDesktop(desktop),
|
fDesktop(desktop),
|
||||||
fDragMessage(NULL),
|
fDragMessage(NULL),
|
||||||
fLastLayerUnderMouse(this),
|
fMouseEventLayer(NULL),
|
||||||
fNotifyLayer(NULL),
|
|
||||||
fSavedEventMask(0),
|
fSavedEventMask(0),
|
||||||
fSavedEventOptions(0),
|
fSavedEventOptions(0),
|
||||||
fAllRegionsLock("root layer region lock"),
|
fAllRegionsLock("root layer region lock"),
|
||||||
|
|
||||||
fDirtyForRedraw(),
|
fDirtyForRedraw(),
|
||||||
|
|
||||||
fButtons(0),
|
|
||||||
fLastMousePosition(0.0, 0.0),
|
|
||||||
|
|
||||||
fActiveWksIndex(0),
|
fActiveWksIndex(0),
|
||||||
fWsCount(0),
|
fWsCount(0),
|
||||||
fWorkspace(new Workspace*[kMaxWorkspaceCount]),
|
fWorkspace(new Workspace*[kMaxWorkspaceCount]),
|
||||||
@@ -371,18 +367,17 @@ bool RootLayer::SetActiveWorkspace(int32 index)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// you cannot switch workspaces on R5 if there is an event mask BView
|
// you cannot switch workspaces on R5 if there is an event mask BView
|
||||||
if (fNotifyLayer && fNotifyLayer->Owner())
|
// if (fNotifyLayer && fNotifyLayer->Owner())
|
||||||
return false;
|
// return false;
|
||||||
|
|
||||||
// if you're dragging something you are allowed to change workspaces only if
|
// if you're dragging something you are allowed to change workspaces only if
|
||||||
// the Layer being dragged is a B_NORMAL_WINDOW_FEEL WinBorder.
|
// the Layer being dragged is a B_NORMAL_WINDOW_FEEL WinBorder.
|
||||||
WinBorder *draggedWinBorder = dynamic_cast<WinBorder*>(fNotifyLayer);
|
WinBorder *draggedWinBorder = dynamic_cast<WinBorder*>(fMouseEventLayer);
|
||||||
if (fNotifyLayer) {
|
if (fMouseEventLayer != NULL) {
|
||||||
if (draggedWinBorder) {
|
if (draggedWinBorder) {
|
||||||
if (draggedWinBorder->Feel() != B_NORMAL_WINDOW_FEEL)
|
if (draggedWinBorder->Feel() != B_NORMAL_WINDOW_FEEL)
|
||||||
return false;
|
return false;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,9 +473,9 @@ RootLayer::SetWinBorderWorskpaces(WinBorder *winBorder, uint32 oldIndex, uint32
|
|||||||
{
|
{
|
||||||
// if the active notify Layer is somehow related to winBorder, then
|
// if the active notify Layer is somehow related to winBorder, then
|
||||||
// this window/WinBorder is not allowed to leave this workspace.
|
// this window/WinBorder is not allowed to leave this workspace.
|
||||||
if (fNotifyLayer && (fNotifyLayer == winBorder || fNotifyLayer->Owner() == winBorder)) {
|
// TODO: this looks wrong: I doubt the window is supposed to open in two workspaces then
|
||||||
newIndex |= (0x00000001UL << fActiveWksIndex);
|
// if (fNotifyLayer && (fNotifyLayer == winBorder || fNotifyLayer->Owner() == winBorder))
|
||||||
}
|
// newIndex |= (0x00000001UL << fActiveWksIndex);
|
||||||
|
|
||||||
uint32 localOldIndex = oldIndex;
|
uint32 localOldIndex = oldIndex;
|
||||||
uint32 localNewIndex = newIndex;
|
uint32 localNewIndex = newIndex;
|
||||||
@@ -851,25 +846,13 @@ RootLayer::SetActive(WinBorder* newActive, bool activate)
|
|||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// Workspace related methods
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
// #pragma mark - Input related methods
|
||||||
// Input related methods
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void
|
void
|
||||||
RootLayer::_ProcessMouseMovedEvent(BMessage *msg)
|
RootLayer::_ProcessMouseMovedEvent(BMessage *msg, BPoint where, Layer* target)
|
||||||
{
|
{
|
||||||
BPoint where(0,0);
|
|
||||||
msg->FindPoint("where", &where);
|
|
||||||
|
|
||||||
Layer* target = LayerAt(where);
|
|
||||||
if (target == NULL) {
|
|
||||||
CRITICAL("RootLayer::_ProcessMouseMovedEvent() 'target' can't be null.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// change focus in FFM mode
|
// change focus in FFM mode
|
||||||
WinBorder* winBorderTarget = dynamic_cast<WinBorder*>(target);
|
WinBorder* winBorderTarget = dynamic_cast<WinBorder*>(target);
|
||||||
if (winBorderTarget) {
|
if (winBorderTarget) {
|
||||||
@@ -886,266 +869,60 @@ RootLayer::_ProcessMouseMovedEvent(BMessage *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the layer under mouse to the list of layers to be notified on mouse moved
|
target->MouseMoved(msg);
|
||||||
bool alreadyPresent = fMouseNotificationList.HasItem(target);
|
}
|
||||||
if (!alreadyPresent)
|
|
||||||
fMouseNotificationList.AddItem(target);
|
|
||||||
|
|
||||||
int32 count = fMouseNotificationList.CountItems();
|
|
||||||
int32 viewAction;
|
|
||||||
Layer *lay;
|
|
||||||
for (int32 i = 0; i <= count; i++) {
|
|
||||||
lay = static_cast<Layer*>(fMouseNotificationList.ItemAt(i));
|
|
||||||
if (lay) {
|
|
||||||
// set transit state
|
|
||||||
if (lay == target)
|
|
||||||
if (lay == fLastLayerUnderMouse)
|
|
||||||
viewAction = B_INSIDE_VIEW;
|
|
||||||
else
|
|
||||||
viewAction = B_ENTERED_VIEW;
|
|
||||||
else
|
|
||||||
if (lay == fLastLayerUnderMouse)
|
|
||||||
viewAction = B_EXITED_VIEW;
|
|
||||||
else
|
|
||||||
viewAction = B_OUTSIDE_VIEW;
|
|
||||||
|
|
||||||
msg->AddInt32("transit", viewAction);
|
void
|
||||||
lay->MouseMoved(msg);
|
RootLayer::MouseEventHandler(BMessage *event)
|
||||||
|
{
|
||||||
|
BPoint where;
|
||||||
|
if (event->FindPoint("where", &where) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Layer* layer = fMouseEventLayer;
|
||||||
|
if (layer == NULL) {
|
||||||
|
if (fWMState.Focus != NULL) {
|
||||||
|
layer = fWMState.Focus->LayerAt(where);
|
||||||
|
if (layer != NULL)
|
||||||
|
event->AddInt32("_view_token", layer->ViewToken());
|
||||||
|
}
|
||||||
|
if (layer == NULL) {
|
||||||
|
layer = LayerAt(where);
|
||||||
|
if (layer == NULL)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!alreadyPresent)
|
switch (event->what) {
|
||||||
fMouseNotificationList.RemoveItem(target);
|
case B_MOUSE_DOWN:
|
||||||
|
layer->MouseDown(event);
|
||||||
fLastLayerUnderMouse = target;
|
|
||||||
fLastMousePosition = where;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RootLayer::MouseEventHandler(BMessage *msg)
|
|
||||||
{
|
|
||||||
switch (msg->what) {
|
|
||||||
case B_MOUSE_DOWN: {
|
|
||||||
//printf("RootLayer::MouseEventHandler(B_MOUSE_DOWN)\n");
|
|
||||||
|
|
||||||
BPoint where(0,0);
|
|
||||||
|
|
||||||
msg->FindPoint("where", &where);
|
|
||||||
// We'll need this so that GetMouse can query for which buttons are down.
|
|
||||||
msg->FindInt32("buttons", &fButtons);
|
|
||||||
|
|
||||||
where.ConstrainTo(Frame());
|
|
||||||
|
|
||||||
if (fLastMousePosition != where) {
|
|
||||||
// If this happens, it's input server's fault.
|
|
||||||
// There might be additional fields an application expects in B_MOUSE_MOVED
|
|
||||||
// message, and in this way it won't get them.
|
|
||||||
int64 when = 0;
|
|
||||||
int32 buttons = 0;
|
|
||||||
|
|
||||||
msg->FindInt64("when", &when);
|
|
||||||
msg->FindInt32("buttons", &buttons);
|
|
||||||
|
|
||||||
BMessage mouseMovedMsg(B_MOUSE_MOVED);
|
|
||||||
mouseMovedMsg.AddInt64("when", when);
|
|
||||||
mouseMovedMsg.AddInt32("buttons", buttons);
|
|
||||||
mouseMovedMsg.AddPoint("where", where);
|
|
||||||
|
|
||||||
_ProcessMouseMovedEvent(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fLastLayerUnderMouse == NULL) {
|
|
||||||
CRITICAL("RootLayer::MouseEventHandler(B_MOUSE_DOWN) fLastLayerUnderMouse is null!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fLastLayerUnderMouse == this)
|
|
||||||
break;
|
|
||||||
|
|
||||||
int32 count = fMouseNotificationList.CountItems();
|
|
||||||
Layer *lay;
|
|
||||||
for (int32 i = 0; i <= count; i++) {
|
|
||||||
lay = static_cast<Layer*>(fMouseNotificationList.ItemAt(i));
|
|
||||||
if (lay)
|
|
||||||
// NOTE: testing under R5 shows that it doesn't matter if a window is created
|
|
||||||
// with B_ASYNCHRONOUS_CONTROLS flag or not. B_MOUSE_DOWN is always transmited.
|
|
||||||
lay->MouseDown(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the pointer for one of the first RootLayer's descendants
|
|
||||||
Layer *primaryTarget = LayerAt(where, false);
|
|
||||||
primaryTarget->MouseDown(msg);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case B_MOUSE_UP: {
|
|
||||||
//printf("RootLayer::MouseEventHandler(B_MOUSE_UP)\n");
|
|
||||||
|
|
||||||
BPoint where(0,0);
|
|
||||||
|
|
||||||
msg->FindPoint("where", &where);
|
|
||||||
|
|
||||||
where.ConstrainTo(fFrame);
|
|
||||||
|
|
||||||
if (fLastMousePosition != where) {
|
|
||||||
// If this happens, it's input server's fault.
|
|
||||||
// There might be additional fields an application expects in B_MOUSE_MOVED
|
|
||||||
// message, and in this way it won't get them.
|
|
||||||
int64 when = 0;
|
|
||||||
int32 buttons = 0;
|
|
||||||
|
|
||||||
msg->FindInt64("when", &when);
|
|
||||||
msg->FindInt32("buttons", &buttons);
|
|
||||||
|
|
||||||
BMessage mouseMovedMsg(B_MOUSE_MOVED);
|
|
||||||
mouseMovedMsg.AddInt64("when", when);
|
|
||||||
mouseMovedMsg.AddInt32("buttons", buttons);
|
|
||||||
mouseMovedMsg.AddPoint("where", where);
|
|
||||||
|
|
||||||
_ProcessMouseMovedEvent(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fLastLayerUnderMouse == NULL) {
|
|
||||||
CRITICAL("RootLayer::MouseEventHandler(B_MOUSE_UP) fLastLayerUnderMouse is null!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool foundCurrent = fMouseNotificationList.HasItem(fLastLayerUnderMouse);
|
|
||||||
int32 count = fMouseNotificationList.CountItems();
|
|
||||||
Layer *lay;
|
|
||||||
for (int32 i = 0; i <= count; i++) {
|
|
||||||
lay = static_cast<Layer*>(fMouseNotificationList.ItemAt(i));
|
|
||||||
if (lay)
|
|
||||||
lay->MouseUp(msg);
|
|
||||||
}
|
|
||||||
ClearNotifyLayer();
|
|
||||||
|
|
||||||
if (!foundCurrent)
|
|
||||||
fLastLayerUnderMouse->MouseUp(msg);
|
|
||||||
|
|
||||||
// TODO: This is a quick fix to avoid the endless loop with windows created
|
|
||||||
// with the B_ASYNCHRONOUS_CONTROLS flag, but please someone have a look into this.
|
|
||||||
fButtons = 0;
|
|
||||||
|
|
||||||
|
case B_MOUSE_UP:
|
||||||
|
layer->MouseUp(event);
|
||||||
|
SetMouseEventLayer(NULL);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case B_MOUSE_MOVED:
|
case B_MOUSE_MOVED:
|
||||||
_ProcessMouseMovedEvent(msg);
|
_ProcessMouseMovedEvent(event, where, layer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_MOUSE_WHEEL_CHANGED: {
|
|
||||||
//printf("RootLayer::MouseEventHandler(B_MOUSE_WHEEL_CHANGED)\n");
|
|
||||||
// FEATURE: This is a tentative change: mouse wheel messages are always sent to the window
|
|
||||||
// under the cursor. It's pretty stupid to send it to the active window unless a particular
|
|
||||||
// view has locked focus via SetMouseEventMask
|
|
||||||
|
|
||||||
if (fLastLayerUnderMouse == NULL) {
|
|
||||||
CRITICAL("RootLayer::MouseEventHandler(B_MOUSE_DOWN) fLastLayerUnderMouse is null!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fLastLayerUnderMouse->MouseWheelChanged(msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
printf("RootLayer::MouseEventHandler(): WARNING: unknown message\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
RootLayer::AddToInputNotificationLists(Layer *lay, uint32 mask, uint32 options)
|
|
||||||
{
|
|
||||||
if (!lay)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool returnValue = true;
|
|
||||||
|
|
||||||
Lock();
|
|
||||||
|
|
||||||
if (mask & B_POINTER_EVENTS) {
|
|
||||||
if (!fMouseNotificationList.HasItem(lay))
|
|
||||||
fMouseNotificationList.AddItem(lay);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (options == 0)
|
|
||||||
fMouseNotificationList.RemoveItem(lay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mask & B_KEYBOARD_EVENTS) {
|
|
||||||
if (!fKeyboardNotificationList.HasItem(lay))
|
|
||||||
fKeyboardNotificationList.AddItem(lay);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (options == 0)
|
|
||||||
fKeyboardNotificationList.RemoveItem(lay);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: set options!!!
|
|
||||||
// B_NO_POINTER_HISTORY only! How? By telling to the input_server?
|
|
||||||
|
|
||||||
Unlock();
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RootLayer::SetNotifyLayer(Layer *lay, uint32 mask, uint32 options)
|
|
||||||
{
|
|
||||||
if (!lay)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool returnValue = true;
|
|
||||||
|
|
||||||
Lock();
|
|
||||||
|
|
||||||
fNotifyLayer = lay;
|
|
||||||
fSavedEventMask = lay->EventMask();
|
|
||||||
fSavedEventOptions = lay->EventOptions();
|
|
||||||
|
|
||||||
AddToInputNotificationLists(lay, mask, options);
|
|
||||||
|
|
||||||
// TODO: set other options!!!
|
|
||||||
// B_SUSPEND_VIEW_FOCUS
|
|
||||||
// B_LOCK_WINDOW_FOCUS
|
|
||||||
Unlock();
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RootLayer::ClearNotifyLayer()
|
RootLayer::SetMouseEventLayer(Layer* layer)
|
||||||
{
|
{
|
||||||
if (fNotifyLayer) {
|
fMouseEventLayer = layer;
|
||||||
Lock();
|
|
||||||
// remove from notification list.
|
|
||||||
AddToInputNotificationLists(fNotifyLayer, 0UL, 0UL);
|
|
||||||
// set event masks
|
|
||||||
fNotifyLayer->QuietlySetEventMask(fSavedEventMask);
|
|
||||||
fNotifyLayer->QuietlySetEventOptions(fSavedEventOptions);
|
|
||||||
// add to notification list with event masks set my BView::SetEventMask()
|
|
||||||
AddToInputNotificationLists(fNotifyLayer, fSavedEventMask, fSavedEventOptions);
|
|
||||||
|
|
||||||
fNotifyLayer = NULL;
|
|
||||||
fSavedEventMask = 0UL;
|
|
||||||
fSavedEventOptions = 0UL;
|
|
||||||
|
|
||||||
Unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RootLayer::LayerRemoved(Layer* layer)
|
RootLayer::LayerRemoved(Layer* layer)
|
||||||
{
|
{
|
||||||
if (layer == fNotifyLayer)
|
if (fMouseEventLayer == layer)
|
||||||
fNotifyLayer = NULL;
|
fMouseEventLayer = NULL;
|
||||||
// TODO: this must not happen!!! Fix this, quickly!
|
|
||||||
if (layer == fLastLayerUnderMouse)
|
|
||||||
fLastLayerUnderMouse = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1158,7 +935,7 @@ RootLayer::SetDragMessage(BMessage* msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (msg)
|
if (msg)
|
||||||
fDragMessage = new BMessage(*msg);
|
fDragMessage = new BMessage(*msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1245,12 +1022,6 @@ RootLayer::hide_winBorder(WinBorder *winBorder)
|
|||||||
void
|
void
|
||||||
RootLayer::change_winBorder_feel(WinBorder *winBorder, int32 newFeel)
|
RootLayer::change_winBorder_feel(WinBorder *winBorder, int32 newFeel)
|
||||||
{
|
{
|
||||||
// if the notify Layer is somehow related to winBorder, then
|
|
||||||
// this window/WinBorder is not allowed to change feel.
|
|
||||||
if (fNotifyLayer && (fNotifyLayer == winBorder || fNotifyLayer->Owner() == winBorder)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isVisible = false;
|
bool isVisible = false;
|
||||||
bool isVisibleInActiveWorkspace = false;
|
bool isVisibleInActiveWorkspace = false;
|
||||||
|
|
||||||
|
|||||||
@@ -97,15 +97,10 @@ public:
|
|||||||
void SetBGColor(const RGBColor &col);
|
void SetBGColor(const RGBColor &col);
|
||||||
RGBColor BGColor(void) const;
|
RGBColor BGColor(void) const;
|
||||||
|
|
||||||
inline int32 Buttons(void) { return fButtons; }
|
|
||||||
|
|
||||||
void SetDragMessage(BMessage *msg);
|
void SetDragMessage(BMessage *msg);
|
||||||
BMessage* DragMessage(void) const;
|
BMessage* DragMessage(void) const;
|
||||||
|
|
||||||
bool AddToInputNotificationLists(Layer *lay, uint32 mask,
|
void SetMouseEventLayer(Layer* layer);
|
||||||
uint32 options);
|
|
||||||
bool SetNotifyLayer(Layer *lay, uint32 mask, uint32 options);
|
|
||||||
void ClearNotifyLayer();
|
|
||||||
|
|
||||||
void LayerRemoved(Layer* layer);
|
void LayerRemoved(Layer* layer);
|
||||||
|
|
||||||
@@ -139,25 +134,19 @@ friend class Desktop;
|
|||||||
|
|
||||||
// Input related methods
|
// Input related methods
|
||||||
void MouseEventHandler(BMessage *msg);
|
void MouseEventHandler(BMessage *msg);
|
||||||
void _ProcessMouseMovedEvent(BMessage *msg);
|
void _ProcessMouseMovedEvent(BMessage *msg, BPoint where, Layer* target);
|
||||||
|
|
||||||
Desktop* fDesktop;
|
Desktop* fDesktop;
|
||||||
BMessage* fDragMessage;
|
BMessage* fDragMessage;
|
||||||
Layer* fLastLayerUnderMouse;
|
Layer* fMouseEventLayer;
|
||||||
|
|
||||||
Layer* fNotifyLayer;
|
|
||||||
uint32 fSavedEventMask;
|
uint32 fSavedEventMask;
|
||||||
uint32 fSavedEventOptions;
|
uint32 fSavedEventOptions;
|
||||||
BList fMouseNotificationList;
|
|
||||||
BList fKeyboardNotificationList;
|
|
||||||
|
|
||||||
BLocker fAllRegionsLock;
|
BLocker fAllRegionsLock;
|
||||||
|
|
||||||
BRegion fDirtyForRedraw;
|
BRegion fDirtyForRedraw;
|
||||||
|
|
||||||
int32 fButtons;
|
|
||||||
BPoint fLastMousePosition;
|
|
||||||
|
|
||||||
int32 fActiveWksIndex;
|
int32 fActiveWksIndex;
|
||||||
int32 fWsCount;
|
int32 fWsCount;
|
||||||
Workspace** fWorkspace;
|
Workspace** fWorkspace;
|
||||||
|
|||||||
@@ -718,9 +718,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
|
|
||||||
link.Read<uint32>(&eventMask);
|
link.Read<uint32>(&eventMask);
|
||||||
if (link.Read<uint32>(&options) == B_OK) {
|
if (link.Read<uint32>(&options) == B_OK) {
|
||||||
printf("got %s: eventMask = %ld, options = %ld\n", fCurrentLayer->Name(), eventMask, options);
|
fCurrentLayer->SetEventMask(eventMask, options);
|
||||||
fCurrentLayer->QuietlySetEventMask(eventMask);
|
|
||||||
fCurrentLayer->QuietlySetEventOptions(options);
|
|
||||||
|
|
||||||
if (eventMask != 0 || options != 0) {
|
if (eventMask != 0 || options != 0) {
|
||||||
fDesktop->EventDispatcher().AddListener(FocusMessenger(),
|
fDesktop->EventDispatcher().AddListener(FocusMessenger(),
|
||||||
@@ -749,8 +747,7 @@ printf("got %s: eventMask = %ld, options = %ld\n", fCurrentLayer->Name(), eventM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rootLayer)
|
// TODO: support B_LOCK_WINDOW_FOCUS option in RootLayer
|
||||||
rootLayer->SetNotifyLayer(fCurrentLayer, eventMask, options);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AS_LAYER_MOVE_TO:
|
case AS_LAYER_MOVE_TO:
|
||||||
@@ -1602,19 +1599,21 @@ if (rootLayer)
|
|||||||
DTRACE(("ServerWindow %s: Message AS_DRAG_RECT unimplemented\n", Title()));
|
DTRACE(("ServerWindow %s: Message AS_DRAG_RECT unimplemented\n", Title()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AS_LAYER_GET_MOUSE_COORDS:
|
case AS_GET_MOUSE:
|
||||||
{
|
{
|
||||||
DTRACE(("ServerWindow %s: Message AS_GET_MOUSE_COORDS\n", fTitle));
|
DTRACE(("ServerWindow %s: Message AS_GET_MOUSE\n", fTitle));
|
||||||
|
|
||||||
fLink.StartMessage(SERVER_TRUE);
|
|
||||||
|
|
||||||
// Returns
|
// Returns
|
||||||
// 1) BPoint mouse location
|
// 1) BPoint mouse location
|
||||||
// 2) int32 button state
|
// 2) int32 button state
|
||||||
|
|
||||||
fLink.Attach<BPoint>(fDesktop->HWInterface()->GetCursorPosition());
|
BPoint where;
|
||||||
fLink.Attach<int32>(fDesktop->RootLayer()->Buttons());
|
int32 buttons;
|
||||||
|
fDesktop->EventDispatcher().GetMouse(where, buttons);
|
||||||
|
|
||||||
|
fLink.StartMessage(B_OK);
|
||||||
|
fLink.Attach<BPoint>(where);
|
||||||
|
fLink.Attach<int32>(buttons);
|
||||||
fLink.Flush();
|
fLink.Flush();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2116,6 +2115,9 @@ ServerWindow::_MessageLooper()
|
|||||||
status_t
|
status_t
|
||||||
ServerWindow::SendMessageToClient(const BMessage* msg, int32 target) const
|
ServerWindow::SendMessageToClient(const BMessage* msg, int32 target) const
|
||||||
{
|
{
|
||||||
|
if (target == B_NULL_TOKEN)
|
||||||
|
target = fClientToken;
|
||||||
|
|
||||||
#ifndef USING_MESSAGE4
|
#ifndef USING_MESSAGE4
|
||||||
ssize_t size = msg->FlattenedSize();
|
ssize_t size = msg->FlattenedSize();
|
||||||
char* buffer = new(nothrow) char[size];
|
char* buffer = new(nothrow) char[size];
|
||||||
|
|||||||
@@ -481,7 +481,7 @@ WinBorder::MouseDown(const BMessage *msg)
|
|||||||
if (action == DEC_MOVETOBACK) {
|
if (action == DEC_MOVETOBACK) {
|
||||||
GetRootLayer()->SetActive(this, false);
|
GetRootLayer()->SetActive(this, false);
|
||||||
} else {
|
} else {
|
||||||
GetRootLayer()->SetNotifyLayer(this, B_POINTER_EVENTS, 0UL);
|
GetRootLayer()->SetMouseEventLayer(this);
|
||||||
GetRootLayer()->SetActive(this);
|
GetRootLayer()->SetActive(this);
|
||||||
}
|
}
|
||||||
} else if (target != NULL) {
|
} else if (target != NULL) {
|
||||||
|
|||||||
Reference in New Issue
Block a user