Skip to content

Design: mouse support

Alexandre Bury edited this page Oct 11, 2017 · 7 revisions

Mouse events add new challenges not present with usual keyboard events: they include a location for the pointer.

This location only makes sense for a view if it can make it relative to the view itself - currently, views don't know where on the screen they are (if they are anywhere at all).

Mouse events are provided by the backend with absolute coordinates. Here are some solutions for what happens next.

Solution 1: Relative event position

In this situation, when a parent views forwards an event to its child, it modifies the event location to make it relative to the child's viewport. Problem: locations currently use usize.

  • Solution 1.a: only forward mouse events that fit in the child viewport, so the location is always positive.
    • Pro: very small impact on the overall architecture
    • Con: add some complexity, since some events should not be forwarded (when outside of the screen)
  • Solution 1.b: include a location: Option<Vec2> in the mouse event. This location is relative, and None if the event is outside the view.
    • Pro: require less work in parent views than 1.a
    • Con: small inconsistencies (no location information for out-of-view events)
  • Solution 1.c: use signed values in the location, and allow negative values.
    • Pro: small impact on overall architecture
    • Con: need to deal with differently signed values

Solution 2: Embed the offset in the event

Similar to solution 1.c, but instead of signed values, events would include both the absolute value and the absolute offset of the view. Parent views are responsible for updating this offset when forwarding events.

  • Pro: small impact on overall architecture
  • Con: make the Event type larger

Solution 3: Include offset in separate Context

In this solution, the View::on_event method is updated to take an additional event::Context argument. This context would currently only include the absolute offset of the view. Child views can then compare the mouse event location and the offset to determine the relative position.

  • Pro: events don't need to be "relativized" (but the context needs to be updated)
  • Pro: Context could be extended to include more information on the view chain.
  • Con: larger impact (changes the View trait)
  • Con: Context only useful for mouse events.

Decision

I'll probably go with solution 2, since the size increase for the Event type is a rather remote concern.

A cleaner structure for mouse events would also be a nice thing. A cleaner structure for the entire event enum would be good actually, BUT! this will come in a separate project. First, focus on the mouse part only.

Event relativization

With the selected solution comes the need for event relativization: when a view group forwards an event to its child, it must pass a modified version with the view offset added. This means view groups must know, at event-processing-time, where its children are located.

Behaviour changes

View Groups

  • StackView: relativize with the view offset.
  • LinearLayout, ListView:
    • If button press:
      • Find view for the given position. Change focus if needed.
    • If button release:
      • Send to currently active view?
    • If wheel move:
      • Find view for the given position. Send the event without focus change?
    • Relativize with the offset.
    • Use ignored mouse wheel to scroll the view?

Wrapper nodes

  • BoxView:
    • Top-left is never changed, so just forward events.
  • Dialog:
    • Top-left is always offset by (1, 1), so constant relativization.
  • Panel:
    • Constant (1, 1) offset.
  • ShadowView:
    • Constant offset as well.
  • The other wrappers aren't even related to sizing.

Leaf nodes

  • Button:
    • Send click event if Left button is Pressed within bounds, then Released within bounds.
  • EditText, TextArea:
    • Mouse wheel scroll on TextArea
    • Left button press moves the cursor.
  • Checkbox, radio: left press+release toggles the state
  • SelectView:
    • Mouse wheel scrolls.
    • Left press+release changes selection. Again sends on_enter?
  • SliderView:
    • Mouse wheel moves the slider?
    • Mouse press moves the slider? What about mouse hold?
  • Menubar:
    • Left button opens a menu.
    • Mouse wheel?
    • Should left button make auto-hide menubar appear?