Дочерние фреймы — это объекты, занимающие промежуточное положение между окнами (см. Окна) и «обычными» фреймами. Как и окна, они прикреплены к владеющему фрейму. В отличие от окон, они могут перекрывать друг друга — изменение размера или положения одного дочернего фрейма не изменяет размер или положение любого из его соседних дочерних фреймов.
По замыслу, операции по созданию или изменению дочерних фреймов реализованы с помощью параметров фреймов (см. Параметры фреймов) без каких-либо специализированных функций или настраиваемых переменных. Обратите внимание, что дочерние фреймы имеют смысл только на графических терминалах.
Чтобы создать новый дочерний фрейм или преобразовать обычный фрейм в дочерний, установите параметр parent-frame этого фрейма (см. Параметры взаимодействия фреймов) в значение уже существующего фрейма. Фрейм, указанный этим параметром, будет родительским фреймом для данного фрейма до тех пор, пока параметр не будет изменён или сброшен. Технически это делает окно оконной системы дочернего фрейма дочерним окном окна оконной системы родительского фрейма.
Параметр parent-frame может быть изменён в любое время. Установка его в другой фрейм переназначает родителя дочернего фрейма. Установка его в другой дочерний фрейм делает данный фрейм вложенным дочерним фреймом. Установка его в nil восстанавливает статус фрейма как фрейма верхнего уровня — фрейма, окно оконной системы которого является дочерним по отношению к корневому окну дисплея.23
Поскольку дочерние фреймы могут быть произвольно вложенными, фрейм может быть одновременно и дочерним, и родительским. Также роли дочернего и родительского фреймов могут быть в любой момент обращены (хотя обычно рекомендуется, чтобы размер дочернего фрейма был достаточно меньше размера его родителя). Будет выдана ошибка при попытке сделать фрейм предком самого себя.
Большинство оконных систем обрезают дочерний фрейм по родным границам (см. Геометрия фрейма) его родительского фрейма — всё, что находится за этими границами, обычно невидимо. Параметры left и top дочернего фрейма задают положение относительно верхнего левого угла родного фрейма его родителя. Когда родительский фрейм изменяет размер, это положение концептуально остаётся неизменным.
Сборки NS не обрезают дочерние фреймы по границам родительского фрейма, позволяя располагать их так, чтобы они не заслоняли родительский фрейм, оставаясь при этом видимыми сами по себе.
Обычно перемещение родительского фрейма влечёт за собой перемещение всех его дочерних фреймов и их потомков, сохраняя их относительное положение неизменным. Обратите внимание, что хук move-frame-functions (см. Положение фрейма) вызывается для дочернего фрейма только тогда, когда изменяется положение дочернего фрейма относительно его родительского фрейма.
Когда родительский фрейм изменяет размер, его дочерние фреймы концептуально сохраняют свои предыдущие размеры и положение относительно левого верхнего угла родителя. Это означает, что дочерний фрейм может стать (частично) невидимым, когда его родительский фрейм сжимается. Параметр keep-ratio (см. Параметры взаимодействия фреймов) может использоваться для пропорционального изменения размера и положения дочернего фрейма при изменении размера его родительского фрейма. Это может предотвратить заслонение частей фрейма при сжатии его родительского фрейма.
Видимый дочерний фрейм всегда появляется поверх своего родительского фрейма, заслоняя его части, за исключением сборок NS, где он может располагаться под родителем. Это сравнимо с окном оконной системы фрейма верхнего уровня, которое также всегда появляется поверх своего родительского окна — корневого окна рабочего стола. Когда родительский фрейм свёрнут или сделан невидимым (см. Видимость фреймов), его дочерние фреймы делаются невидимыми. Когда родительский фрейм разворачивается или делается видимым, его дочерние фреймы делаются видимыми.
Когда родительский фрейм должен быть удалён (см. Удаление фреймов), его дочерние фреймы рекурсивно удаляются перед ним. Существует одно исключение из этого правила: когда дочерний фрейм служит суррогатным минибуферным фреймом (см. Минибуферы и фреймы) для другого фрейма, он сохраняется до тех пор, пока родительский фрейм не будет удалён. Если к этому моменту ни один оставшийся фрейм не использует дочерний фрейм как свой минибуферный фрейм, Emacs попытается также удалить дочерний фрейм. Если это удаление по какой-либо причине не удаётся, дочерний фрейм становится фреймом верхнего уровня.
Возможность наличия у дочернего фрейма меню или панели инструментов зависит от оконной системы или оконного менеджера. Большинство оконных систем явно запрещают строки меню для дочерних фреймов. Желательно отключать как строку меню, так и панель инструментов через начальные настройки параметров фрейма.
Обычно дочерние фреймы не имеют украшений оконного менеджера, таких как заголовок или внешние границы (см. Геометрия фрейма). Если дочерний фрейм не показывает меню или панель инструментов, любые другие границы фрейма (см. Параметры макета) могут использоваться вместо внешних границ.
В частности, под X (но не при сборке с GTK+) может использоваться внешняя граница фрейма. В MS-Windows указание ненулевой ширины внешней границы отображает внешнюю границу шириной в один пиксель. Во всех оконных системах может использоваться внутренняя граница. В любом случае рекомендуется отключать украшения оконного менеджера для дочернего фрейма с помощью параметра фрейма undecorated (см. Параметры управления).
Для изменения размера или перемещения неоформленного дочернего фрейма с помощью мыши необходимо использовать специальные параметры фрейма (см. Параметры перетаскивания мышью). Внутренняя граница дочернего фрейма, если она присутствует, может использоваться для изменения размера фрейма с помощью мыши при условии, что фрейм имеет ненулевой параметр drag-internal-border. Если задан, параметр snap-width указывает количество пикселей, на котором фрейм прилипает к соответствующему краю или углу своего родительского фрейма.
Существует два способа перетаскивания всего дочернего фрейма с помощью мыши: Параметр drag-with-mode-line, если он не равен nil, позволяет перетаскивать фрейм без окна минибуфера (см. Окна минибуфера) через область строки режима его самого нижнего окна. Параметр drag-with-header-line, если он не равен nil, позволяет перетаскивать фрейм через область заголовка его самого верхнего окна.
Чтобы снабдить дочерний фрейм перетаскиваемым заголовком или строкой режима, полезны параметры окна mode-line-format и header-line-format (см. Параметры окон). Они позволяют убрать нежелательную строку режима (когда выбран drag-with-header-line) и удалить чувствительные к мыши области, которые могут мешать перетаскиванию фрейма.
Когда пользователь перетаскивает фрейм мышью и промахивается, легко вытащить фрейм за пределы экранной области его родителя. Вернуть такой фрейм обратно может быть сложно после отпускания кнопки мыши. Чтобы предотвратить такую ситуацию, рекомендуется установить параметры фрейма top-visible или bottom-visible (см. Параметры перетаскивания мышью).
Установите параметр top-visible дочернего фрейма в число, если вы намерены разрешить пользователю перетаскивать этот фрейм за его заголовок. Установка top-visible в число предотвращает перетаскивание верхнего края дочернего фрейма выше верхнего края его родителя. Установите параметр bottom-visible в число, если вы намерены перетаскивать этот фрейм через его строку режима; это предотвращает перетаскивание нижнего края дочернего фрейма ниже нижнего края его родителя. В любом случае это число также задаёт ширину и высоту (в пикселях) области дочернего фрейма, которая остаётся видимой во время перетаскивания.
Когда дочерний фрейм используется для отображения буфера с помощью display-buffer-in-child-frame (см. Функции действий для отображения буферов), параметр фрейма auto-hide-function (см. Параметры взаимодействия фреймов) может быть установлен в функцию для надлежащей обработки фрейма, когда окно, отображающее буфер, должно быть закрыто.
Когда дочерний фрейм используется во время взаимодействия с минибуфером, например, для отображения дополнений в отдельном окне, параметр minibuffer-exit (см. Параметры взаимодействия фреймов) полезен для обработки фрейма при выходе из минибуфера.
Поведение дочерних фреймов отличается от поведения фреймов верхнего уровня и в ряде других аспектов. Вот некоторые из них:
iconify-frame для дочернего фрейма попытается свернуть вместо него фрейм верхнего уровня, соответствующий этому дочернему фрейму. Чтобы получить другое поведение, пользователи могут настроить параметр iconify-child-frame, описанный ниже.
z-group (см. Параметры положения) дочернего фрейма изменяет только порядок расположения дочерних фреймов с одним и тем же родителем.
mouse-autoselect-window может помочь в этом отношении (см. Автовыбор окна мышью).
Следующие две функции могут быть полезны при работе с дочерними и родительскими фреймами:
Эта функция возвращает родительский фрейм для frame. Родительским фреймом для frame является фрейм Emacs, окно оконной системы которого является родительским окном для окна оконной системы frame. Если такой фрейм существует, frame считается дочерним фреймом этого фрейма.
Эта функция возвращает nil, если frame не имеет родительского фрейма.
Эта функция возвращает не nil, если ancestor является предком descendant. ancestor является предком descendant, если он либо является родительским фреймом для descendant, либо является предком родительского фрейма для descendant. Как ancestor, так и descendant должны указывать на живые фреймы.
Обратите также внимание на функцию window-largest-empty-rectangle (см. Координаты и окна), которую можно использовать для вписывания дочернего фрейма в наибольшую пустую область существующего окна. Это может быть полезно, чтобы избежать заслонения дочерним фреймом текста, отображаемого в этом окне.
Настройка следующего параметра может быть полезна для корректировки поведения iconify-frame для дочерних фреймов.
Этот параметр указывает Emacs, как действовать при запросе на сворачивание дочернего фрейма. Если он равен nil, iconify-frame не будет ничего делать при вызове для дочернего фрейма. Если он равен iconify-top-level, Emacs попытается свернуть вместо этого фрейм верхнего уровня, являющийся предком данного дочернего фрейма. Если он равен make-invisible, Emacs попытается сделать этот дочерний фрейм невидимым вместо его сворачивания.
Любое другое значение означает попытку свернуть дочерний фрейм. Поскольку такая попытка может не быть поддержана всеми оконными менеджерами и даже может привести к тому, что дочерний фрейм перестанет реагировать на действия пользователя, по умолчанию вместо этого сворачивается фрейм верхнего уровня.
В Haiku дочерние фреймы видны только тогда, когда родительский фрейм активен, из-за ограничения оконной системы Haiku. Из-за того же ограничения дочерние фреймы гарантированно появляются только над своим родителем верхнего уровня; то есть самым верхним фреймом в иерархии, который не имеет родительского фрейма.