v0.15.0: Critical input/rendering fixes, subagent-reviewed #7

Merged
amr merged 36 commits from feature/v0.11.0-slots into main 2026-05-11 22:03:18 -04:00
7 changed files with 32 additions and 19 deletions
Showing only changes of commit a294f21c70 - Show all commits

View File

@@ -124,7 +124,10 @@
((and (>= b #x30) (<= b #x3f)) ((and (>= b #x30) (<= b #x3f))
(if (char= (code-char b) #\;) (if (char= (code-char b) #\;)
(progn (push current params) (setf current 0)) (progn (push current params) (setf current 0))
(setf current (+ (* current 10) (- b #x30))))) ;; Non-digit parameter characters (< = > ?) start a new param at zero
(if (member b '(#x3c #x3d #x3e #x3f) :test #'=)
(setf current 0)
(setf current (+ (* current 10) (- b #x30))))))
((and (>= b #x20) (<= b #x2f)) ((and (>= b #x20) (<= b #x2f))
nil) nil)
((and (>= b #x40) (<= b #x7e)) ((and (>= b #x40) (<= b #x7e))
@@ -219,15 +222,12 @@
(y (third params)) (y (third params))
(button (logand p0 #x03)) (button (logand p0 #x03))
(motion (logand p0 #x20)) (motion (logand p0 #x20))
(wheel (logand p0 #x40))) (release (= button 3)))
(make-mouse-event (make-mouse-event
:type (if motion :drag :press) :type (cond (release :release)
:button (cond (wheel (if (zerop (logand p0 #x01)) (motion :drag)
:wheel-up :wheel-down)) (t :press))
((= button 0) :left) :button (let ((b button)) (cond ((= b 0) :left) ((= b 1) :middle) ((= b 2) :right) (t :none)))
((= button 1) :middle)
((= button 2) :right)
(t :none))
:x x :y y :raw (format nil "~C[<~d;~d;~d~C" #\Esc p0 x y (code-char final-byte)))) :x x :y y :raw (format nil "~C[<~d;~d;~d~C" #\Esc p0 x y (code-char final-byte))))
(let* ((tilde-p (char= (code-char final-byte) #\~)) (let* ((tilde-p (char= (code-char final-byte) #\~))
(param (or p0 0)) (param (or p0 0))

View File

@@ -17,17 +17,26 @@
(defun hit-test (root x y) (defun hit-test (root x y)
"Find the deepest component at (X, Y) by testing layout-node bounds. "Find the deepest component at (X, Y) by testing layout-node bounds.
Recurses into component-children to find the innermost match.
Components without a layout-node or position return nil." Components without a layout-node or position return nil."
(labels ((recurse (node) (labels ((recurse (node)
(let ((ln (ignore-errors (component-layout-node node)))) (let ((ln (ignore-errors (component-layout-node node)))
(best nil))
(when ln (when ln
(let ((nx (layout-node-x ln)) (let ((nx (layout-node-x ln))
(ny (layout-node-y ln)) (ny (layout-node-y ln))
(nw (layout-node-width ln)) (nw (layout-node-width ln))
(nh (layout-node-height ln))) (nh (layout-node-height ln)))
;; Check children first for deeper match
(dolist (child (ignore-errors (component-children node)))
(let ((child-hit (recurse child)))
(when child-hit
(setf best child-hit))))
;; If no child matched, check self
(or best
(when (and (>= x nx) (< x (+ nx nw)) (when (and (>= x nx) (< x (+ nx nw))
(>= y ny) (< y (+ ny nh))) (>= y ny) (< y (+ ny nh)))
node)))))) node)))))))
(recurse root))) (recurse root)))
;; Selection ;; Selection

View File

@@ -76,7 +76,9 @@
(subseq filtered start end))) (subseq filtered start end)))
(defmethod render ((sel select) backend) (defmethod render ((sel select) backend)
(let* ((ln (select-layout-node sel)) (x 0) (y 0) (let* ((ln (select-layout-node sel))
(x (if ln (layout-node-x ln) 0))
(y (if ln (layout-node-y ln) 0))
(w (if ln (layout-node-width ln) 80)) (w (if ln (layout-node-width ln) 80))
(visible (select-visible-options sel)) (sel-idx (select-selected-index sel))) (visible (select-visible-options sel)) (sel-idx (select-selected-index sel)))
(dolist (item visible) (dolist (item visible)

View File

@@ -35,9 +35,11 @@
(case (key-event-key event) (:left (tab-bar-prev tb) t) (:right (tab-bar-next tb) t) (t nil))) (case (key-event-key event) (:left (tab-bar-prev tb) t) (:right (tab-bar-next tb) t) (t nil)))
(defmethod render ((tb tab-bar) backend) (defmethod render ((tb tab-bar) backend)
(let* ((ln (tab-bar-layout-node tb)) (y 0) (let* ((ln (tab-bar-layout-node tb))
(x (if ln (layout-node-x ln) 0))
(y (if ln (layout-node-y ln) 0))
(w (if ln (layout-node-width ln) 80)) (w (if ln (layout-node-width ln) 80))
(active-id (tab-bar-active tb)) (tabs (tab-bar-tabs tb)) (x-pos 0)) (active-id (tab-bar-active tb)) (tabs (tab-bar-tabs tb)) (x-pos x))
(dolist (tab tabs) (dolist (tab tabs)
(let* ((id (getf tab :id)) (title (getf tab :title)) (let* ((id (getf tab :id)) (title (getf tab :title))
(label (format nil " ~A " title)) (label-len (length label)) (label (format nil " ~A " title)) (label-len (length label))

View File

@@ -165,6 +165,7 @@
(cursor (text-input-cursor in)) (cursor (text-input-cursor in))
(display (if (plusp (length value)) (display (if (plusp (length value))
value value
(or (text-input-placeholder in) "")))) (or (text-input-placeholder in) "")))
(truncated (subseq display 0 (min (length display) w))))
(declare (ignore w cursor)) (declare (ignore w cursor))
(draw-text backend x y display nil nil))) (draw-text backend x y truncated nil nil)))

Binary file not shown.

View File

@@ -248,7 +248,6 @@
(h (if ln (layout-node-height ln) 24)) (h (if ln (layout-node-height ln) 24))
(lines (textarea-lines ta)) (lines (textarea-lines ta))
(max-lines (min (length lines) h))) (max-lines (min (length lines) h)))
(declare (ignore w))
(loop for i from 0 below max-lines (loop for i from 0 below max-lines
for line in lines for line in lines
do (draw-text backend x (+ y i) do (draw-text backend x (+ y i)