简体   繁体   中英

Change Emacs window appearance when it loses focus

When I program I use two screens with Emacs on both with two buffers split in each window totaling 4 open source files on screen at any one time.

I switch between buffers with Cx b and between Windows with Alt-TAB . I change the appearance of buffers when I switch between them by defining different faces for mode-line and mode-line-inactive . But how do I inactivate a buffer when I switch from the Emacs window completely to another Emacs window via Alt-TAB ?

It's probably also relevant that I'm using Emacs 23.2.1 on Ubuntu 11.04 with Gnome 2.32.1.

PS: The question How to automatically save files on lose focus in Emacs is after a different goal but with the same original event of "window losing focus".

It may depend on your window manager and how it manages multiple windows, or frames, in emacs parlance. The code below works like a champ in fvwm but not always in gnome.

I map a keystroke, Co, to go between frames, this helps when you want to go to the other frame but an alt-tab would take you through a number of superfluous apps on the way.

If you're running a single instance of emacs with two frames you could use something like the following:

(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
  )

You could also try adding some advice to raise-frame and lower-frame haven't tried it but it's worth a try.

In Emacs 24.4 and later, you can use focus-in-hook and focus-out-hook . This piece of code seems to work, such that the active window of an inactive frame has the same colour as an inactive window:

(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)

I really liked @logoscia answer, which allowed me to do this more generic version. It uses the mode-line-inactive face when no focus.

(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)))

I don't know if it can be done only with Emacs, but a possible alternative is running wmctrl in a shell script which perodically checks which window has the focus and if there is a change then it lets Emacs know via emacsclient which can send lisp code to a running Emacs for evaluation:

-e' --eval' Tell Emacs to evaluate some Emacs Lisp code, instead of visiting some files. When this option is given, the arguments to `emacsclient' are interpreted as a list of expressions to evaluate, not as a list of files to visit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM