[haiku-appserver] Re: [Haiku-commits] r12082 - haiku/trunk/src/kits/interface

  • From: "Axel Dörfler" <axeld@xxxxxxxxxxxxxxxx>
  • To: haiku-appserver@xxxxxxxxxxxxx
  • Date: Tue, 29 Mar 2005 14:27:30 +0200 CEST

Michael Lotz <mmlr@xxxxxxxx> wrote:
>  > 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.
> 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.

Actually, this is not correct; the basic idea is, but the B_TAB key is 
(like all other keys) supposed to get through to a normal KeyDown(). 
The view itself is responsible to trigger the navigation (as stippi 
correctly remembered) - AFAICT the window only handles the control 
group navigation.
IOW our implementation seems to be wrong - but please check before you 
trust me :-)

[...]
> later should go to the filter function, plus those who would normally 
> be dispatched by 
> BWindow like the B_TAB.

Again, that's not correct. BWindow dispatches key events in 
DispatchMessage() and makes sure that all command keys are filtered 
out, etc. B_TAB comes definitely through.

> 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.

Note that this only applies if the target handler is known at this 
point. If all handlers are asked subsequently, the message filter must 
still be applied, which is not yet done (I recently added a comment 
about this to BHandler::MessageReceived()).

> 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.

A looper knows about its handlers as a windows knows its views - there 
is nothing special here; a looper must apply the filters for the 
handlers, the window itself shouldn't care.

> 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.

Why should that behaviour be different for a BWindow (compared to a 
BLooper)?

> 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);
>      }

A filter can redirect a message to another looper? And if that's the 
case, it should probably not be eaten like done here.

> 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.

That part is correct, but for loopers too.

Bye,
   Axel.


Other related posts: