diff --git a/heart/include/hrt/hrt_view.h b/heart/include/hrt/hrt_view.h index 4c660e9..93b4220 100644 --- a/heart/include/hrt/hrt_view.h +++ b/heart/include/hrt/hrt_view.h @@ -65,4 +65,10 @@ void hrt_view_focus(struct hrt_view *view, struct hrt_seat *seat); **/ void hrt_view_unfocus(struct hrt_view *view, struct hrt_seat *seat); +/** + * Stop the given view from being displayed + **/ +void hrt_view_set_hidden(struct hrt_view *view, bool hidden); + + #endif diff --git a/heart/src/view.c b/heart/src/view.c index c3261a9..bb73856 100644 --- a/heart/src/view.c +++ b/heart/src/view.c @@ -69,3 +69,7 @@ void hrt_view_unfocus(struct hrt_view *view, struct hrt_seat *seat) { wlr_xdg_toplevel_set_activated(toplevel, false); wlr_seat_keyboard_notify_clear_focus(seat->seat); } + +void hrt_view_set_hidden(struct hrt_view *view, bool hidden) { + wlr_scene_node_set_enabled(&view->scene_tree->node, !hidden); +} diff --git a/lisp/bindings/hrt-bindings.lisp b/lisp/bindings/hrt-bindings.lisp index 4e62585..0d672cf 100644 --- a/lisp/bindings/hrt-bindings.lisp +++ b/lisp/bindings/hrt-bindings.lisp @@ -127,6 +127,11 @@ it visible to the user." (view (:pointer (:struct hrt-view))) (seat (:pointer (:struct hrt-seat)))) +(cffi:defcfun ("hrt_view_set_hidden" hrt-view-set-hidden) :void + "Stop the given view from being displayed" + (view (:pointer (:struct hrt-view))) + (hidden :bool)) + ;; next section imported from file build/include/hrt/hrt_output.h (cffi:defcstruct hrt-output diff --git a/lisp/bindings/package.lisp b/lisp/bindings/package.lisp index 5b997e1..426a0de 100644 --- a/lisp/bindings/package.lisp +++ b/lisp/bindings/package.lisp @@ -28,6 +28,7 @@ #:view-hrt-view #:focus-view #:unfocus-view + #:view-set-hidden ;; seat callbacks #:button-event #:wheel-event #:keyboard-keypress-event #:hrt-server diff --git a/lisp/bindings/wrappers.lisp b/lisp/bindings/wrappers.lisp index 277f80e..62cae44 100644 --- a/lisp/bindings/wrappers.lisp +++ b/lisp/bindings/wrappers.lisp @@ -34,6 +34,12 @@ (declare (type view view)) (hrt-view-unfocus (view-hrt-view view) seat)) +(declaim (inline view-set-hidden)) +(defun view-set-hidden (view hidden) + (declare (type view view) + (type boolean hidden)) + (hrt-view-set-hidden (view-hrt-view view) hidden)) + (defmethod mh/interface:set-dimensions ((view view) width height) (hrt-view-set-size (view-hrt-view view) width height)) diff --git a/lisp/group.lisp b/lisp/group.lisp index 2157e6f..e7f653c 100644 --- a/lisp/group.lisp +++ b/lisp/group.lisp @@ -62,6 +62,27 @@ to match." (when (and (mahogany-group-current-frame group) (= 0 (hash-table-count output-map))) (group-unfocus-frame group (mahogany-group-current-frame group) seat))))) +(defun %add-hidden (hidden-list view) + (ring-list:add-item hidden-list view) + (hrt:view-set-hidden view t)) + +(defun %swap-next-hidden (hidden-list view) + (let ((swapped (ring-list:swap-next hidden-list view))) + (hrt:view-set-hidden view t) + (hrt:view-set-hidden swapped nil) + swapped)) + +(defun %swap-prev-hidden (hidden-list view) + (let ((swapped (ring-list:swap-previous hidden-list view))) + (hrt:view-set-hidden view t) + (hrt:view-set-hidden swapped nil) + swapped)) + +(defun %pop-hidden-item (hidden-list) + (alexandria:when-let ((popped (ring-list:pop-item hidden-list))) + (hrt:view-set-hidden popped nil) + popped)) + (defun group-add-view (group view) (declare (type mahogany-group group) (type hrt:view view)) @@ -72,7 +93,7 @@ to match." (push view (mahogany-group-views group)) (alexandria:when-let ((current-frame (mahogany-group-current-frame group))) (alexandria:when-let ((view (tree:frame-view current-frame))) - (ring-list:add-item hidden view)) + (%add-hidden hidden view)) (setf (tree:frame-view current-frame) view)))) (defun group-remove-view (group view) @@ -87,7 +108,7 @@ to match." (dolist (f (mahogany/tree:get-populated-frames (mahogany/tree:root-tree container))) (when (equalp (tree:frame-view f) view) (setf (tree:frame-view f) nil) - (alexandria:when-let ((new-view (ring-list:pop-item hidden))) + (alexandria:when-let ((new-view (%pop-hidden-item hidden))) (setf (tree:frame-view f) new-view))))) output-map) (ring-list:remove-item hidden view) @@ -104,11 +125,35 @@ to match." (go :top))))))) (defun group-maximize-current-frame (group) + "Remove all of the splits in the current window tree and replae it with the +currently focused frame" (declare (type mahogany-group group)) (let* ((current-frame (mahogany-group-current-frame group)) (container (mahogany/tree:find-frame-container current-frame)) (tree-root (tree:root-tree container))) (flet ((hide-and-disable (view-frame) - (alexandria:when-let (view (tree:frame-view view-frame)) - (ring-list:add-item (mahogany-group-hidden-views group) view)))) + (alexandria:when-let ((view (tree:frame-view view-frame))) + (%add-hidden (mahogany-group-hidden-views group) view)))) (tree:replace-frame tree-root current-frame #'hide-and-disable)))) + +(defun group-next-hidden (group) + (declare (type mahogany-group group)) + (let ((current-frame (mahogany-group-current-frame group)) + (hidden-views (mahogany-group-hidden-views group)) + (next-view)) + (when (> (ring-list:ring-list-size hidden-views) 0) + (alexandria:if-let ((view (tree:frame-view current-frame))) + (setf next-view (%swap-next-hidden hidden-views view)) + (setf next-view (%pop-hidden-item hidden-views))) + (setf (tree:frame-view current-frame) next-view)))) + +(defun group-previous-hidden (group) + (declare (type mahogany-group group)) + (let ((current-frame (mahogany-group-current-frame group)) + (hidden-views (mahogany-group-hidden-views group)) + (next-view)) + (when (> (ring-list:ring-list-size hidden-views) 0) + (alexandria:if-let ((view (tree:frame-view current-frame))) + (setf next-view (%swap-prev-hidden hidden-views view)) + (setf next-view (%pop-hidden-item hidden-views))) + (setf (tree:frame-view current-frame) next-view)))) diff --git a/lisp/key-bindings.lisp b/lisp/key-bindings.lisp index 16fe434..ee40c82 100644 --- a/lisp/key-bindings.lisp +++ b/lisp/key-bindings.lisp @@ -29,6 +29,18 @@ (let ((group (mahogany-current-group *compositor-state*))) (group-maximize-current-frame group))) +(defun next-view (sequence seat) + "Raise the next hidden view in the current group" + (declare (ignore sequence seat)) + (let ((group (mahogany-current-group *compositor-state*))) + (group-next-hidden group))) + +(defun previous-view (sequence seat) + "Raise the next hidden view in the current group" + (declare (ignore sequence seat)) + (let ((group (mahogany-current-group *compositor-state*))) + (group-previous-hidden group))) + (setf (mahogany-state-keybindings *compositor-state*) (list (define-kmap (kbd "C-t") (define-kmap @@ -37,4 +49,6 @@ (kbd "s") #'split-frame-v (kbd "S") #'split-frame-h (kbd "Q") #'maximize-current-frame + (kbd "n") #'next-view + (kbd "p") #'previous-view (kbd "+") #'open-kcalc)))) diff --git a/lisp/ring-list/ring-list.lisp b/lisp/ring-list/ring-list.lisp index 4c32767..697667b 100644 --- a/lisp/ring-list/ring-list.lisp +++ b/lisp/ring-list/ring-list.lisp @@ -7,6 +7,7 @@ #:add-item #:remove-item #:pop-item + #:pop-item-prev #:swap-next #:swap-previous #:swap-next-find @@ -83,6 +84,14 @@ found and removed" (%remove-item ring-list head) (ring-item-item head)))) +(defun pop-item-prev (ring-list) + (declare (type ring-list ring-list)) + (let ((head (ring-item-prev (ring-list-head ring-list)))) + (when head + (let ((prev (ring-item-prev head))) + (%remove-item ring-list prev) + (ring-item-item prev))))) + (defun %swap-find (ring-list item test swap-fn) (declare (type ring-list ring-list) (type (function (ring-list t) t) swap-fn)