Spec-Zone.ru › Elisp

Фокус ввода

В любой момент времени один кадр в Emacs является выбранным кадром. Выбранное окно (см. Выбор окон) всегда находится в выбранном кадре.

Когда Emacs отображает свои кадры на нескольких терминалах (см. Несколько терминалов), у каждого терминала есть собственный выбранный кадр. Но только один из них является тем самым выбранным кадром: это кадр, принадлежащий терминалу, с которого поступил последний ввод. То есть, когда Emacs выполняет команду, поступившую с определённого терминала, выбранным становится кадр этого терминала. Поскольку в каждый момент времени Emacs выполняет только одну команду, ему нужно учитывать только один выбранный кадр; именно этот кадр в данном руководстве называется выбранным кадром. Дисплей, на котором отображается выбранный кадр, называется дисплеем выбранного кадра.

Функция: selected-frame

Эта функция возвращает выбранный кадр.

Некоторые оконные системы и оконные менеджеры направляют ввод с клавиатуры в оконный объект, над которым находится указатель мыши; другие требуют явных щелчков или команд, чтобы переместить фокус на различные оконные объекты. В любом случае Emacs автоматически отслеживает, какие кадры находятся в фокусе. Чтобы явно переключиться на другой кадр из функции Lisp, вызовите select-frame-set-input-focus.

Множественное число «кадры» в предыдущем абзаце использовано намеренно: хотя у самого Emacs есть только один выбранный кадр, кадры Emacs могут находиться на многих разных терминалах (напомним, что подключение к оконной системе считается терминалом), и у каждого терминала своё представление о том, какой кадр находится в фокусе ввода. В X Window System, где пользовательский ввод организован в отдельные «места» ввода, каждое такое место, в свою очередь, может иметь собственный фокус ввода. Когда вы устанавливаете фокус ввода на кадр, вы устанавливаете фокус для терминала этого кадра в последнем месте, взаимодействовавшем с Emacs, но кадры на других терминалах и в других местах могут по-прежнему оставаться в фокусе.

Если фокус ввода устанавливается до того, как на указанном терминале произошло какое-либо взаимодействие с пользователем, X-сервер выбирает случайное место (обычно с наименьшим номером) и устанавливает фокус ввода там.

Программы Lisp могут временно переключать кадры, вызывая функцию select-frame. Это не меняет представление оконной системы о фокусе; вместо этого управление оконным менеджером приостанавливается до тех пор, пока оно каким-либо образом не будет восстановлено.

При использовании текстового терминала на нём в каждый момент времени может отображаться только один кадр, поэтому после вызова select-frame при следующем обновлении дисплея фактически отображается вновь выбранный кадр. Этот кадр остаётся выбранным до последующего вызова select-frame. У каждого кадра на текстовом терминале есть номер, который отображается в строке режима перед именем буфера (см. Переменные, используемые в строке режима).

Функция: select-frame-set-input-focus frame &optional norecord

Эта функция выбирает frame, поднимает его (если он оказался заслонён другими кадрами) и пытается передать ему фокус оконной системы. На текстовом терминале при следующем обновлении дисплея новый кадр отображается на всём экране терминала. Необязательный аргумент norecord имеет то же значение, что и для select-frame (см. ниже). Возвращаемое значение этой функции не имеет значения.

В идеале описанная далее функция должна переводить кадр в фокус, не поднимая его над другими кадрами. К сожалению, многие оконные системы и оконные менеджеры могут отказаться это делать.

Функция: x-focus-frame frame &optional noactivate

Эта функция передаёт frame фокус X-сервера, не обязательно поднимая его. frame nil означает, что нужно использовать выбранный кадр. В X необязательный аргумент noactivate, если он не-nil, означает, что окно оконной системы для frame не следует делать «активным»; это должно несколько настойчивее препятствовать поднятию frame над другими кадрами.

В MS-Windows аргумент noactivate не действует. Однако, если frame является дочерним кадром (см. Дочерние кадры), эта функция обычно переводит frame в фокус, не поднимая его над другими дочерними кадрами.

Если поддержка оконной системы отсутствует, эта функция ничего не делает.

Команда: select-frame frame &optional norecord

Эта функция выбирает кадр frame, временно игнорируя фокус X-сервера, если он есть. frame остаётся выбранным до тех пор, пока пользователь не выберет другой кадр или пока эта функция не будет вызвана снова. (Если вы используете оконную систему, после возврата в цикл команд ранее выбранный кадр может снова стать выбранным, поскольку у него всё ещё может быть фокус ввода оконной системы.)

Указанный frame становится выбранным кадром, а его терминал — выбранным терминалом. Затем эта функция вызывает select-window как подпрограмму, передавая ей в качестве первого аргумента окно, выбранное в frame, а в качестве второго — norecord (следовательно, если norecord не-nil, это предотвращает изменение порядка недавно выбранных окон и списка буферов). См. Выбор окон.

