diff options
| -rw-r--r-- | modules/org-agenda-frame.el | 21 | ||||
| -rw-r--r-- | tests/test-org-agenda-frame.el | 41 |
2 files changed, 57 insertions, 5 deletions
diff --git a/modules/org-agenda-frame.el b/modules/org-agenda-frame.el index ef541c2f..efd74115 100644 --- a/modules/org-agenda-frame.el +++ b/modules/org-agenda-frame.el @@ -31,6 +31,8 @@ ;; `with-eval-after-load' so a batch test-load runs no org-agenda side effects. (defvar org-agenda-custom-commands) (defvar org-agenda-finalize-hook) +(defvar org-agenda-sticky) +(defvar org-agenda-window-setup) (declare-function cj/build-org-agenda-list "org-agenda-config" (&optional force-rebuild)) (declare-function cj/org-agenda-refresh-files "org-agenda-config" ()) (declare-function org-agenda-redo "org-agenda" (&optional all)) @@ -357,10 +359,11 @@ the timer and kills the sticky buffer." "Return the frame parameters for the dedicated agenda frame. A normal frame -- not fullscreen -- so a tiling window manager places it side by side with the working frame rather than covering the whole output. -It carries the `cj/agenda-frame' marker and a distinct name so window-manager -rules can target it." +It carries the `cj/agenda-frame' marker and a distinct, noticeable name +\(\"Full Agenda\") so the frame is recognizable at a glance and +window-manager rules can target it." `((,cj/--agenda-frame-parameter . t) - (name . "Org Agenda"))) + (name . "Full Agenda"))) (defun cj/--agenda-frame-spawn () "Create, display, and focus the dedicated agenda frame. @@ -378,7 +381,17 @@ Returns the new agenda frame on success." ;; Cached, non-forced: a frame spawned early after daemon startup ;; still shows the full project agenda, not the base-files-only view. (cj/build-org-agenda-list) - (org-agenda "a" cj/--agenda-frame-command-key) + ;; Bind sticky + current-window dynamically around the render. The + ;; custom command's own settings apply too late to name the buffer; + ;; without these the buffer is plain *Org Agenda*, which matches the + ;; 0.75 below-selected display rule in org-agenda-config.el -- the + ;; new frame gets split with the launch buffer left in the top 25%. + ;; Sticky names it *Org Agenda(F)*, which no display rule matches. + (let ((org-agenda-sticky t) + (org-agenda-window-setup 'current-window)) + (org-agenda "a" cj/--agenda-frame-command-key)) + ;; Belt: whatever a display rule did, the frame is one agenda window. + (delete-other-windows) (let ((buffer (cj/--agenda-frame-sticky-buffer))) (when (buffer-live-p buffer) (with-current-buffer buffer diff --git a/tests/test-org-agenda-frame.el b/tests/test-org-agenda-frame.el index 19dab74b..c29d057b 100644 --- a/tests/test-org-agenda-frame.el +++ b/tests/test-org-agenda-frame.el @@ -772,11 +772,50 @@ Guards against restoring by raw line number after the item moved." side by side with the working frame), carrying the marker and a distinct name." (let ((params (cj/--agenda-frame-make-parameters))) (should (assq cj/--agenda-frame-parameter params)) - (should (equal (cdr (assq 'name params)) "Org Agenda")) + (should (equal (cdr (assq 'name params)) "Full Agenda")) ;; No fullscreen request -- a fullboth frame would cover the whole output ;; instead of tiling beside the working frame. (should-not (assq 'fullscreen params)))) +(ert-deftest test-org-agenda-frame-spawn-binds-sticky-and-current-window () + "Normal: spawn dynamically binds sticky + current-window around the render. +The custom command's own settings apply too late to name the buffer, so +without these bindings the buffer is plain *Org Agenda* -- which matches +the 0.75 below-selected display rule and splits the new frame with the +working buffer left on top." + (let (seen-sticky seen-setup) + (cl-letf (((symbol-function 'selected-frame) (lambda () 'launch)) + ((symbol-function 'make-frame) (lambda (&rest _) 'af)) + ((symbol-function 'select-frame-set-input-focus) (lambda (_f &rest _) nil)) + ((symbol-function 'cj/build-org-agenda-list) (lambda (&rest _) nil)) + ((symbol-function 'org-agenda) + (lambda (&rest _) + (setq seen-sticky org-agenda-sticky + seen-setup org-agenda-window-setup))) + ((symbol-function 'delete-other-windows) (lambda (&rest _) nil)) + ((symbol-function 'cj/--agenda-frame-sticky-buffer) (lambda () nil)) + ((symbol-function 'cj/--agenda-frame-start-timer) (lambda (_f) nil))) + (cj/--agenda-frame-spawn) + (should (eq seen-sticky t)) + (should (eq seen-setup 'current-window))))) + +(ert-deftest test-org-agenda-frame-spawn-forces-single-window () + "Boundary: spawn collapses the frame to one window after rendering. +A display rule that still splits the frame must not leave a second window +showing the launch buffer." + (let (collapsed) + (cl-letf (((symbol-function 'selected-frame) (lambda () 'launch)) + ((symbol-function 'make-frame) (lambda (&rest _) 'af)) + ((symbol-function 'select-frame-set-input-focus) (lambda (_f &rest _) nil)) + ((symbol-function 'cj/build-org-agenda-list) (lambda (&rest _) nil)) + ((symbol-function 'org-agenda) (lambda (&rest _) nil)) + ((symbol-function 'delete-other-windows) + (lambda (&rest _) (setq collapsed t))) + ((symbol-function 'cj/--agenda-frame-sticky-buffer) (lambda () nil)) + ((symbol-function 'cj/--agenda-frame-start-timer) (lambda (_f) nil))) + (cj/--agenda-frame-spawn) + (should collapsed)))) + (ert-deftest test-org-agenda-frame-spawn-starts-timer () "Normal: a successful spawn starts the refresh timer for the new frame." (let (timed) |
