OutpostUniverse / OPHD

OutpostHD - Open source remake of Sierra On-Line's Outpost
BSD 3-Clause "New" or "Revised" License
109 stars 20 forks source link

Use event bubbling for UI event dispatch #894

Open DanRStevens opened 3 years ago

DanRStevens commented 3 years ago

We should rework event dispatch so it propagates through a tree of controls. Effectively we should use an event bubbling system, much like is used in Windows. Messages are delivered to a single top-level control, such as the main Window. The Window would be a container control. If the control is a container, then it should propagate event messages to contained controls.

Two main sources of events are keyboard and mouse messages. For keyboard messages, the concept of control "focus" is relevant (related: #884). Keyboard messages to a container are routed to the contained control that has the focus. Mouse messages are instead routed based on screen position of the mouse message, and checking if it overlaps with any of the contained controls. It's possible multiple controls will overlap. In that case, we may wish to route to the top most control. Alternatively, we could potentially look at routing to all controls that overlap with the mouse position.

Some messages, such as resize events, might be propagated to all contained controls.

If a container is disabled or invisible, it can block propagation of all messages to contained controls.

I believe the event bubbling method would help ensure a correct by default behavior in many cases. In particular, developers would no longer need to proactively defend against controls responding to messages when they are not visible or enabled. There seem to have been a number of UI bugs related to controls responding to events when they are not visible, or are obscured by other controls drawn over top. For instance, the following bugs seem to have had something to do with message routing:

ldicker83 commented 3 years ago

This would resolve a lot of complexity issues in event handling of controls (and would make modal dialog boxes way easier to implement, e.g., have an invisible control that covers the entire screen with the modal dialog in the middle, or just set the dialog to consume all events).

Anyway, I tried a system like this in the past that failed horribly which has discouraged me from attempting it again. Instead I went with the sig/slot approach.

I would think this is a better way to handle it but I don't have a lot of good insight into it. I do support it, especially now that I've had some time to think about it and see the problems with the current implementation.

I can at least say that the current implementation suffers from the same problem that Qt and wxWidgets libraries both also suffer from so I at least feel somewhat vindicated knowing that it's not just poor design but simply prone to errors if not carefully handled. :D