3

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 C-x 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".

Community
  • 1
  • 1
Alan Turing
  • 12,223
  • 16
  • 74
  • 116
  • 1
    First to get the terms straight: A buffer contains a file, a window displays a buffer and a window is displayed by a frame. With Alt-Tab you switch frames. That said: As far as I can tell you can't deselect a window to get your behavior for free. – Michael Markert Sep 01 '11 at 14:13
  • Thanks for that clarification. I was slightly misusing terms. I suppose I was using "window" to mean either window or frame. – Alan Turing Sep 01 '11 at 14:15

4 Answers4

3

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, C-o, 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.

Paul Rubel
  • 26,632
  • 7
  • 60
  • 80
  • 1
    Also, FrameMove ( http://www.emacswiki.org/emacs/FrameMove ) combines with WindMove (built-in) to create a wonderfully-intuitive way of navigating between windows/frames in Emacs. – phils Sep 01 '11 at 21:49
2

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)
legoscia
  • 39,593
  • 22
  • 116
  • 167
2

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

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.

Tom
  • 7,515
  • 7
  • 38
  • 54
  • Interesting solution but I would like the focus event to update the window appearance immediately which would require `wmctrl` to check which windows has the focus at an overwhelmingly high rate. I wonder if I can instead catch "change of focus" events. – Alan Turing Sep 01 '11 at 14:13
  • The shell script was only a simple example. There is probably a way to subscribe to window change events in X, so you could write a separate small program which subscribes to these events and notifies emacs when it's called back by X. – Tom Sep 01 '11 at 14:35