DVUI

eventMatch

Should e be processed by a widget with the given id and screen rect?

This is the core event matching logic and includes keyboard focus and mouse capture. Call this on each event in events to know whether to process.

If asking whether an existing widget would process an event (if you are wrapping a widget), that widget should have a matchEvent which calls this internally but might extend the logic, or use that function to track state (like whether a modifier key is being pressed).

Only valid between Window.beginand Window.end.

Parameters

#
e:*Event
*Event
opts:EventMatchOptions
EventMatchOptions

Source

Implementation

#
pub fn eventMatch(e: *Event, opts: EventMatchOptions) bool {
    if (e.handled) {
        if (builtin.mode == .Debug and opts.debug) {
            log.debug("eventMatch {f} already handled", .{e});
        }
        return false;
    }

    switch (e.evt) {
        .app => {}, // app events always match
        .window => {
            if (e.target_windowId) |wid| {
                if (wid != opts.id) {
                    if (builtin.mode == .Debug and opts.debug) {
                        log.debug("eventMatch {f} not to this window", .{e});
                    }
                    return false;
                }
            }
        },
        .key, .text => {
            if (e.target_windowId) |wid| {
                // focusable event
                if (opts.cleanup) {
                    // window is catching all focus-routed events that didn't get
                    // processed (maybe the focus widget never showed up)
                    if (wid != opts.id) {
                        // not the focused window
                        if (builtin.mode == .Debug and opts.debug) {
                            log.debug("eventMatch {f} (cleanup) focus not to this window", .{e});
                        }
                        return false;
                    }
                } else {
                    if (e.target_widgetId != opts.id and (opts.focus_id == null or opts.focus_id.? != e.target_widgetId)) {
                        // not the focused widget
                        if (builtin.mode == .Debug and opts.debug) {
                            log.debug("eventMatch {f} focus not to this widget", .{e});
                        }
                        return false;
                    }
                }
            }
        },
        .mouse => |me| {
            var other_capture = false;
            if (e.target_widgetId) |fwid| {
                // this event is during a mouse capture
                if (fwid == opts.id) {
                    // we have capture, we get all capturable mouse events (excludes wheel)
                    return true;
                } else {
                    // someone else has capture
                    other_capture = true;
                }
            }

            const cw = currentWindow();
            if (cw.dragging.state == .dragging and cw.dragging.name != null and (opts.drag_name == null or !std.mem.eql(u8, cw.dragging.name.?, opts.drag_name.?))) {
                // a cross-widget drag is happening that we don't know about
                if (builtin.mode == .Debug and opts.debug) {
                    log.debug("eventMatch {f} drag_name ({?s}) given but current drag is ({?s})", .{ e, opts.drag_name, cw.dragging.name });
                }
                return false;
            }

            if (me.floating_win != subwindowCurrentId()) {
                // floating window is above us
                if (builtin.mode == .Debug and opts.debug) {
                    log.debug("eventMatch {f} floating window above", .{e});
                }
                return false;
            }

            if (!opts.r.contains(me.p)) {
                // mouse not in our rect
                if (builtin.mode == .Debug and opts.debug) {
                    log.debug("eventMatch {f} not in rect", .{e});
                }
                return false;
            }

            if (!clipGet().contains(me.p)) {
                // mouse not in clip region

                // prevents widgets that are scrolled off a
                // scroll area from processing events
                if (builtin.mode == .Debug and opts.debug) {
                    log.debug("eventMatch {f} not in clip", .{e});
                }
                return false;
            }

            if (other_capture) {
                if (captureMouseGet()) |capture| {
                    // someone else has capture, but otherwise we would have gotten
                    // this mouse event
                    if (me.action == .position and capture.subwindow_id == subwindowCurrentId() and !capture.rect.intersect(opts.r).empty()) {
                        // we might be trying to highlight a background around the widget with capture:
                        // * we are in the same subwindow
                        // * our rect overlaps with the capture rect
                        return true;
                    }
                }

                if (builtin.mode == .Debug and opts.debug) {
                    log.debug("eventMatch {f} captured by other widget", .{e});
                }
                return false;
            }
        },
    }

    return true;
}