Linux下折腾emacs-rime

把函数 posframe-hide-all 重写成直接 error ,然后看异常栈

debug-on-entry posframe-hide 的时候会出现,但是并不是每次 posframe 消失就出现。 这个像是我打空格,或者回车时候正常的 posframe-hide。

Debugger entered--entering a function:
* posframe-hide(" *rime-posframe*")
  (if (string-blank-p content) (posframe-hide rime-posframe-buffer) (apply #'posframe-show rime-posframe-buffer :string content rime-posframe-properties))
  (if (and (featurep 'posframe) (display-graphic-p)) (if (string-blank-p content) (posframe-hide rime-posframe-buffer) (apply #'posframe-show rime-posframe-buffer :string content rime-posframe-properties)) (rime--popup-display-content content))
  rime--posframe-display-content("")
  (cond ((eql rime-show-candidate 'minibuffer) (rime--minibuffer-display-content content)) ((eql rime-show-candidate 'message) (message content)) ((eql rime-show-candidate 'popup) (rime--popup-display-content content)) ((eql rime-show-candidate 'posframe) (rime--posframe-display-content content)) (t (progn)))
  (if (minibufferp) (rime--minibuffer-message content) (cond ((eql rime-show-candidate 'minibuffer) (rime--minibuffer-display-content content)) ((eql rime-show-candidate 'message) (message content)) ((eql rime-show-candidate 'popup) (rime--popup-display-content content)) ((eql rime-show-candidate 'posframe) (rime--posframe-display-content content)) (t (progn))))
  rime--show-content("")
  rime--show-candidate()
  rime--redisplay()
  (cond ((not handled) (list key)) (commit (rime--clear-overlay) (mapcar 'identity commit)) (t (if (and (rime--should-inline-ascii-p) commit-text-preview (not (rime--ascii-mode-p))) (progn (rime--inline-ascii))) (rime--redisplay)))
  (unwind-protect (cond ((not handled) (list key)) (commit (rime--clear-overlay) (mapcar 'identity commit)) (t (if (and (rime--should-inline-ascii-p) commit-text-preview (not (rime--ascii-mode-p))) (progn (rime--inline-ascii))) (rime--redisplay))) (rime--refresh-mode-state))
  (let* ((context (rime-lib-get-context)) (commit-text-preview (alist-get 'commit-text-preview context)) (preedit (alist-get 'preedit (alist-get 'composition context))) (commit (rime-lib-get-commit))) (unwind-protect (cond ((not handled) (list key)) (commit (rime--clear-overlay) (mapcar 'identity commit)) (t (if (and (rime--should-inline-ascii-p) commit-text-preview (not (rime--ascii-mode-p))) (progn (rime--inline-ascii))) (rime--redisplay))) (rime--refresh-mode-state)))
  (progn (let* ((context (rime-lib-get-context)) (commit-text-preview (alist-get 'commit-text-preview context)) (preedit (alist-get 'preedit (alist-get 'composition context))) (commit (rime-lib-get-commit))) (unwind-protect (cond ((not handled) (list key)) (commit (rime--clear-overlay) (mapcar 'identity commit)) (t (if (and (rime--should-inline-ascii-p) commit-text-preview (not ...)) (progn (rime--inline-ascii))) (rime--redisplay))) (rime--refresh-mode-state))))
  (unwind-protect (progn (let* ((context (rime-lib-get-context)) (commit-text-preview (alist-get 'commit-text-preview context)) (preedit (alist-get 'preedit (alist-get 'composition context))) (commit (rime-lib-get-commit))) (unwind-protect (cond ((not handled) (list key)) (commit (rime--clear-overlay) (mapcar 'identity commit)) (t (if (and ... commit-text-preview ...) (progn ...)) (rime--redisplay))) (rime--refresh-mode-state)))) (if modified nil (restore-buffer-modified-p nil)))
  (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (let* ((context (rime-lib-get-context)) (commit-text-preview (alist-get 'commit-text-preview context)) (preedit (alist-get 'preedit (alist-get ... context))) (commit (rime-lib-get-commit))) (unwind-protect (cond ((not handled) (list key)) (commit (rime--clear-overlay) (mapcar ... commit)) (t (if ... ...) (rime--redisplay))) (rime--refresh-mode-state)))) (if modified nil (restore-buffer-modified-p nil))))
  (let ((handled (rime-lib-process-key key 0))) (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (let* ((context (rime-lib-get-context)) (commit-text-preview (alist-get ... context)) (preedit (alist-get ... ...)) (commit (rime-lib-get-commit))) (unwind-protect (cond (... ...) (commit ... ...) (t ... ...)) (rime--refresh-mode-state)))) (if modified nil (restore-buffer-modified-p nil)))))
  (if (and (not (rime--should-enable-p)) (not (rime--has-composition (rime-lib-get-context)))) (list key) (let ((handled (rime-lib-process-key key 0))) (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (let* ((context ...) (commit-text-preview ...) (preedit ...) (commit ...)) (unwind-protect (cond ... ... ...) (rime--refresh-mode-state)))) (if modified nil (restore-buffer-modified-p nil))))))
  (progn (if (and (not (rime--should-enable-p)) (not (rime--has-composition (rime-lib-get-context)))) (list key) (let ((handled (rime-lib-process-key key 0))) (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (let* (... ... ... ...) (unwind-protect ... ...))) (if modified nil (restore-buffer-modified-p nil)))))))
  (if (rime--rime-lib-module-ready-p) (progn (if (and (not (rime--should-enable-p)) (not (rime--has-composition (rime-lib-get-context)))) (list key) (let ((handled (rime-lib-process-key key 0))) (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (let* ... ...)) (if modified nil (restore-buffer-modified-p nil))))))))
  rime-input-method(105)

是的,不同的buffer都是这样的情况。 不用 posframe 就没有这个问题, popupminibuffer 都正常。

我是输入 s 的时候异常,而且输入后 posframe 反应很慢。

你是说posframe出来以后反应就很慢吗?如果 posframe 始终很慢的话,应该和 emacs 没有用 gtk 有关系。至于 hide 的话,就不太清楚了。

这个是什么意思?难道GUI Emacs不是用的GTK么?

我用二分法找到问题了。。。 但是还不知道该怎么改,要呼叫一下 @seagle0128 一起来研究下。

开了 doom-modeline 就不正常,关掉 doom-modeline 就正常了。@stardiviner 看你是不是也是这个问题。试试 doom-mode-line-mode 把那个 modeline 关掉看看是不是好了。

child frame中禁用modeline了吗?

我这边确认了,确实关掉 doom-modeline 就好了。

没看到关于 child-frame 特别的设置,有没有示例的代码,我可以测试下是不是 child-frame 打开 modeline 的影响。

就是在child-frame的buffer里面设置 (setq-local mode-line-format nil)

我加上了代码

(with-current-buffer rime-posframe-buffer
    (setq-local mode-line-format nil))

没什么改变。我去那个rime 的隐藏 buffer 里面去看,确认了 mode-line-format 的值已经是 nil 了。

是不是 doom-modeline 对焦点有特殊处理?这个可能影响 posframe

posframe 有一个hook 设置

(add-hook 'focus-in-hook #'posframe--redirect-posframe-focus)

pyim 的 posframe 使用就没有问题,就是这个 emacs-rime 使用 posframe 配合 doom-modeline 有问题。

doom-modeline 里面确实有关于焦点处理的 hook.

(with-no-warnings
  (if (boundp 'after-focus-change-function)
      (progn
        (defun doom-modeline-refresh-frame ()
          (setq doom-modeline-current-window nil)
          (cl-loop for frame in (frame-list)
                   if (eq (frame-focus-state frame) t)
                   return (setq doom-modeline-current-window
                                (doom-modeline--get-current-window frame)))
          (force-mode-line-update))
        (add-function :after after-focus-change-function #'doom-modeline-refresh-frame))
    (progn
      (add-hook 'focus-in-hook #'doom-modeline-set-selected-window)
      (add-hook 'focus-out-hook #'doom-modeline-unset-selected-window))))

以及

(with-no-warnings
  (if (boundp 'after-focus-change-function)
      (progn
        (defun doom-modeline-focus-change (&rest _)
          (if (frame-focus-state)
              (doom-modeline-focus)
            (doom-modeline-unfocus)))
        (advice-add #'handle-switch-frame :after #'doom-modeline-focus-change)
        (add-function :after after-focus-change-function #'doom-modeline-focus-change))
    (progn
      (add-hook 'focus-in-hook #'doom-modeline-focus)
      (add-hook 'focus-out-hook #'doom-modeline-unfocus))))

我把这个去掉了,还是一样的表现。

我准备去对比下 pyim 和 emacs-rime 中关于 posframe 的部分。

rime.el 里面, rime–posframe-display-content 函数,其中对 posframe-show 的调用是使用的一个 apply 方式,

 (apply #'posframe-show rime-posframe-buffer
               :string content
               rime-posframe-properties)

rime-posframe-properties 是一个 plist 形式定义的参数。我给改成

(posframe-show rime-posframe-buffer :string content)

就好了。有点神奇。

直接调用和 apply 感觉不应该有这样的差异。。。 另外我想知道,直接 posframe-show 有没有办法将这些相当于 face 定义的外观作为变量传进去。

已放弃doom了,:joy:

我也在逐渐把 doom 的一些默认配置关掉,改成自己的了。不过就这个问题来说,不是 doom 的问题。我也只是找到了互相有冲突的包,没找到根本问题。

你以做个 profiling,看看到底是哪个调用占用 CPU。

是不是posframe的某个属性有影响