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;
}