[haiku-bugs] [Haiku] #15254: BWindow shouldn't dispatch messages on behalf of BView

  • From: "Haiku" <trac@xxxxxxxxxxxx>
  • To: undisclosed-recipients: ;
  • Date: Fri, 16 Aug 2019 01:07:36 -0000

#15254: BWindow shouldn't dispatch messages on behalf of BView
--------------------------------+------------------------------
 Reporter:  simonsouth          |        Owner:  nobody
     Type:  bug                 |       Status:  new
 Priority:  normal              |    Milestone:  Unscheduled
Component:  Kits/Interface Kit  |      Version:  R1/Development
 Keywords:                      |   Blocked By:
 Blocking:                      |  Has a Patch:  0
 Platform:  All                 |
--------------------------------+------------------------------
 (**TLDR:** I think our BWindow isn't sending to BView all the messages it
 should. If you have access to BeOS, please compile and run on it the
 attached program. Use the mouse and keyboard to try to get as many
 checkboxes checked as possible, then post a screenshot with the results
 and I'll work on a patch for BWindow::DispatchMessage().)

 ----

 In a number of cases, when BWindow's DispatchMessage() method receives a
 message targeting one of its BView instances it will invoke a handler
 method on the BView object directly rather than passing the message on and
 letting the BView handle it itself. In some cases (and there may be more)
 this means BView isn't receiving messages it should be.

 A clear example is BWindow's handling of keystroke-related messages.
 [https://git.haiku-
 
os.org/haiku/tree/src/kits/interface/Window.cpp?id=72b37d9ffc7e083a3f44ebf24e064596e0392b63#n1164
 For example]:

 {{{
 #!c++
 case B_KEY_DOWN:
 {
     if (!_HandleKeyDown(message)) {
         if (BView* view = dynamic_cast<BView*>(target)) {
             // TODO: cannot use "string" here if we support having
             // different font encoding per view (it's supposed to be
             // converted by _HandleKeyDown() one day)
             const char* string;
             ssize_t bytes;
             if (message->FindData("bytes", B_STRING_TYPE,
                 (const void**)&string, &bytes) == B_OK) {
                 view->KeyDown(string, bytes - 1);
             }
         } else
             target->MessageReceived(message);
     }
     break;
 }
 }}}

 Here, if BWindow decides not to capture the keypress itself it "reaches
 into" the target BView and invokes its KeyDown() method directly, rather
 than passing the message on and letting the BView itself decide how to
 handle it (by invoking KeyDown() on its own, presumably). As a result,
 it's difficult for a BView subclass to override or extend this behaviour.

 This strikes me as incorrect, for several reasons:

 1. It embeds in BWindow knowledge about BView and its behaviour, coupling
 the two classes in much the way message-passing systems are meant to
 eliminate.

 2. Since BView's KeyDown() handler is passed only limited information
 about the original message, subclasses that need to work at a lower level
 have to do so in a roundabout manner, re-requesting the message currently
 being handled as [https://git.haiku-
 
os.org/haiku/tree/src/apps/terminal/TermViewStates.cpp?id=72b37d9ffc7e083a3f44ebf24e064596e0392b63#n195
 this example from Terminal] illustrates:

 {{{
 #!c++
 void
 TermView::DefaultState::KeyDown(const char* bytes, int32 numBytes)
 {
         // (...)
         BMessage* currentMessage = fView->Looper()->CurrentMessage();
         if (currentMessage == NULL)
                 return;

         currentMessage->FindInt32("modifiers", &mod);
         currentMessage->FindInt32("key", &key);
         currentMessage->FindInt32("raw_char", &rawChar);
 }}}

 This kind of processing should really be done in an overridden
 MessageReceived() method, but that's not possible right now because the
 object never actually receives the message.

 3. **This is a departure from BeOS' behaviour.** The Be Book's
 [https://www.haiku-os.org/legacy-
 docs/bebook/TheKeyboard_JourneyOfAKeystroke.html section on keystroke-
 event handling] makes this clear:
     The [B_KEY_DOWN] message finally arrives at the view that's currently
 focused in the active window. This view's MessageReceived() function
 processes the keypress in whatever way it wants to.

 Note there are at least eight messages that BWindow "forcibly" dispatches
 in this manner; it's not just keyboard events.

 I'd like to fix this, and to me it makes sense that BWindow should pass on
 to the target BView ''any'' relevant message it decides not to handle on
 its own. However, to make sure this matches what was originally intended,
 I'm attaching to this ticket a little program with a BView subclass that
 listens for specific messages and indicates their receipt by checking a
 checkbox in its UI. This should help reveal which messages our BView
 should be receiving but presently isn't.

 If you have access to BeOS, please compile and run the attached program,
 then use the mouse and keyboard to generate events and try to get all the
 checkboxes to "light up". Post a screenshot with the results, and I can
 work on updating BWindow::DispatchMessage() to match.

-- 
Ticket URL: <https://dev.haiku-os.org/ticket/15254>
Haiku <https://dev.haiku-os.org>
The Haiku operating system.

Other related posts: