当Emacs失去焦点时改变窗口外观

3
当我编程时,我使用两个屏幕,在每个窗口上都有两个缓冲区,总共在屏幕上同时打开4个源文件。我使用“C-x b”在不同的缓冲区之间切换,在不同的窗口之间使用“Alt-TAB”进行切换。当我切换缓冲区时,通过定义不同的“mode-line”和“mode-line-inactive”面来改变缓冲区的外观。但是,当我通过“Alt-TAB”完全从Emacs窗口切换到另一个Emacs窗口时,如何使缓冲区无效?
顺便说一下,我正在Ubuntu 11.04上使用Emacs 23.2.1和Gnome 2.32.1。
PS:问题如何在Emacs失去焦点时自动保存文件目标不同,但具有相同的原始事件“窗口失去焦点”。

1
首先澄清一下术语:缓冲区包含文件,窗口显示缓冲区,而窗口由框架显示。使用Alt-Tab可以切换框架。话虽如此:据我所知,您无法取消选择窗口以免费获得您想要的行为。 - Michael Markert
谢谢您的澄清。我有点误用了术语。我想我是在使用“窗口”来表示窗口或框架。 - Alan Turing
4个回答

3

这可能取决于您的窗口管理器以及它如何在emacs控制下管理多个窗口或框架。下面的代码在fvwm中表现良好,但在gnome中不一定。

我将一个按键绑定为C-o,用于在框架之间进行切换,这在您想要转到另一个框架时非常有帮助,因为alt-tab会经过许多不必要的应用程序。

如果您正在运行具有两个框架的单个emacs实例,则可以使用以下内容:

(defun pgr-previous-frame ()
  "go to the previous frame"
  (interactive)
  (pgr-switch-frame (previous-frame)))

(defun pgr-next-frame ()
  "go to the next frame"
  (interactive)
  (pgr-switch-frame (next-frame)))

(defun pgr-switch-frame (frame)
  "go to the specified frame and raise it"
  ;; reset the frame properties here
  (select-frame frame)     
  (raise-frame frame)
  ;;change the display in some manner here
  )

你也可以尝试添加一些建议到raise-frame和lower-frame中,虽然我没有尝试过,但值得一试。


1
此外,FrameMove(http://www.emacswiki.org/emacs/FrameMove)与内置的WindMove结合使用,为在Emacs中导航窗口/框架提供了一种非常直观的方式。 - phils

2

我非常喜欢@logoscia的答案,它让我能够做出更通用的版本。当没有焦点时,它使用mode-line-inactive面。

(add-hook 'focus-out-hook
      (lambda ()
        (copy-face 'mode-line '--mode-line-backup)
        (copy-face 'mode-line-inactive 'mode-line)))
(add-hook 'focus-in-hook
      (lambda ()
        (copy-face '--mode-line-backup 'mode-line)))

2
在Emacs 24.4及更高版本中,您可以使用focus-in-hookfocus-out-hook。下面这段代码似乎可以起作用,使得非活动框架的活动窗口与非活动窗口颜色相同:
(defvar my-mode-line-active-background "gray75")
(defvar my-mode-line-inactive-background "gray40")

(defun my-unhighlight-mode-line ()
  (set-face-attribute 'mode-line nil
                      :background my-mode-line-inactive-background))

(add-hook 'focus-out-hook 'my-unhighlight-mode-line)

(defun my-highlight-mode-line ()
  (set-face-attribute 'mode-line nil
                      :background my-mode-line-active-background))

(add-hook 'focus-in-hook 'my-highlight-mode-line)

0

我不确定是否只能使用Emacs来完成,但一个可能的替代方案是在shell脚本中运行wmctrl,该脚本定期检查哪个窗口具有焦点,如果有变化,则通过emacsclient让Emacs知道,后者可以将lisp代码发送到正在运行的Emacs进行评估:

-e'--eval' 告诉Emacs评估一些Emacs Lisp代码,而不是访问某些文件。当给出此选项时,`emacsclient'的参数被解释为要评估的表达式列表,而不是要访问的文件列表。


有趣的解决方案,但我希望焦点事件能立即更新窗口外观,这需要使用wmctrl以极高的频率检查哪个窗口具有焦点。我想知道是否可以捕获“焦点变化”事件。 - Alan Turing
这个shell脚本只是一个简单的例子。可能有一种方法可以订阅X中的窗口更改事件,因此您可以编写一个单独的小程序来订阅这些事件,并在被X回调时通知emacs。 - Tom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接