feat(ui): a key field takes a mouse button, and is :capturing while it listens

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-24 22:04:47 +03:00
parent 6bd3228990
commit d15cc79822
9 changed files with 90 additions and 3 deletions

View file

@ -46,7 +46,9 @@ function ct_key_pressed_away(hit: UiNode) -> void {
function ct_key_text(n: UiNode) -> string {
if ct_capture == n.key { return ui_tr("press a key...") }
if Value.kind(ui_attr(n, "shown")) != 0 { return ui_tr(ui_attr_text(n, "shown")) }
return Input.key_label(Value.as_int(ui_attr(n, "value")))
let v = Value.as_int(ui_attr(n, "value"))
if v >= UI_MOUSE_LEFT and v <= UI_MOUSE_MIDDLE { return ct_mouse_name(v) }
return Input.key_label(v)
}
# a key field is listening: the host should leave the keys alone until it is done (it stays true
# for the frame in which Esc or a key ended it, so that key is not read twice)

View file

@ -0,0 +1,22 @@
# controls_key_mouse.ludic - a key field listening takes a mouse button too: the left, right or
# middle button pressed anywhere is its value, as UI_MOUSE_LEFT, UI_MOUSE_RIGHT or UI_MOUSE_MIDDLE
# (past every key code, for the host to map), and that press does nothing else
export const UI_MOUSE_LEFT: int = 256
export const UI_MOUSE_RIGHT: int = 257
export const UI_MOUSE_MIDDLE: int = 258
function ct_key_mouse(root: UiNode) -> bool {
if ct_capture == "" or ct_capture_at == an_frame { return false }
let b = pe_pressed(in_now, in_last)
if b < 0 { return false }
let n = fr_node(root, ct_capture)
ct_capture = ""
ct_capture_seen = an_frame
fr_press_key = ""
if n != null { ct_change(n, Value.int(UI_MOUSE_LEFT + b)) }
return true
}
function ct_mouse_name(v: int) -> string {
if v == UI_MOUSE_RIGHT { return ui_tr("Right click") }
if v == UI_MOUSE_MIDDLE { return ui_tr("Middle click") }
return ui_tr("Left click")
}

View file

@ -19,6 +19,7 @@ import "controls.ludic"
import "controls_build.ludic"
import "controls_parts.ludic"
import "controls_key.ludic"
import "controls_key_mouse.ludic"
import "controls_number.ludic"
import "input.ludic"
import "input_pad.ludic"

View file

@ -17,7 +17,7 @@ function fr_pointer(root: UiNode) -> void {
fr_hover = keys
tt_track(scope, i.x, i.y)
if top != null and pp_pointer(top) { return }
if sc_drag != "" { return }
if sc_drag != "" or ct_key_mouse(root) { return }
let hit = fr_hit(scope, i.x, i.y)
pe_frame(root, scope)
if i.down and not in_was_down { fr_press(hit, i.x, i.y) }

View file

@ -76,6 +76,7 @@ function sel_pseudo_ok(p: string, arg: string, n: UiNode) -> bool {
if p == "root" { return n.parent == null }
if p == "checked" { return ui_attr_on(n, "checked") }
if p == "active" { return fr_active(n) }
if p == "capturing" { return ct_capture != "" and n.key == ct_capture }
if p == "nth-child" { return sel_nth(arg, n.index + 1) }
ui_err(`:{p}: there is no such pseudo-class here`)
return false