Implement the BWindow::task_loop again. I know that this is code duplication, but look at

the TODO item for an explanation. We could do this as a hack in Looper.cpp though.
Also implement the determine_target function (incomplete).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12082 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2005-03-27 21:08:38 +00:00
parent 4b72d3d8a8
commit cd970020cb
+121 -54
View File
@@ -67,6 +67,8 @@
#endif #endif
// Globals --------------------------------------------------------------------- // Globals ---------------------------------------------------------------------
using BPrivate::gDefaultTokens;
static property_info windowPropInfo[] = static property_info windowPropInfo[] =
{ {
{ "Feel", { B_GET_PROPERTY, 0 }, { "Feel", { B_GET_PROPERTY, 0 },
@@ -2261,111 +2263,126 @@ void BWindow::InitData( BRect frame, const char* title, window_look look,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// TODO: This here is a nearly full code duplication to BLooper::task_loop
// but with one little difference: It uses the determine_target function
// to tell what the later target of a message will be, if no explicit target
// is supplied. This is important because we need to call the right targets
// MessageFilter. For B_KEY_DOWN messages for example, not the BWindow but the
// focus view will be the target of the message. This means that also the
// focus views MessageFilters have to be checked before DispatchMessage and
// not the ones of this BWindow.
void BWindow::task_looper() void BWindow::task_looper()
{ {
STRACE(("info: BWindow::task_looper() started.\n")); STRACE(("info: BWindow::task_looper() started.\n"));
BLooper::task_looper();
}
/*
// Check that looper is locked (should be) // Check that looper is locked (should be)
AssertLocked(); AssertLocked();
// Unlock the looper
Unlock(); Unlock();
using namespace BPrivate;
bool dispatchNextMessage = false;
BMessage *msg;
// loop: As long as we are not terminating. // loop: As long as we are not terminating.
while (!fTerminating) while (!fTerminating)
{ {
STRACE(("info: BWindow::task_looper() waiting for message.\n")); // TODO: timeout determination algo
msg = MessageFromPort(); // Read from message port (how do we determine what the timeout is?)
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);
STRACE(("info: BWindow::task_looper() queued a message.\n"));
}
// Get message count from port
STRACE(("info: BWindow::task_looper() getting port_count...\n"));
int32 msgCount = port_count(fMsgPort);
if (msgCount > 0){
fQueue->Lock();
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
STRACE(("info: BWindow::task_looper() zero-wait pre-fetch messages...\n"));
msg = MessageFromPort(0);
// Add messages to queue
if (msg)
fQueue->AddMessage(msg);
}
} }
STRACE(("info: BWindow::task_looper() pre-fetching complete.\n")); // Get message count from port
// loop as long as there are messages in the queue and int32 msgCount = port_count(fMsgPort);
// and we are not terminating. for (int32 i = 0; i < msgCount; ++i)
dispatchNextMessage = true; {
// 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) while (!fTerminating && dispatchNextMessage)
{ {
fQueue->Lock(); // Get next message from queue (assign to fLastMessage)
fLastMessage = fQueue->NextMessage(); fLastMessage = fQueue->NextMessage();
fQueue->Unlock();
// Lock the looper
Lock(); Lock();
// TODO: add code for drag & drop
if (!fLastMessage) if (!fLastMessage)
{ {
// No more messages: Unlock the looper and terminate the // No more messages: Unlock the looper and terminate the
// dispatch loop. // dispatch loop.
STRACE(("info: BWindow::task_looper() no more pre-fetched messages.\n"));
dispatchNextMessage = false; dispatchNextMessage = false;
} }
else else
{ {
STRACE(("info: BWindow::task_looper() dispatching...\n"));
STRACE(("info: BWindow::task_looper() "));
// Get the target handler // Get the target handler
// Use BMessage friend functions to determine if we are using the
// preferred handler, or if a target has been specified
BHandler* handler; BHandler* handler;
if (_use_preferred_target_(fLastMessage)) if (_use_preferred_target_(fLastMessage))
{
handler = fPreferred; handler = fPreferred;
}
else else
gDefaultTokens.GetToken(_get_message_target_(fLastMessage), {
B_HANDLER_TOKEN, (void**)&handler); /**
@note Here is where all the token stuff starts to
if (!handler) make sense. How, exactly, do we determine
handler = this; what the target BHandler is? If we look at
BMessage, we see an int32 field, fTarget.
Amazingly, we happen to have a global mapping
of BHandler pointers to int32s!
*/
gDefaultTokens.GetToken(_get_message_target_(fLastMessage),
B_HANDLER_TOKEN,
(void**)&handler);
}
// Is this a scripting message? if (!handler)
{
handler = determine_target(msg, handler, _use_preferred_target_(fLastMessage));
if (!handler)
handler = this;
}
// Is this a scripting message? (BMessage::HasSpecifiers())
if (fLastMessage->HasSpecifiers()) if (fLastMessage->HasSpecifiers())
{ {
int32 index = 0; int32 index = 0;
// Make sure the current specifier is kosher // Make sure the current specifier is kosher
if (fLastMessage->GetCurrentSpecifier(&index) == B_OK) if (fLastMessage->GetCurrentSpecifier(&index) == B_OK)
{
handler = resolve_specifier(handler, fLastMessage); handler = resolve_specifier(handler, fLastMessage);
}
} }
else else
STRACE(("info: BWindow::task_looper() no handler for dispatch.\n")); {
}
if (handler) if (handler)
{ {
// Do filtering // Do filtering
handler = top_level_filter(fLastMessage, handler); handler = top_level_filter(fLastMessage, handler);
if (handler && handler->Looper() == this) if (handler && handler->Looper() == this)
{
DispatchMessage(fLastMessage, handler); DispatchMessage(fLastMessage, handler);
}
} }
} }
// empty our message buffer
fLink->Flush();
// Unlock the looper
Unlock(); Unlock();
// Delete the current message (fLastMessage) // Delete the current message (fLastMessage)
@@ -2383,9 +2400,8 @@ void BWindow::task_looper()
} }
} }
} }
} }
*/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
window_type BWindow::composeType(window_look look, window_type BWindow::composeType(window_look look,
@@ -2578,6 +2594,9 @@ void BWindow::setFocus(BView *focusView, bool notifyInputServer)
{ {
// what am I suppose to do here?? // what am I suppose to do here??
} }
// TODO: find out why R5 does this
SetPreferredHandler(fFocus);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -2616,6 +2635,54 @@ void BWindow::activateView( BView *aView, bool active ){
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
BHandler *
BWindow::determine_target(BMessage *msg, BHandler *target, bool pref)
{
// TODO: this is mostly guessed; check for correctness.
// I think this function is used to determine if a BView will be
// the target of a message. This is used in the BLooper::task_loop
// to determine what BHandler will dispatch the message and what filters
// should be checked before doing so.
printf("determine_target: %x, %x, %s\n", msg, target, pref ? "true" : "false");
switch (msg->what) {
case B_KEY_DOWN:
case B_KEY_UP:
case B_UNMAPPED_KEY_DOWN:
case B_UNMAPPED_KEY_UP:
case B_MODIFIERS_CHANGED:
case B_MOUSE_WHEEL_CHANGED:
// these messages will be dispatched by the focus view later
return fFocus;
case B_MOUSE_DOWN:
case B_MOUSE_UP:
case B_MOUSE_MOVED:
// TODO: find out how to determine the target for these
break;
case B_PULSE:
case B_QUIT_REQUESTED:
// TODO: test wether R5 will let BView dispatch these messages
break;
case B_VIEW_RESIZED:
case B_VIEW_MOVED: {
int32 token = B_NULL_TOKEN;
msg->FindInt32("_token", &token);
BView *view = findView(top_view, token);
if (view)
return view;
} break;
default: break;
}
return target;
}
//------------------------------------------------------------------------------
bool BWindow::handleKeyDown( const char key, uint32 modifiers){ bool BWindow::handleKeyDown( const char key, uint32 modifiers){
// TODO: ask people if using 'raw_char' is OK ? // TODO: ask people if using 'raw_char' is OK ?