Эта функция возвращает frame или nil, если frame был удалён.

Как правило, никогда не следует использовать select-frame так, чтобы переключиться на другой терминал и не вернуться обратно после завершения работы.

Функция: frame-use-time &optional frame

Эта функция возвращает время использования кадра frame. frame должен быть активным кадром; по умолчанию используется выбранный кадр.

Время использования кадра — это наибольшее время использования, сообщаемое функцией window-use-time для любого окна в frame.

Функция: get-mru-frame &optional all-frames exclude-child-frames exclude-frame

Эта функция возвращает кадр с наибольшим временем использования, сообщаемым функцией frame-use-time. Она возвращает nil, если подходящих кадров не найдено; обычно это происходит, когда кадры исключены с помощью необязательных аргументов.

По умолчанию кадры подсказок и кадры только с минибуфером никогда не рассматриваются в качестве кандидатов. Если необязательный аргумент exclude-child-frames не равен nil, дочерние кадры также исключаются. Аргумент exclude-frame, если он указан, также исключает заданный им кадр. Поскольку на практике последним использованным кадром всегда является выбранный кадр, обычно имеет смысл вызывать эту функцию с аргументом exclude-frame, не равным nil и указывающим на выбранный кадр.

Необязательный аргумент all-frames задаёт, какие кадры следует рассматривать:

  • visible означает учитывать все видимые кадры на текущем терминале или на терминале exclude-frame.
  • 0 означает учитывать все видимые или свёрнутые в значок кадры на текущем терминале или на терминале exclude-frame.
  • Любое другое значение означает учитывать все кадры.
Функция: get-mru-frames &optional all-frames exclude-child-frames exclude-frame

Эта функция возвращает список кадров, отсортированных по убыванию времени использования, сообщаемого функцией frame-use-time, которое вычисляется с использованием последнего использованного окна каждого кадра.

По умолчанию кадры подсказок и кадры только с минибуфером никогда не рассматриваются в качестве кандидатов. Если необязательный аргумент exclude-child-frames не равен nil, дочерние кадры также исключаются. Аргумент exclude-frame, если он указан, также исключает заданный им кадр.

Функция может вернуть nil, что может произойти, если кадры исключены с помощью необязательных аргументов, например, если существует один кадр и exclude-frame — выбранный кадр.

Необязательный аргумент all-frames задаёт, какие кадры следует рассматривать:

  • visible означает учитывать все видимые кадры на текущем терминале или на терминале exclude-frame.
  • 0 означает учитывать все видимые или свёрнутые в значок кадры на текущем терминале или на терминале exclude-frame.
  • Любое другое значение означает учитывать все кадры.
Команда: select-frame-by-id id &optional noerror

Эта функция ищет среди открытых и неудалённых кадров кадр с идентификатором id (см. Кадры). Если кадр найден, он при необходимости восстанавливается, затем поднимается, переводится в фокус и становится выбранным. На текстовом терминале поднятие кадра приводит к тому, что он занимает весь дисплей терминала.

Эта функция возвращает выбранный кадр или сигнализирует об ошибке, если id не найден, за исключением случая, когда noerror не-nil; тогда функция возвращает nil.

Команда: undelete-frame-by-id id &optional noerror

Эта функция ищет среди неудалённых кадров кадр с идентификатором id (см. Кадры). Если кадр найден, он восстанавливается, поднимается, переводится в фокус и становится выбранным. На текстовом терминале поднятие кадра приводит к тому, что он занимает весь дисплей терминала.

Эта функция возвращает восстановленный кадр или сигнализирует об ошибке, если id не найден, за исключением случая, когда noerror не-nil; тогда функция возвращает nil.

Emacs взаимодействует с оконной системой, выбирая кадры по запросам сервера и оконного менеджера. Когда оконная система сообщает Emacs, что один из его кадров выбран, Emacs внутренне генерирует событие focus-in. Когда кадр Emacs отображается в эмуляторе текстового терминала, например xterm, поддерживающем уведомления об изменении фокуса, события focus-in и focus-out доступны даже для кадров в текстовом режиме. События фокуса обычно обрабатываются командой handle-focus-in.

Команда: handle-focus-in event

Эта функция обрабатывает события focus-in от оконных систем и терминалов, поддерживающих явные уведомления о фокусе. Она обновляет флаги фокуса отдельных кадров, которые запрашивает frame-focus-state, и вызывает after-focus-change-function. Кроме того, она генерирует событие switch-frame, чтобы переключить представление Emacs о выбранном кадре на кадр, который последним получил фокус в каком-либо терминале. Важно отметить, что переключение выбранного кадра Emacs на последний кадр, получивший фокус, не означает, что другие кадры перестают оставаться в фокусе на соответствующих терминалах. Не вызывайте эту функцию самостоятельно: вместо этого добавьте логику в after-focus-change-function.

