* reverted Adi's premature changes to BWindow and restored _DetermineTarget() and

task_looper() again.
* removed BMessenger::fPreferred - whenever you had to specify "usePreferred" separately,
  you don't have to do that anymore - use B_PREFERRED_TOKEN instead.
* fixed BTokenSpace::GetToken() semantics: it will no longer touch the "object" argument
  in case of failure.
* Introduced a BWindow::_DistributeMessage() that will be part of the event dispatcher
  counterpart to the app_server (the other will be _DetermineTarget()).
* Made it easier to use Michael's Message4 implementation: just add the following line
  to your UserBuildConfig:
	AppendToConfigVar DEFINES : HAIKU_TOP src : USING_MESSAGE4 : global ;
* Introduced ServerWindow::HandlerMessenger() and FocusMessenger() - the first will
  target the client handler, while the other will target the preferred handler of the
  client looper (usually the view having focus).
* Fixed dano message unflattening in the Message4 code.
* Changed BMessage::PrintToStream() to no longer use macros in the Message4 implementation.
* I hope that's all - it's a huge change, but it's all connected.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15046 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-11-20 16:24:23 +00:00
parent 26e09e5870
commit 4ceb1e519c
29 changed files with 752 additions and 647 deletions
+210 -42
View File
@@ -925,7 +925,7 @@ BWindow::DispatchMessage(BMessage *msg, BHandler *target)
msg->FindPoint("where", i, &frameLeftTop);
msg->FindFloat("width", i, &width);
msg->FindFloat("height", i, &height);
if ((view = findView(fTopView, token))) {
if ((view = _FindView(token)) != NULL) {
// update the views offset in parent
if (view->LeftTop() != frameLeftTop) {
view->fParentOffset = frameLeftTop;
@@ -1330,16 +1330,16 @@ BWindow::UpdateIfNeeded()
BView *
BWindow::FindView(const char *viewName) const
{
// TODO: What about locking?!?
return findView(fTopView, viewName);
BAutolock _(const_cast<BWindow*>(this));
return fTopView->FindView(viewName);
}
BView *
BWindow::FindView(BPoint point) const
{
// TODO: What about locking?!?
return findView(fTopView, point);
BAutolock _(const_cast<BWindow*>(this));
return _FindView(fTopView, point);
}
@@ -2134,7 +2134,7 @@ BWindow::_InitData(BRect frame, const char* title, window_look look,
port_id sendPort;
int32 code;
if (fLink->FlushWithReply(code) == B_OK
&& code == SERVER_TRUE
&& code == B_OK
&& fLink->Read<port_id>(&sendPort) == B_OK) {
fLink->SetSenderPort(sendPort);
@@ -2194,7 +2194,118 @@ BWindow::task_looper()
{
STRACE(("info: BWindow::task_looper() started.\n"));
BLooper::task_looper();
// Check that looper is locked (should be)
AssertLocked();
// Unlock the looper
Unlock();
if (IsLocked())
debugger("window must not be locked!");
// loop: As long as we are not terminating.
while (!fTerminating) {
// TODO: timeout determination algo
// Read from message port (how do we determine what the timeout is?)
BMessage* msg = MessageFromPort();
// Did we get a message?
if (msg) {
// Add to queue
fQueue->AddMessage(msg);
} else
continue;
// Get message count from port
int32 msgCount = port_count(fMsgPort);
for (int32 i = 0; i < msgCount; ++i) {
// Read 'count' messages from port (so we will not block)
// We use zero as our timeout since we know there is stuff there
msg = MessageFromPort(0);
// Add messages to queue
if (msg)
fQueue->AddMessage(msg);
}
// loop: As long as there are messages in the queue and the port is
// empty... and we are not terminating, of course.
bool dispatchNextMessage = true;
while (!fTerminating && dispatchNextMessage) {
// Get next message from queue (assign to fLastMessage)
fLastMessage = fQueue->NextMessage();
// Lock the looper
Lock();
if (!fLastMessage) {
// No more messages: Unlock the looper and terminate the
// dispatch loop.
dispatchNextMessage = false;
} else {
// Get the target handler
#ifdef USING_MESSAGE4
// Use the private BMessage accessor to determine if we are
// using the preferred handler, or if a target has been
// specified
BHandler *handler = NULL;
BMessage::Private messagePrivate(fLastMessage);
bool usePreferred = messagePrivate.UsePreferredTarget();
#else
// Use BMessage friend functions to determine if we are using the
// preferred handler, or if a target has been specified
BHandler* handler = NULL;
bool usePreferred = _use_preferred_target_(fLastMessage);
#endif
if (usePreferred) {
handler = PreferredHandler();
} else {
#ifndef USING_MESSAGE4
gDefaultTokens.GetToken(_get_message_target_(fLastMessage),
B_HANDLER_TOKEN, (void **)&handler);
#else
gDefaultTokens.GetToken(messagePrivate.GetTarget(),
B_HANDLER_TOKEN, (void **)&handler);
#endif
}
//printf("handler = %p, usePreferred = %s\n", handler, usePreferred ? "yes" : "no");
if (!usePreferred || _DistributeMessage(fLastMessage)) {
// if a target was given, and we should not use the preferred
// handler, we can just use that one
if (handler == NULL || usePreferred)
handler = _DetermineTarget(fLastMessage, handler);
if (handler == NULL)
handler = this;
// Is this a scripting message? (BMessage::HasSpecifiers())
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) {
// Do filtering and dispatch message
handler = top_level_filter(fLastMessage, handler);
if (handler && handler->Looper() == this)
DispatchMessage(fLastMessage, handler);
}
}
}
Unlock();
// Delete the current message (fLastMessage)
delete fLastMessage;
fLastMessage = NULL;
// Are any messages on the port?
if (port_count(fMsgPort) > 0) {
// Do outer loop
dispatchNextMessage = false;
}
}
}
}
@@ -2349,6 +2460,85 @@ BWindow::handleActivation(bool active)
fTopView->_Activate(active);
}
/*!
\brief Determines the target of a message received.
*/
BHandler *
BWindow::_DetermineTarget(BMessage *message, BHandler *target)
{
// TODO: this is mostly guessed; check for correctness.
switch (message->what) {
case B_KEY_DOWN:
case B_KEY_UP:
case B_UNMAPPED_KEY_DOWN:
case B_UNMAPPED_KEY_UP:
case B_MODIFIERS_CHANGED:
// these messages will be dispatched by the focus view later
return CurrentFocus();
case B_MOUSE_DOWN:
case B_MOUSE_UP:
case B_MOUSE_MOVED:
case B_MOUSE_WHEEL_CHANGED:
// TODO: the app_server should tell us which view is the target
break;
case B_PULSE:
case B_QUIT_REQUESTED:
// TODO: test wether R5 will let BView dispatch these messages
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:
break;
}
return target;
}
/*!
\brief Distributes the message to its intended targets. This is done for
all messages that should go to the preferred handler.
Returns \c false in case the message needs no more processing.
*/
bool
BWindow::_DistributeMessage(BMessage* message)
{
message->PrintToStream();
int32 index = 0, count = 0;
int32 token;
for (; message->FindInt32("_token_", index, &token) == B_OK; index++) {
printf(" token = %ld\n", token);
BView* target = _FindView(token);
if (target == NULL)
continue;
printf("distribute message %lx to: %s\n", message->what, target->Name());
BMessenger messenger(target);
if (messenger.SendMessage(message) == B_OK)
count++;
}
return count == 0;
}
bool
BWindow::_HandleKeyDown(char key, uint32 modifiers)
{
@@ -2478,45 +2668,23 @@ BWindow::_FindShortcut(uint32 key, uint32 modifiers)
BView *
BWindow::findView(BView *view, int32 token)
BWindow::_FindView(int32 token)
{
if (_get_object_token_(view) == token)
BHandler* handler;
if (gDefaultTokens.GetToken(token, B_HANDLER_TOKEN, (void**)&handler) != B_OK)
return NULL;
// the view must belong to us in order to be found by this method
BView* view = dynamic_cast<BView*>(handler);
if (view != NULL && view->Window() == this)
return view;
BView *child = view->fFirstChild;
while (child != NULL) {
if ((view = findView(child, token)) != NULL)
return view;
child = child->fNextSibling;
}
return NULL;
}
BView *
BWindow::findView(BView *view, const char *name) const
{
if (!strcmp(name, view->Name()))
return view;
BView *child = view->fFirstChild;
while (child != NULL) {
if ((view = findView(child, name)) != NULL)
return view;
child = child->fNextSibling;
}
return NULL;
}
BView *
BWindow::findView(BView *view, BPoint point) const
BWindow::_FindView(BView *view, BPoint point) const
{
if (view->Bounds().Contains(point) && !view->fFirstChild)
return view;
@@ -2524,7 +2692,7 @@ BWindow::findView(BView *view, BPoint point) const
BView *child = view->fFirstChild;
while (child != NULL) {
if ((view = findView(child, point)) != NULL)
if ((view = _FindView(child, point)) != NULL)
return view;
child = child->fNextSibling;
@@ -2577,7 +2745,7 @@ BWindow::_FindPreviousNavigable(BView *focus, uint32 flags)
// Search the tree for views that accept focus
while (true) {
BView *view;
if ((view = findLastChild(prevFocus)) != NULL)
if ((view = _LastViewChild(prevFocus)) != NULL)
prevFocus = view;
else if (prevFocus->fPreviousSibling)
prevFocus = prevFocus->fPreviousSibling;
@@ -2586,7 +2754,7 @@ BWindow::_FindPreviousNavigable(BView *focus, uint32 flags)
prevFocus = prevFocus->fParent;
if (prevFocus == fTopView)
prevFocus = findLastChild(prevFocus);
prevFocus = _LastViewChild(prevFocus);
else
prevFocus = prevFocus->fPreviousSibling;
}
@@ -2603,7 +2771,7 @@ BWindow::_FindPreviousNavigable(BView *focus, uint32 flags)
BView *
BWindow::findLastChild(BView *parent)
BWindow::_LastViewChild(BView *parent)
{
BView *last = parent->fFirstChild;
if (last == NULL)