Opened 4 years ago

Closed 11 days ago

#10461 closed bug (fixed)

SetEventMask(B_KEYBOARD_EVENTS) leads to duplicate Alt-B, Alt-V ..etc

Reported by: ttcoder Owned by: axeld
Priority: high Milestone: R1
Component: Kits/Interface Kit Version: R1/Development
Keywords: Cc:
Blocked By: Blocking:
Has a Patch: no Platform: All


BView::SetEventMask(B_KEYBOARD_EVENTS) allows a view to "snoop" on the keyboard, i.e. makes the view receive keystrokes regardless of its being the window's current focus view or not.

This currently works not by re-routing the original message (like SetMouseEventMask() does), but instead by sending it normally and then also sending a duplicate copy to the view that called SetEventMask(). That in itself is not a big problem to work-around, as each recipient (the window and the "snooping" view) is free to ignore what does not concern it by re-implementing the concerned hooks...

Except..... in the case of Command-xyz keyboard shortcuts, due to special treatment : they are not dispatched to both recipients -- instead they are both handled by the same recipient, the window. They never reach the view that called SetEventMask() (!) because BWindow::DispatchMessage() processes them apart, consuming them with return true here:

and thus the target view's hooks (KeyDown(), MessageReceived()) are never called, we never enter the if() here:

Thus hitting Command-B leads to be_app.AboutRequested() being called twice, hitting Command-V leads to the clipboard text being pasted twice and so on for other window shortcuts... And contrarily to other keyboard events, there is no clean possibility of fixing the misbehavior, except by hacking/overriding BWindow::DispatchMessage(), as I had to do in my app. Either that, or you have to forget about using SetEventMask(B_KEYBOARD_EVENTS). Somewhat annoying.

Change History (4)

comment:1 Changed 4 years ago by ttcoder

Proposed Solutions: Not sure how feasible it is, but it seems to me SetEventMask() should behave more like SetMouseEventMask() (I might be wrong but I recall that the latter re-routes mouse events instead of adding a second event snooping copy); maybe SetEventMask(keyboard..) should do the same: stop sending the keyboard events to the window and re-route them to the view... And when applicable, the view would "bounce up" those messages it cannot handle, like Command-Q, Command-W ..etc messages, for the window to eventually process them as it should in its own hooks.

Another solution would be to keep the dual-BMessage aspect but fix the special treatment of Command-xyz messages so that it discriminates between the first and second instance of the message: the first instance of e.g. Alt-V would land in the BWindow hooks where it would trigger a B_PASTE (only once!), and the second instance of the Alt-V message would land in the BView KeyDown() hook where it would have a chance of being properly ignored, instead of triggering a second B_PASTE.

comment:2 Changed 4 years ago by axeld

Priority: normalhigh

comment:3 Changed 3 years ago by ttcoder

hrev50033 might be somewhat related (only gave a glance to the git diff, didn't test yet)

-- Seems this bug actually was discovered years before: #5393

Last edited 16 months ago by ttcoder (previous) (diff)

comment:4 Changed 11 days ago by waddlesplash

Resolution: fixed
Status: newclosed

Yep, #5393 was indeed fixed by that commit, so closing this as fixed also.

Note: See TracTickets for help on using tickets.