diff --git a/src/components/input.lisp b/src/components/input.lisp index 1996d49..419837f 100644 --- a/src/components/input.lisp +++ b/src/components/input.lisp @@ -124,7 +124,10 @@ ((and (>= b #x30) (<= b #x3f)) (if (char= (code-char b) #\;) (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)) nil) ((and (>= b #x40) (<= b #x7e)) @@ -219,15 +222,12 @@ (y (third params)) (button (logand p0 #x03)) (motion (logand p0 #x20)) - (wheel (logand p0 #x40))) + (release (= button 3))) (make-mouse-event - :type (if motion :drag :press) - :button (cond (wheel (if (zerop (logand p0 #x01)) - :wheel-up :wheel-down)) - ((= button 0) :left) - ((= button 1) :middle) - ((= button 2) :right) - (t :none)) + :type (cond (release :release) + (motion :drag) + (t :press)) + :button (let ((b button)) (cond ((= b 0) :left) ((= b 1) :middle) ((= b 2) :right) (t :none))) :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) #\~)) (param (or p0 0)) diff --git a/src/components/mouse.lisp b/src/components/mouse.lisp index 60e641f..db68be7 100644 --- a/src/components/mouse.lisp +++ b/src/components/mouse.lisp @@ -17,17 +17,26 @@ (defun hit-test (root x y) "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." (labels ((recurse (node) - (let ((ln (ignore-errors (component-layout-node node)))) + (let ((ln (ignore-errors (component-layout-node node))) + (best nil)) (when ln (let ((nx (layout-node-x ln)) (ny (layout-node-y ln)) (nw (layout-node-width ln)) (nh (layout-node-height ln))) - (when (and (>= x nx) (< x (+ nx nw)) - (>= y ny) (< y (+ ny nh))) - node)))))) + ;; 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)) + (>= y ny) (< y (+ ny nh))) + node))))))) (recurse root))) ;; Selection diff --git a/src/components/select.lisp b/src/components/select.lisp index 436636e..fb57324 100644 --- a/src/components/select.lisp +++ b/src/components/select.lisp @@ -76,7 +76,9 @@ (subseq filtered start end))) (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)) (visible (select-visible-options sel)) (sel-idx (select-selected-index sel))) (dolist (item visible) diff --git a/src/components/tabbar.lisp b/src/components/tabbar.lisp index f7b7f64..ff94fe6 100644 --- a/src/components/tabbar.lisp +++ b/src/components/tabbar.lisp @@ -35,9 +35,11 @@ (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) - (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)) - (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) (let* ((id (getf tab :id)) (title (getf tab :title)) (label (format nil " ~A " title)) (label-len (length label)) diff --git a/src/components/text-input.lisp b/src/components/text-input.lisp index a00a659..4259f6b 100644 --- a/src/components/text-input.lisp +++ b/src/components/text-input.lisp @@ -165,6 +165,7 @@ (cursor (text-input-cursor in)) (display (if (plusp (length value)) value - (or (text-input-placeholder in) "")))) + (or (text-input-placeholder in) ""))) + (truncated (subseq display 0 (min (length display) w)))) (declare (ignore w cursor)) - (draw-text backend x y display nil nil))) + (draw-text backend x y truncated nil nil))) diff --git a/src/components/textarea.fasl b/src/components/textarea.fasl new file mode 100644 index 0000000..e63852b Binary files /dev/null and b/src/components/textarea.fasl differ diff --git a/src/components/textarea.lisp b/src/components/textarea.lisp index 2c9090e..5c8b1f0 100644 --- a/src/components/textarea.lisp +++ b/src/components/textarea.lisp @@ -248,7 +248,6 @@ (h (if ln (layout-node-height ln) 24)) (lines (textarea-lines ta)) (max-lines (min (length lines) h))) - (declare (ignore w)) (loop for i from 0 below max-lines for line in lines do (draw-text backend x (+ y i)