daemon 模式下awesome-tray只有不到一半长度,无法自动调整

@manateelazycat awesome-tray 很好用,但是在daemon 模式下awesome-tray只有不到一半长度。

安装

brew install emacs-plus@28 --with-xwidgets

版本 :

GNU Emacs 28.0.50 (build 1, x86_64-apple-darwin20.3.0, NS appkit-2022.30 Version 11.2.2 (Build 20D80)) of 2021-02-28

最小配置: init-mini.el

    ;;; init-mini.el --- mini config for test -*- lexical-binding: t no-byte-compile: t -*-
    ;;; Commentary:
    ;;; Code:

    ;; appearence
    (column-number-mode)
    (line-number-mode)
    (tool-bar-mode -1)
    (scroll-bar-mode -1)
    (tooltip-mode -1)

    ;; ---------------------- Load const, env and path ------------------------------
    ;; add init-*.el to load-path
    (add-to-list 'load-path (expand-file-name "core/" user-emacs-directory))

    ;; const viriable
    (require 'init-const)

    ;; add submodules to load-path
    (defun add-subdirs-to-load-path (dir)
      "Recursive add `DIR` to `load-path'."
      (let ((default-directory (file-name-as-directory dir)))
        (add-to-list 'load-path dir)
        (normal-top-level-add-subdirs-to-load-path)))
    (add-subdirs-to-load-path (expand-file-name "module/" user-emacs-directory))

    ;; ---------------------- Test module -----------------------------

    (require 'awesome-tray)
    (awesome-tray-mode 1)

    (provide 'init-mini)
    ;;; init-mini.el ends here

复现:

不使用daemon,一切正常,并且 make-frame 新建的frame 也可以自动调整


emacs -Q --load init-mini.el`

# 使用daemon,则通过`emacsclient --create-frame`创建的frame,
# tray的长度只到屏幕的一半,无法自动调整。
emacs -Q --daemon --load init-mini.el
emacsclient -n -q -a ''  -c init-mini.el

因为awesome-tray要根据当前的 frame 计算宽度来动态调整右边的padding值。 主要的函数是 awesome-tray-get-frame-width , 我猜测是Daemon没有Frame的原因。

我建议你对 awesome-tray-get-frame-width 函数进行 advice.

我看了下那个方程,

(defun awesome-tray-get-frame-width ()
  "Only calculating a main Frame width, to avoid wrong width when new frame, such as `snails'."
  (with-selected-frame (car (last (frame-list)))
    (frame-width)))

我发现我是错的,即便不用daemon模式,新建的第二个frame的tray位置也取决于第一个frame的frame width,后续新建的frame tray都和第一个frame width宽度强相关。第一个frame resize了,后续的tray 位置都会跟着变,以至于不停的偏移和闪烁。

我看注释的意思,用(last (frame-list))你是想规避临时新建的类似 posframe的窗口影响,但是这就把后续的frame tray都绑在第一个 frame width上了。

# 不使用daemon,第一个frame一切正常,
# 后续的 tray 都和第一个 frame width 绑定,不是独立的。
emacs -Q --load init-mini.el

至于daemon,那是另外一个问题。

@manateelazycat ,你估计从来不用第二个Main frame,所以一个的时候没有任何问题。。

是啊,我只用一个,但是多个的时候也没想好怎么解决。

@manateelazycat , 获取 awesome-tray 当前 frame 的 width,这样会不会好一点?

第一,尽可能排除child-frame的影响,类似snail,acm应该都是可以排除的吧

第二, 永远根据当前的frame进行计算,尤其使用多个frame的时候

第三, 根据 window-width 而不是 frame-width,这样就可以提前排除一些 fringe之类的影响,需要设置padding 的概率会降低很多

(defun mini-echo-minibuffer-width ()
"Return current minibuffer window width."
(with-selected-frame (or (frame-parent (window-frame))
                         (window-frame))
  (window-width (minibuffer-window))))
  1. snails, acm 都是可以排除的, 现在有影响吗? 有影响可以发补丁
  2. 默认加了 with-selected-frame 就是选中的 frame
  3. window-width 分屏的时候会出问题吧

能说一下哪些场景有问题吗? 我不太明白你说的意思

你说分屏是指什么意思? 一个frame永远只有一个minibuffer-window啊,类似于C-x 3这样应该不会影响吧

没有,没有使用上的问题,我在写一个简单的 mini-modeline 来练习 elisp,在实现的时候想到的新方法。

(window-width (minibuffer-window)) 和 (frame-width) 这两个在实践中会有差别吗?

如果有差别, 确实可以改进下。

会有的, 比如我的 frame-width 就是180,但是window-width就是178,应该是排除了fringe或者margin width的差别,这样的话手动设置padding的概率会降低很多我觉得。

我一会试一下, 感谢提示

我试了一下, (window-width (minibuffer-window)) 确实比 frame-width 的方法, 确实能够更准确的计算 minibuffer 的宽度, 已经推送补丁了 `window-width' can calculate the width of the minibuffer more accurat… · manateelazycat/awesome-tray@60eae80 · GitHub

感谢指教。

@manateelazycat

我发现其实不用单独为 minibuf-0 插入 text, 可以类似于 echo-area-0,echo-area-1 设置 overlay。 每一次 minibuffer-inactive-mode 的确会重置overlay,但前提是 minibuf-0 内容为空。

只要我们在 mode 初始化的时候,在 minibuf-0插入一个空格,这样在 minibuf-0设置的 overlay 就不会失效成为 overlay-in-no-buffer。至于 minibuf-0 自己好像也从来不用来展示内容,插入一个空格应该问题不大。

大佬,可以发一个补丁吗?感谢

我晚些时候来提 pr