diff --git a/org/mouse.org b/org/mouse.org index 1e95b7a..701c51f 100644 --- a/org/mouse.org +++ b/org/mouse.org @@ -59,18 +59,27 @@ module adds: (when handler (funcall handler event)))) (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) - (when (and (slot-exists-p node 'x) (slot-boundp node 'x) - (slot-exists-p node 'y) (slot-boundp node 'y) - (slot-exists-p node 'width) (slot-boundp node 'width) - (slot-exists-p node 'height) (slot-boundp node 'height)) - (let ((nx (slot-value node 'x)) - (ny (slot-value node 'y)) - (nw (slot-value node 'width)) - (nh (slot-value node 'height))) - (when (and (>= x nx) (< x (+ nx nw)) - (>= y ny) (< y (+ ny nh))) - 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))) + ;; 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/org/scrollbox-tabbar.org b/org/scrollbox-tabbar.org index c2034e7..9a1de21 100644 --- a/org/scrollbox-tabbar.org +++ b/org/scrollbox-tabbar.org @@ -504,7 +504,8 @@ they are truncated with an ellipsis. #+BEGIN_SRC lisp (defmethod render ((tb tab-bar) backend) (let* ((ln (tab-bar-layout-node tb)) - (x 0) (y 0) + (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)) @@ -664,9 +665,11 @@ Children outside the viewport are skipped." (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/org/select.org b/org/select.org index 47baf55..d9bb177 100644 --- a/org/select.org +++ b/org/select.org @@ -402,7 +402,8 @@ not selectable (visually distinct). #+BEGIN_SRC lisp (defmethod render ((sel select) backend) (let* ((ln (select-layout-node sel)) - (x 0) (y 0) + (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))) @@ -508,7 +509,9 @@ not selectable (visually distinct). (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/org/text-input.org b/org/text-input.org index 0b6f1ba..0d95004 100644 --- a/org/text-input.org +++ b/org/text-input.org @@ -603,9 +603,9 @@ debugging argument mismatches — avoid that trap. (cursor (text-input-cursor in)) (display (if (plusp (length value)) value - (or (text-input-placeholder in) "")))) - (declare (ignore w cursor)) - (draw-text backend x y display nil nil))) + (or (text-input-placeholder in) ""))) + (truncated (subseq display 0 (min (length display) w)))) + (draw-text backend x y truncated nil nil))) #+END_SRC @@ -861,7 +861,6 @@ debugging argument mismatches — avoid that trap. (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) diff --git a/src/components/scrollbox.lisp b/src/components/scrollbox.lisp index 6fa71ac..96a7641 100644 --- a/src/components/scrollbox.lisp +++ b/src/components/scrollbox.lisp @@ -72,21 +72,18 @@ Children outside the viewport are skipped." (if (> content-size viewport-size) (/ (float scroll-pos) (- content-size viewport-size)) 0.0)) (defun draw-scrollbars (sb backend viewport-w viewport-h) - (let* ((ln (scroll-box-layout-node sb)) - (vx (if ln (layout-node-x ln) 0)) - (vy (if ln (layout-node-y ln) 0)) - (content-h (scroll-box-content-height sb)) (content-w (scroll-box-content-width sb)) + (let* ((content-h (scroll-box-content-height sb)) (content-w (scroll-box-content-width sb)) (sy (scroll-box-scroll-y sb)) (sx (scroll-box-scroll-x sb))) (when (> content-h viewport-h) (let* ((thumb (scrollbar-thumb sy viewport-h content-h)) (thumb-pos (round (* thumb viewport-h)))) - (draw-rect backend (+ vx (1- viewport-w)) vy 1 viewport-h :bg :bright-black) - (draw-text backend (+ vx (1- viewport-w)) (+ vy thumb-pos) "█" nil nil))) + (draw-rect backend (1- viewport-w) 0 1 viewport-h :bg :bright-black) + (draw-text backend (1- viewport-w) thumb-pos "█" nil nil))) (when (> content-w viewport-w) (let* ((thumb (scrollbar-thumb sx viewport-w content-w)) (thumb-pos (round (* thumb viewport-w)))) - (draw-rect backend vx (+ vy (1- viewport-h)) viewport-w 1 :bg :bright-black) - (draw-text backend (+ vx thumb-pos) (+ vy (1- viewport-h)) "█" nil nil))))) + (draw-rect backend 0 (1- viewport-h) viewport-w 1 :bg :bright-black) + (draw-text backend thumb-pos (1- viewport-h) "█" nil nil))))) (defun update-sticky-scroll (sb) (when (sticky-scroll-p sb) diff --git a/src/components/tabbar.lisp b/src/components/tabbar.lisp index ff94fe6..1ec6219 100644 --- a/src/components/tabbar.lisp +++ b/src/components/tabbar.lisp @@ -46,7 +46,7 @@ (is-active (eql id active-id)) (fg (if is-active :accent :text-muted)) (bg (if is-active :background-element nil))) - (when (> (+ x-pos label-len 2) w) + (when (>= (+ x-pos label-len 2) w) (draw-text backend x-pos y "..." :text-muted nil) (return)) (draw-text backend x-pos y label fg bg) (incf x-pos (+ label-len 2)))))