Изменение внешнего вида окна Emacs, когда оно теряет фокус

Когда я программирую, я использую два экрана с Emacs на обоих с двумя разделенными буферами в каждом окне, что в сумме дает 4 файла с открытым исходным кодом на экране одновременно.

Я переключаюсь между буферами с C-x b и между Windows с Alt-TAB. Я меняю внешний вид буферов, когда переключаюсь между ними, определяя разные грани для mode-line и mode-line-inactive. Но как мне деактивировать буфер, когда я полностью переключаюсь из окна Emacs в другое окно Emacs через Alt-TAB?

Вероятно, также актуально то, что я использую Emacs 23.2.1 в Ubuntu 11.04 с Gnome 2.32.1.

PS: вопрос Как автоматически сохранять файлы при потере фокуса в Emacs преследует другую цель, но с тем же исходным событием "окно теряет фокус".


person Alan Turing    schedule 01.09.2011    source источник
comment
Прежде всего, чтобы понять термины: буфер содержит файл, окно отображает буфер, а окно отображается рамкой. С помощью Alt-Tab вы переключаете кадры. Тем не менее: насколько я могу судить, вы не можете отменить выбор окна, чтобы получить свое поведение бесплатно.   -  person Michael Markert    schedule 01.09.2011
comment
Спасибо за это разъяснение. Я немного неправильно употреблял термины. Полагаю, я использовал окно для обозначения окна или рамки.   -  person Alan Turing    schedule 01.09.2011


Ответы (4)


Это может зависеть от вашего оконного менеджера и того, как он управляет несколькими окнами или фреймами, говоря языком emacs. Приведенный ниже код работает как чемпион в fvwm, но не всегда в gnome.

Я сопоставляю нажатие клавиши C-o для перехода между кадрами, это помогает, когда вы хотите перейти к другому кадру, но альтернативная вкладка проведет вас через множество лишних приложений по пути.

Если вы запускаете один экземпляр 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
  )

Вы также можете попробовать добавить несколько советов, как поднять и опустить рамку, не пробовали, но попробовать стоит.

person Paul Rubel    schedule 01.09.2011
comment
Кроме того, FrameMove (emacswiki.org/emacs/FrameMove) сочетается с WindMove (встроенным) для создания удивительно интуитивно понятного способа навигации между окнами / фреймами в Emacs. - person phils; 02.09.2011

Мне очень понравился ответ @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)))
person raskolnikov    schedule 05.06.2015

В Emacs 24.4 и новее вы можете использовать focus-in-hook и focus-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)
person legoscia    schedule 21.02.2014

Я не знаю, можно ли это сделать только с Emacs, но возможная альтернатива - запустить wmctrl в сценарий оболочки, который периодически проверяет, какое окно находится в фокусе, и, если есть изменения, он сообщает Emacs через emacsclient, который может отправлять код Lisp в работающий Emacs для оценки:

_1 _-- eval 'Скажите Emacs оценить некоторый код Emacs Lisp вместо посещения некоторых файлов. Когда задана эта опция, аргументы emacsclient интерпретируются как список выражений для оценки, не как список файлов для посещения.

person Tom    schedule 01.09.2011
comment
Интересное решение, но я бы хотел, чтобы событие focus немедленно обновляло внешний вид окна, что потребовало бы wmctrl, чтобы проверять, какие окна имеют фокус с чрезвычайно высокой скоростью. Интересно, смогу ли я вместо этого поймать события смены фокуса. - person Alan Turing; 01.09.2011
comment
Сценарий оболочки был лишь простым примером. Вероятно, есть способ подписаться на события изменения окна в X, поэтому вы могли бы написать отдельную небольшую программу, которая подписывается на эти события и уведомляет emacs, когда она вызывается X. - person Tom; 01.09.2011