Команда: handle-switch-frame frame

Эта функция обрабатывает событие switch-frame, которое Emacs генерирует для себя при получении уведомления о фокусе или при различных других обстоятельствах, когда событие ввода поступает в кадр, отличный от кадра предыдущего события. Не вызывайте эту функцию самостоятельно.

Функция: redirect-frame-focus frame &optional focus-frame

Эта функция перенаправляет фокус с frame на focus-frame. Это означает, что focus-frame будет получать последующие нажатия клавиш и события, предназначенные для frame. После такого события значением last-event-frame будет focus-frame. Кроме того, события switch-frame, указывающие на frame, вместо этого будут выбирать focus-frame.

Если focus-frame не указан или равен nil, существующее перенаправление для frame отменяется, и кадр снова получает собственные события.

Одно из применений перенаправления фокуса — кадры без минибуферов. Такие кадры используют минибуферы в других кадрах. При активации минибуфера в другом кадре фокус перенаправляется на этот кадр. Благодаря этому фокус оказывается на кадре минибуфера, где ему и надлежит быть, хотя указатель мыши остаётся в кадре, активировавшем минибуфер.

Выбор кадра также может изменить перенаправление фокуса. При выборе кадра bar, когда был выбран foo, все перенаправления, указывающие на foo, изменяются так, чтобы вместо этого указывать на bar. Это позволяет перенаправлению фокуса работать правильно, когда пользователь переключается с одного кадра на другой с помощью select-window.

Это означает, что кадр, фокус которого перенаправлен на него самого, обрабатывается иначе, чем кадр, фокус которого не перенаправлен. select-frame действует на первый кадр, но не на второй.

Перенаправление сохраняется до тех пор, пока для его изменения не будет вызвана функция redirect-frame-focus.

Функция: frame-focus-state &optional frame

Эта функция получает последнее известное состояние фокуса для frame. По умолчанию используется выбранный кадр.

Она возвращает nil, если известно, что кадр не находится в фокусе, t, если известно, что кадр находится в фокусе, или unknown, если Emacs не знает состояние фокуса кадра. (Последнее состояние может встречаться у кадров TTY, работающих на терминалах, не поддерживающих явные уведомления о фокусе.)

Переменная: after-focus-change-function

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

Например, вот простая функция, которая задаёт цвет фона в зависимости от того, находится кадр в фокусе или нет:

(add-function :after after-focus-change-function
              #'my-change-background)
(defun my-change-background ()
  (dolist (frame (frame-list))
    (pcase (frame-focus-state frame)
      (`t (set-face-background 'default "black" frame))
      (`nil (set-face-background 'default "#404040" frame)))))

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

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

Эта функция может вызываться в произвольном контексте, в том числе изнутри read-event, поэтому соблюдайте ту же осторожность, что и при написании фильтра процесса.

Пользовательский параметр: focus-follows-mouse

Этот параметр сообщает Emacs, передаёт ли оконный менеджер фокус и каким образом при перемещении указателя мыши в кадр. У него есть три значимых значения:

nil

Значение по умолчанию nil следует использовать, если оконный менеджер придерживается политики «фокус по щелчку», при которой нужно щёлкнуть мышью внутри кадра, чтобы тот получил фокус.

t

Значение t следует использовать, если оконный менеджер автоматически перемещает фокус вслед за указателем мыши, но кадр, получивший фокус, автоматически не поднимается и может даже оставаться заслонённым другими окнами оконной системы.

auto-raise

Значение auto-raise следует использовать, если оконный менеджер автоматически перемещает фокус вслед за указателем мыши и автоматически поднимает кадр, получивший фокус.

Если этот параметр не-nil, Emacs перемещает указатель мыши к кадру, выбранному функцией select-frame-set-input-focus. Эта функция используется рядом команд, например other-frame и pop-to-buffer.

Различие между значениями t и auto-raise не требуется для «обычных» кадров, поскольку оконный менеджер обычно сам заботится об их поднятии. Оно полезно для автоматического поднятия дочерних кадров с помощью mouse-autoselect-window (см. Автоматический выбор окна мышью).

Обратите внимание: этот параметр не различает «нестрогий» фокус (когда кадр, ранее находившийся в фокусе, сохраняет его, пока указатель мыши не переместится в другое окно оконной системы) и «строгий» фокус (когда кадр немедленно теряет фокус, как только указатель мыши покидает его). Он также не определяет, поддерживает ли оконный менеджер отложенную передачу фокуса или автоматическое поднятие, при которых можно явно указать время до получения фокуса новым кадром или его автоматического поднятия.

Можно настроить политику «фокус следует за мышью» для отдельных окон Emacs с помощью переменной mouse-autoselect-window (см. Автоматический выбор окна мышью).

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Input-Focus.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API