
|
[haiku-appserver]
||
[Date Prev]
[03-2005 Date Index]
[Date Next]
||
[Thread Prev]
[03-2005 Thread Index]
[Thread Next]
[haiku-appserver] Re: [Haiku-commits] r12082 - haiku/trunk/src/kits/interface
- From: Michael Lotz <mmlr@xxxxxxxx>
- To: haiku-appserver@xxxxxxxxxxxxx
- Date: Tue, 29 Mar 2005 10:24:24 +0200
> For B_KEY_DOWN, BWindow will first handle this message in
> DispatchMessage to intercept TAB, SHIFT+TAB, OPTION+TAB, etc keystrokes
> to that it would advance to the next focus item/group. It is after that
> check that it calls fFocus->KeyDown(); Same goes for the menu and
> DefaultButton.
This is exactly what has to be avoided here. For clarifying what I mean, here's
an example
situation (from the MiniTerminal actually):
You have your BWindow which has a BView attached where you track B_KEY_DOWNs
with the
KeyDown hook function. This works well for almost all cases. But if you want to
write a
Terminal application, you will need to get those B_TAB keys too.
The BeBook describes the BMessageFilter as follows:
A BMessageFilter is a message-screening function that you "attach" to a BLooper
or
BHandler. The message filter sees messages just before they're dispatched (i.e.
just
before BLooper::DispatchMessage()), ...
So the way we can get those B_TAB keys is to attach a
BMessageFilter(B_KEY_DOWN, <filter
function>) to the BView. We add it to the view because if we had multiple views
we maybe
would want a different function to handle the B_TAB for any given view
depending on which
one has the focus.
If you follow the BeBook all B_KEY_DOWN messages that would arrive in the
KeyDown hook
later should go to the filter function, plus those who would normally be
dispatched by
BWindow like the B_TAB.
Look at MiniView.cpp in src/tests/apps/miniterminal for the implementation.
This way it
works under R5 as it should and we get the following if we hit debugger from
the filter
function:
w>MiniTerminal:sc
frame retaddr
fd039c18 8000608e MiniView::MessageFilter(BMessage *, BHandler **,
BMessageFilter *) +
0000002e
fd039c58 ec199012 BLooper::apply_filters(BList *, BMessage *, BHandler *) +
000000e2
fd039c88 ec19a8ab BLooper::top_level_filter(BMessage *, BHandler *) +
00000087
fd039cac ec25307e BWindow::task_looper(void) + 000003a2
fd039d28 ec19ae46 BLooper::_task0_(void *) + 00000036
fd039d3c ec06c50d thread_start + 00000039
w>MiniTerminal:
This tells us, the BWindow::task_looper got the message, called apply_filters
and found
the filter we added to our BView and called it's function.
Without my change, we do pretty much the same thing, we would get into the
task_looper and
would call apply_filters. BUT we would not catch the filter that was added to
our BView,
because we would only check the filters that were applied to the BWindow itself
and not to
the view that will later receive the B_KEY_DOWN event.
If we bdb the MiniTerminal from where we will find that the
BWindow::task_looper calls
BWindow::determine_target somewhere before applying the filters. What I guess
from this
now is: The BWindow finds out whether itself or the focus view will be the
target for this
event and then calls apply_filters for the actual target and not itself.
For any B_KEY_DOWN or B_KEY_UP event aswell as B_UNMAPPED_KEY_DOWN,
B_UNMAPPED_KEY_UP,
B_MODIFIERS_CHANGED and B_MOUSE_WHEEL_CHANGED the focus view will be the actual
target, so
this is what determine_target returns.
This does not break the path of the message to dispatch. Even if we change the
target, the
BWindow will get the message to dispatch, but only if we did not filter it out
by our
BMessageFilter:
if (handler) // the determine_target one -> our MiniView
{
// Do filtering
handler = top_level_filter(fLastMessage, handler);
// filtering is applied to the BMessageFilters of MiniView
// if we skip the message from within the filter, handler will be NULL.
// if we don't change the handler to something else from within our
// filter funcation, the looper of the handler will be the looper of
// the BWindow we are in -> this one.
if (handler && handler->Looper() == this)
{
// so we get here normally and can handle B_TAB from
// BWindow for TAB navigation.
DispatchMessage(fLastMessage, handler);
}
}
We must find out what the target will be first, only then we can call the
correct filters.
I hope this clears it up a bit.
Regards
Michael Lotz
|

|