aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorF. Jason Park2024-05-21 05:37:39 -0700
committerF. Jason Park2024-05-27 16:39:18 -0700
commit1b633ea59ad7f27263bf2a74ecc0e7d048b5eab5 (patch)
tree3e5c33d5ee1063ba47c35c72184edd6f4f6ec7a1
parent8c54a79ec10d21cfc961476d85db06b643260e38 (diff)
downloademacs-1b633ea59ad7f27263bf2a74ecc0e7d048b5eab5.tar.gz
emacs-1b633ea59ad7f27263bf2a74ecc0e7d048b5eab5.zip
Delete original speedbar frame in erc-nickbar-mode
* lisp/erc/erc-speedbar.el (erc-speedbar-buttons): Disable `erc-nickbar-mode' when it's not displayed in a window. (erc-speedbar--highlight-self-and-ops): Check `status' slot of `erc-channel-user' object instead of calling accessors. (erc-speedbar--hidden-speedbar-frame) (erc-speedbar--emulate-speedbar): Add doc string. (erc-speedbar--handle-delete-frame): New function. (erc-speedbar--toggle-nicknames-sidebar): Remove function because its conditional logic was needlessly complicated and is no longer needed. (erc-speedbar--ensure): Create `speedbar-buffer' when needed, and delete the original frame, but still keep a reference to it in `erc-speedbar--hidden-speedbar-frame'. Set `dframe-delete-frame-function' to own handler. (erc-speedbar--shutting-down-p): Remove unused variable. (erc-speedbar--run-timer-on-post-insert) (erc-speedbar--prod-dframe-timer): Rename former to latter. Return nil, and accept any number of args. (erc-nickbar-mode, erc-nickbar-disable): Tear down completely when disabling, regardless of universal argument. This changes user-facing behavior that was originally introduced with this module as part of bug#63595. Run `erc-speedbar--prod-dframe-timer' on `erc-server-PONG-functions' as well as `erc-insert-post-hook' so that the panel will eventually update if no messages are being received. (erc-speedbar--dframe-controlled): Don't make frame visible because it's been deleted and was never made invisible. * test/lisp/erc/erc-scenarios-status-sidebar.el (erc-scenarios-status-sidebar--nickbar): Update assertions.
-rw-r--r--lisp/erc/erc-speedbar.el203
-rw-r--r--test/lisp/erc/erc-scenarios-status-sidebar.el16
2 files changed, 110 insertions, 109 deletions
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index b156f61d5d9..9cde452be58 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -146,7 +146,10 @@ This will add a speedbar major display mode."
146 (setq serverp (erc--server-buffer-p)) 146 (setq serverp (erc--server-buffer-p))
147 (setq chanp (erc-channel-p (erc-default-target))) 147 (setq chanp (erc-channel-p (erc-default-target)))
148 (setq queryp (erc-query-buffer-p))) 148 (setq queryp (erc-query-buffer-p)))
149 (cond (serverp 149 (defvar erc-nickbar-mode)
150 (cond ((and erc-nickbar-mode (null (get-buffer-window speedbar-buffer)))
151 (run-at-time 0 nil #'erc-nickbar-mode -1))
152 (serverp
150 (erc-speedbar-channel-buttons nil 0 buffer)) 153 (erc-speedbar-channel-buttons nil 0 buffer))
151 (chanp 154 (chanp
152 (erc-speedbar-insert-target buffer 0) 155 (erc-speedbar-insert-target buffer 0)
@@ -288,15 +291,9 @@ composed or anonymous, or nil.")
288 'erc-current-nick-face 291 'erc-current-nick-face
289 'erc-my-nick-face)) 292 'erc-my-nick-face))
290 (v v)) 293 (v v))
291 ;; FIXME overload `erc-channel-user-owner-p' and friends to 294 (or (and cuser (not (zerop (erc-channel-user-status cuser)))
292 ;; accept an `erc-channel-user' object and replace this unrolled 295 erc-button-nickname-face)
293 ;; stuff with a single call to `erc-get-user-mode-prefix'. 296 'erc-default-face))))
294 (and cuser (or (erc-channel-user-owner cuser)
295 (erc-channel-user-admin cuser)
296 (erc-channel-user-op cuser)
297 (erc-channel-user-halfop cuser)
298 (erc-channel-user-voice cuser))
299 erc-button-nickname-face))))
300 297
301(defun erc-speedbar--on-click (nick sbtoken _indent) 298(defun erc-speedbar--on-click (nick sbtoken _indent)
302 ;; 0: finger, 1: name, 2: info, 3: buffer-name 299 ;; 0: finger, 1: name, 2: info, 3: buffer-name
@@ -447,7 +444,11 @@ The INDENT level is ignored."
447 (speedbar-use-images . nil) 444 (speedbar-use-images . nil)
448 (speedbar-hide-button-brackets-flag . t))) 445 (speedbar-hide-button-brackets-flag . t)))
449 446
450(defvar erc-speedbar--hidden-speedbar-frame nil) 447(defvar erc-speedbar--hidden-speedbar-frame nil
448 "The original `speedbar-frame', which `erc-nickbar-mode' deletes.
449It keeps a reference to it in order to run upstream teardown
450procedures without having to create a dummy frame for that
451purpose.")
451 452
452(defun erc-speedbar--emulate-sidebar-set-window-preserve-size () 453(defun erc-speedbar--emulate-sidebar-set-window-preserve-size ()
453 (let ((erc-status-sidebar-buffer-name (buffer-name speedbar-buffer)) 454 (let ((erc-status-sidebar-buffer-name (buffer-name speedbar-buffer))
@@ -463,6 +464,7 @@ The INDENT level is ignored."
463 #'erc-speedbar--emulate-sidebar-set-window-preserve-size)) 464 #'erc-speedbar--emulate-sidebar-set-window-preserve-size))
464 465
465(defun erc-speedbar--emulate-sidebar () 466(defun erc-speedbar--emulate-sidebar ()
467 "Perform local setup for `erc-nickbar-mode' in a new `speedbar-buffer'."
466 (require 'erc-status-sidebar) 468 (require 'erc-status-sidebar)
467 (cl-assert speedbar-frame) 469 (cl-assert speedbar-frame)
468 (cl-assert (eq speedbar-buffer (current-buffer))) 470 (cl-assert (eq speedbar-buffer (current-buffer)))
@@ -482,30 +484,32 @@ The INDENT level is ignored."
482 (add-function :around (local 'erc-speedbar--nick-face-function) 484 (add-function :around (local 'erc-speedbar--nick-face-function)
483 #'erc-speedbar--compose-nicks-face)))) 485 #'erc-speedbar--compose-nicks-face))))
484 486
485(defun erc-speedbar--toggle-nicknames-sidebar (arg) 487(defun erc-speedbar--handle-delete-frame (event)
486 (let ((force (numberp arg))) 488 "Disable the nickbar if EVENT is deleting the proxy frame."
487 (if speedbar-buffer 489 (when (and speedbar-frame
488 (progn 490 (cdr (frame-list))
489 (cl-assert (buffer-live-p speedbar-buffer)) 491 (pcase event
490 (if (or (and force (< arg 0)) 492 (`(delete-frame (,frame)) (eq frame speedbar-frame))))
491 (and (not force) (get-buffer-window speedbar-buffer nil))) 493 (erc-nickbar-mode -1)))
492 ;; Close associated windows and stop updating but leave timer. 494
493 (progn 495(defun erc-speedbar--ensure (&optional forcep)
494 (dolist (window (get-buffer-window-list speedbar-buffer nil t)) 496 "Perform common setup for `erc-nickbar-mode'.
495 (unless (frame-root-window-p window) 497Without FORCEP, return early when the calling context isn't
496 (when erc-speedbar--hidden-speedbar-frame 498associated with an ERC session."
497 (cl-assert 499 (save-excursion
498 (not (eq (window-frame window) 500 (when (or (erc-server-buffer) forcep)
499 erc-speedbar--hidden-speedbar-frame)))) 501 (when erc-track-mode
500 (delete-window window))) 502 (cl-pushnew '(derived-mode . speedbar-mode)
501 (with-current-buffer speedbar-buffer 503 erc-track--switch-fallback-blockers :test #'equal))
502 (setq speedbar-update-flag nil) 504 (unless speedbar-update-flag
503 (speedbar-set-mode-line-format))) 505 (erc-button--display-error-notice-with-keys
504 (when (or (not force) (>= arg 0)) 506 (erc-server-buffer)
505 (with-selected-frame speedbar-frame 507 "Module `nickbar' needs `speedbar-update-flag' to be non-nil"
506 (erc-speedbar--emulate-sidebar-set-window-preserve-size) 508 (and (not (display-graphic-p)) " in text terminals")
507 (erc-speedbar-toggle-nicknames-window-lock -1))))) 509 ". Setting to t for the current Emacs session."
508 (when-let (((or (not force) (>= arg 0))) 510 " Customize it permanently to avoid this message.")
511 (setq speedbar-update-flag t))
512 (when-let (((null speedbar-buffer))
509 (speedbar-frame-parameters (backquote-list* 513 (speedbar-frame-parameters (backquote-list*
510 '(visibility . nil) 514 '(visibility . nil)
511 '(no-other-frame . t) 515 '(no-other-frame . t)
@@ -516,52 +520,45 @@ The INDENT level is ignored."
516 ;; created twice. 520 ;; created twice.
517 (speedbar-change-initial-expansion-list "ERC") 521 (speedbar-change-initial-expansion-list "ERC")
518 (speedbar-frame-mode 1) 522 (speedbar-frame-mode 1)
519 ;; If we put the remaining parts in the "create hook" along 523 ;; The setup steps below can't go in the "create hook" because
520 ;; with everything else, the frame with `window-main-window' 524 ;; the frame with `window-main-window' will be raised and
521 ;; gets raised and steals focus if you've switched away from 525 ;; steal focus if you switch away from Emacs in the meantime.
522 ;; Emacs in the meantime. 526 (let ((frame speedbar-frame))
523 (make-frame-invisible speedbar-frame) 527 (cl-assert (not (eq speedbar-frame (selected-frame))))
524 (select-frame (setq speedbar-frame (previous-frame))) 528 (select-frame (setq speedbar-frame (selected-frame)))
529 (delete-frame frame))
530 ;; Allow deleting (our) `speedbar-frame' with the mouse.
531 (with-current-buffer speedbar-buffer
532 (kill-local-variable 'dframe-delete-frame-function)
533 (setq dframe-delete-frame-function
534 #'erc-speedbar--handle-delete-frame)))
535 (with-selected-frame speedbar-frame
525 (erc-speedbar--emulate-sidebar-set-window-preserve-size) 536 (erc-speedbar--emulate-sidebar-set-window-preserve-size)
526 (erc-speedbar-toggle-nicknames-window-lock -1)))) 537 (erc-speedbar-toggle-nicknames-window-lock -1))
527 (cl-assert (not (cdr (erc-speedbar--get-timers))) t)) 538 (cl-assert (null (cdr (erc-speedbar--get-timers))))
528 539 (with-current-buffer speedbar-buffer
529(defun erc-speedbar--ensure (&optional force) 540 (setq speedbar-update-flag t)
530 (when (or (erc-server-buffer) force) 541 (speedbar-set-mode-line-format)))))
531 (when erc-track-mode
532 (cl-pushnew '(derived-mode . speedbar-mode)
533 erc-track--switch-fallback-blockers :test #'equal))
534 (unless speedbar-update-flag
535 (erc-button--display-error-notice-with-keys
536 (erc-server-buffer)
537 "Module `nickbar' needs `speedbar-update-flag' to be non-nil"
538 (and (not (display-graphic-p)) " in text terminals")
539 ". Setting to t for the current Emacs session."
540 " Customize it permanently to avoid this message.")
541 (setq speedbar-update-flag t))
542 (erc-speedbar--toggle-nicknames-sidebar +1)
543 (with-current-buffer speedbar-buffer
544 (setq speedbar-update-flag t)
545 (speedbar-set-mode-line-format))))
546 542
547(defvar erc-speedbar--shutting-down-p nil) 543(defvar erc-speedbar--force-update-interval-secs 5
548(defvar erc-speedbar--force-update-interval-secs 5 "Speedbar update period.") 544 "Speedbar update period.")
549 545
550(defvar-local erc-speedbar--last-ran nil 546(defvar-local erc-speedbar--last-ran nil
551 "When non-nil, a lisp timestamp updated when the speedbar timer runs.") 547 "When non-nil, a lisp timestamp updated when the speedbar timer runs.")
552 548
553(defun erc-speedbar--run-timer-on-post-insert () 549(defun erc-speedbar--prod-dframe-timer (&rest _)
554 "Refresh speedbar if idle for `erc-speedbar--force-update-interval-secs'." 550 "Refresh speedbar if dormant for `erc-speedbar--force-update-interval-secs'."
555 (when speedbar-buffer 551 (when (buffer-live-p speedbar-buffer)
556 (with-current-buffer speedbar-buffer 552 (with-current-buffer speedbar-buffer
557 (when-let 553 (when
558 ((dframe-timer) 554 (and dframe-timer
559 ((erc--check-msg-prop 'erc--cmd 'PRIVMSG)) 555 (or (null erc-speedbar--last-ran)
560 (interval erc-speedbar--force-update-interval-secs) 556 (time-less-p erc-speedbar--last-ran
561 ((or (null erc-speedbar--last-ran) 557 (time-subtract
562 (time-less-p erc-speedbar--last-ran 558 (current-time)
563 (time-subtract (current-time) interval))))) 559 erc-speedbar--force-update-interval-secs))))
564 (run-at-time 0 nil #'dframe-timer-fn))))) 560 (run-at-time 0 nil #'dframe-timer-fn))))
561 nil)
565 562
566(defun erc-speedbar--reset-last-ran-on-timer () 563(defun erc-speedbar--reset-last-ran-on-timer ()
567 "Reset `erc-speedbar--last-ran'." 564 "Reset `erc-speedbar--last-ran'."
@@ -574,42 +571,47 @@ The INDENT level is ignored."
574 "Show nicknames for current target buffer in a side window. 571 "Show nicknames for current target buffer in a side window.
575When enabling, create a speedbar session if one doesn't exist and 572When enabling, create a speedbar session if one doesn't exist and
576show its buffer in an `erc-status-sidebar' window instead of a 573show its buffer in an `erc-status-sidebar' window instead of a
577separate frame. When disabling, close the window or, with a 574separate frame. If ERC doesn't yet have any live connections,
578negative prefix arg, destroy the session. 575defer activation until such time. This means the variable
576`erc-nickbar-mode' may be t even though no actual speedbar yet
577exists. When disabling, destroy the speedbar session.
579 578
580For controlling whether the speedbar window is selectable with 579For controlling whether the speedbar window is selectable with
581`other-window', see `erc-nickbar-toggle-nicknames-window-lock'. 580`other-window', see `erc-nickbar-toggle-nicknames-window-lock'."
582Note that during initialization, this module may produce unwanted
583side effects, like the raising of frames or the stealing of input
584focus. If you witness such a thing and can reproduce it, please
585file a bug report with \\[erc-bug]."
586 ((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure) 581 ((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
587 (add-hook 'erc-insert-post-hook #'erc-speedbar--run-timer-on-post-insert)
588 (add-hook 'speedbar-timer-hook #'erc-speedbar--reset-last-ran-on-timer) 582 (add-hook 'speedbar-timer-hook #'erc-speedbar--reset-last-ran-on-timer)
583 (add-hook 'erc-insert-post-hook #'erc-speedbar--prod-dframe-timer)
584 (add-hook 'erc-server-PONG-functions #'erc-speedbar--prod-dframe-timer)
589 (erc-speedbar--ensure) 585 (erc-speedbar--ensure)
590 (unless (or erc--updating-modules-p 586 (unless (or erc--updating-modules-p
591 (and-let* ((speedbar-buffer) 587 (and speedbar-buffer
592 (win (get-buffer-window speedbar-buffer 'all-frames)) 588 (eq speedbar-frame
593 ((eq speedbar-frame (window-frame win)))))) 589 (window-frame (get-buffer-window speedbar-buffer t)))))
594 (when-let ((buf (or (and (derived-mode-p 'erc-mode) (current-buffer)) 590 (when-let ((buf (or (and (derived-mode-p 'erc-mode) (current-buffer))
595 (car (erc-buffer-filter #'erc--server-buffer-p))))) 591 (car (erc-buffer-filter #'erc--server-buffer-p)))))
596 (with-current-buffer buf 592 (with-current-buffer buf
597 (erc-speedbar--ensure 'force))))) 593 (erc-speedbar--ensure 'forcep)))))
598 ((remove-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure) 594 ((remove-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
599 (remove-hook 'erc-insert-post-hook #'erc-speedbar--run-timer-on-post-insert)
600 (remove-hook 'speedbar-timer-hook #'erc-speedbar--reset-last-ran-on-timer) 595 (remove-hook 'speedbar-timer-hook #'erc-speedbar--reset-last-ran-on-timer)
596 (remove-hook 'erc-insert-post-hook #'erc-speedbar--prod-dframe-timer)
597 (remove-hook 'erc-server-PONG-functions #'erc-speedbar--prod-dframe-timer)
601 (when erc-track-mode 598 (when erc-track-mode
602 (setq erc-track--switch-fallback-blockers 599 (setq erc-track--switch-fallback-blockers
603 (remove '(derived-mode . speedbar-mode) 600 (remove '(derived-mode . speedbar-mode)
604 erc-track--switch-fallback-blockers))) 601 erc-track--switch-fallback-blockers)))
605 (erc-speedbar--toggle-nicknames-sidebar -1) 602 (cl-assert speedbar-buffer)
606 (when-let (((not erc-speedbar--shutting-down-p)) 603 ;; Close associated windows and stop updating but leave timer.
607 (arg erc--module-toggle-prefix-arg) 604 (dolist (window (get-buffer-window-list speedbar-buffer nil t))
608 ((numberp arg)) 605 (unless (frame-root-window-p window)
609 ((< arg 0))) 606 (when erc-speedbar--hidden-speedbar-frame
610 (with-current-buffer speedbar-buffer 607 (cl-assert (not (eq (window-frame window)
611 (dframe-close-frame) 608 erc-speedbar--hidden-speedbar-frame))))
612 (setq erc-speedbar--hidden-speedbar-frame nil))))) 609 (delete-window window)))
610 (with-current-buffer speedbar-buffer
611 (setq speedbar-update-flag nil)
612 (speedbar-set-mode-line-format)
613 (unless (eq erc--module-toggle-prefix-arg most-negative-fixnum)
614 (dframe-close-frame)))))
613 615
614(defun erc-speedbar--get-timers () 616(defun erc-speedbar--get-timers ()
615 (cl-remove #'dframe-timer-fn timer-idle-list 617 (cl-remove #'dframe-timer-fn timer-idle-list
@@ -621,21 +623,18 @@ file a bug report with \\[erc-bug]."
621 (cl-assert (eq speedbar-buffer (current-buffer)))) 623 (cl-assert (eq speedbar-buffer (current-buffer))))
622 (when (and erc-speedbar--hidden-speedbar-frame (numberp arg) (< arg 0)) 624 (when (and erc-speedbar--hidden-speedbar-frame (numberp arg) (< arg 0))
623 (when erc-nickbar-mode 625 (when erc-nickbar-mode
624 (let ((erc-speedbar--shutting-down-p t)) 626 (erc-nickbar-mode most-negative-fixnum))
625 (erc-nickbar-mode -1)))
626 (setq speedbar-frame erc-speedbar--hidden-speedbar-frame 627 (setq speedbar-frame erc-speedbar--hidden-speedbar-frame
627 erc-speedbar--hidden-speedbar-frame nil) 628 erc-speedbar--hidden-speedbar-frame nil)
628 ;; It's unknown whether leaving the frame invisible interferes
629 ;; with the upstream teardown sequence.
630 (when (display-graphic-p)
631 (make-frame-visible speedbar-frame))
632 (speedbar-frame-mode arg) ; -1 629 (speedbar-frame-mode arg) ; -1
633 ;; As of Emacs 29, `dframe-set-timer' can't remove `dframe-timer'. 630 ;; As of Emacs 29, `dframe-set-timer' can't remove `dframe-timer'.
634 (cl-assert (= 1 (length (erc-speedbar--get-timers))) t) 631 (cl-assert (= 1 (length (erc-speedbar--get-timers))) t)
635 (cancel-function-timers #'dframe-timer-fn) 632 (cancel-function-timers #'dframe-timer-fn)
636 ;; `dframe-close-frame' kills the buffer but no function in 633 ;; `dframe-close-frame' kills the buffer but no function in
637 ;; erc-speedbar.el resets this to nil. 634 ;; erc-speedbar.el resets this to nil.
638 (setq speedbar-buffer nil))) 635 (setq erc-speedbar--hidden-speedbar-frame nil
636 speedbar-buffer nil
637 speedbar-frame nil)))
639 638
640(defun erc-speedbar-toggle-nicknames-window-lock (arg) 639(defun erc-speedbar-toggle-nicknames-window-lock (arg)
641 "Toggle whether nicknames window is selectable with \\[other-window]. 640 "Toggle whether nicknames window is selectable with \\[other-window].
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el b/test/lisp/erc/erc-scenarios-status-sidebar.el
index 2523ff9ee46..4cec00e2312 100644
--- a/test/lisp/erc/erc-scenarios-status-sidebar.el
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -98,12 +98,14 @@
98(defvar erc-nickbar-mode) 98(defvar erc-nickbar-mode)
99(defvar speedbar-buffer) 99(defvar speedbar-buffer)
100 100
101;; FIXME move to own file because it takes 20+ seconds, uncompiled.
101(ert-deftest erc-scenarios-status-sidebar--nickbar () 102(ert-deftest erc-scenarios-status-sidebar--nickbar ()
102 :tags `(:expensive-test :unstable ,@(and (getenv "ERC_TESTS_GRAPHICAL") 103 :tags `(:expensive-test :unstable ,@(and (getenv "ERC_TESTS_GRAPHICAL")
103 '(:erc--graphical))) 104 '(:erc--graphical)))
104 (when noninteractive (ert-skip "Interactive only")) 105 (when (and noninteractive (= emacs-major-version 27))
106 (ert-skip "Hangs on Emacs 27, asking for input"))
105 107
106 (erc-scenarios-common-with-cleanup 108 (erc-scenarios-common-with-noninteractive-in-term
107 ((erc-scenarios-common-dialog "base/gapless-connect") 109 ((erc-scenarios-common-dialog "base/gapless-connect")
108 (erc-server-flood-penalty 0.1) 110 (erc-server-flood-penalty 0.1)
109 (erc-server-flood-penalty erc-server-flood-penalty) 111 (erc-server-flood-penalty erc-server-flood-penalty)
@@ -156,14 +158,14 @@
156 ;; etc. for testing commands that call those same functions. 158 ;; etc. for testing commands that call those same functions.
157 (call-interactively #'erc-nickbar-mode) 159 (call-interactively #'erc-nickbar-mode)
158 (should-not erc-nickbar-mode) 160 (should-not erc-nickbar-mode)
159 (should-not (and speedbar-buffer 161 (should-not speedbar-buffer)
160 (get-buffer-window speedbar-buffer))) 162 (should-not (get-buffer " SPEEDBAR"))
161 (should speedbar-buffer)
162 163
163 (erc-nickbar-mode +1) 164 (erc-nickbar-mode +1)
164 (should (and speedbar-buffer 165 (should (and speedbar-buffer (get-buffer-window speedbar-buffer)))
165 (get-buffer-window speedbar-buffer))) 166 (should (eq speedbar-buffer (get-buffer " SPEEDBAR")))
166 (should (get-buffer " SPEEDBAR")) 167 (should (get-buffer " SPEEDBAR"))
168
167 (erc-nickbar-mode -1) 169 (erc-nickbar-mode -1)
168 (should-not (get-buffer " SPEEDBAR")) 170 (should-not (get-buffer " SPEEDBAR"))
169 (should-not erc-nickbar-mode) 171 (should-not erc-nickbar-mode)