Перетаскивание
Данные, передаваемые перетаскиванием, обычно представляют собой обычный текст или список URL-адресов, указывающих на файлы или другие ресурсы. При перетаскивании текст вставляется в место сброса; если это невозможно, предпринимается попытка сохранить его в кольце уничтожения.
Перетаскиваемые URL-адреса передаются соответствующим функциям-обработчикам DND из переменной dnd-protocol-alist либо, в качестве альтернативы, «обработчикам URL», заданным переменными browse-url-handlers и browse-url-default-handlers; если соответствующих обработчиков обоих типов нет, URL-адреса считаются обычным текстом и вставляются в буфер.
- Переменная: dnd-protocol-alist
-
Эта переменная представляет собой список соответствий между регулярными выражениями, которым должны соответствовать URL-адреса, и функциями-обработчиками DND, вызываемыми при сбрасывании URL-адресов, соответствующих этим выражениям.
Если функция-обработчик — это символ, свойство
dnd-multiple-handlerкоторого (см. Свойства символов) установлено, то при сбрасывании ей передаётся список всех URL-адресов, соответствующих её регулярному выражению; если это свойство не установлено, функция вызывается отдельно для каждого такого URL-адреса. За первым аргументом следует один из символовcopy,move,link,privateилиask, определяющий выполняемое действие.Если action —
private, программа, инициировавшая перетаскивание, не настаивает на каком-либо конкретном поведении получателя; в этом случае разумным действием будет открыть URL-адрес или скопировать его содержимое в текущий буфер. Другие значения action имеют примерно тот же смысл, что и аргумент action вdnd-begin-file-drag.Завершив работу, функция-обработчик должна вернуть символ, обозначающий выполненное действие: либо действие, которое ей было передано, либо символ
private, сообщающий источнику перетаскивания, что предписанное им действие не было выполнено.Если несколько обработчиков соответствуют пересекающимся подмножествам элементов перетаскивания, для открытия этого подмножества вызывается обработчик, соответствующий наибольшему числу элементов. Переданные ему элементы впоследствии не передаются другим обработчикам, даже если им они тоже соответствуют.
Emacs не предпринимает мер для приёма данных, отличных от текста и URL-адресов: интерфейсы оконной системы, которые обеспечивают такую возможность, слишком сильно различаются, чтобы их можно было согласованно абстрагировать. Обработчики DND также не могут влиять на действия, которые им предписано выполнять, поскольку отдельные протоколы перетаскивания не предоставляют получателям такого контроля. Реализация перетаскивания в X11 основана на нескольких базовых протоколах, использующих передачу выделения и имеющих много общего; низкоуровневый доступ к ним предоставляют следующие функции и переменные:
- Переменная: x-dnd-test-function
-
Эта функция вызывается, чтобы определить, должен ли Emacs принять сброшенный элемент. Она вызывается с тремя аргументами:
- Окно под перетаскиваемым элементом, то есть окно, буфер которого должен принять сброшенный элемент. Если элемент расположен над компонентом рамки, не являющимся окном (например, полосами прокрутки, панелями инструментов и тому подобным), вместо него передаётся сама рамка.
- Один из символов
move,copy,linkилиask, обозначающий действие с данными элемента, предложенное источником перетаскивания. Эти символы имеют тот же смысл, что и вx-begin-drag. - Вектор типов данных выделения (см. Выделения X), предоставляемых элементом.
Эта функция должна вернуть
nil, чтобы отклонить сброс, либо пару cons, содержащую действие, которое будет выполнено (например, посредством передачи функции-обработчику DND), и тип данных выделения, который следует запросить. Возвращённое в этой паре cons действие также может быть символомprivate, указывающим, что выполняемое действие пока не определено.
- Переменная: x-dnd-known-types
-
Обычно нет необходимости изменять
x-dnd-test-function, поскольку заданный по умолчанию набор критериев принятия сброшенного элемента можно настроить, изменив этот список типов данных выделения. Каждый элемент — это строка, которая, если она обнаруживается стандартной «функцией проверки» в качестве имени символа одного из элементов списка типов данных, заставляет эту функцию принять сброс.Добавлять новую запись в этот список бесполезно, если к
x-dnd-types-alistне добавить соответствующую функцию-обработчик.
- Переменная: x-dnd-types-alist
-
Эта переменная представляет собой список соответствий между строками, обозначающими типы данных выделения, и функциями, вызываемыми при сбрасывании элементов таких типов.
Каждая такая функция получает три аргумента: первый — окно или рамка под местом сброса, как в
x-dnd-test-function; второй — действие, которое нужно выполнить, то есть любое действие, возвращаемое функциями проверки; третий — сами данные выделения (см. Доступ к выделениям).
Типы данных выделения, предоставляемые протоколами перетаскивания X11, иногда отличаются от типов, предоставляемых ICCCM и совместимыми с ним владельцами буфера обмена или основного выделения. Часто вместо стандартного имени выделения X, такого как UTF8_STRING, используется имя типа MIME, например "text/plain;charset=utf-8" (с отличающимся регистром букв в «utf-8»).
Протокол X Direct Save (XDS) позволяет программам поручить получателю указать имя перетаскиваемого файла. При таком сбросе обработчики DND и описанный выше интерфейс, специфичный для X, в значительной степени обходятся, а обработкой сброса занимается другая функция.
- Переменная: x-dnd-direct-save-function
-
Эту переменную следует установить в функцию, которая регистрирует и именует файлы, перетаскиваемые с использованием протокола XDS, в ходе двухэтапной процедуры. Ей передаются два аргумента: need-name и filename.
- Приложение, из которого перетаскивается файл, просит Emacs предоставить полное имя файла, под которым его следует сохранить. Для этого функция прямого сохранения вызывается с первым аргументом need-name, не равным
nil, а второй аргумент filename задаётся как базовое имя сохраняемого файла. Функция должна вернуть полностью раскрытое абсолютное имя файла, под которым его следует сохранить. Например, если файл перетаскивается в окно Dired, естественным каталогом для него будет каталог файла, отображаемого в месте сброса. Если по какой-либо причине сохранить файл невозможно, функция должна вернутьnil, что отменит операцию перетаскивания. - Приложение, из которого перетаскивается файл, сохраняет его под именем, возвращённым при первом вызове функции прямого сохранения. Если сохранение файла проходит успешно, функция прямого сохранения вызывается повторно: на этот раз первый аргумент need-name устанавливается в
nil, а второй аргумент filename — в полное абсолютное имя сохранённого файла. Затем функция должна выполнить необходимые действия с учётом того, что файл сохранён. Например, Dired должна обновить отображаемый каталог, показав в нём новый файл.
По умолчанию для неё задано
x-dnd-direct-save-function:x-dnd-save-direct. - Приложение, из которого перетаскивается файл, просит Emacs предоставить полное имя файла, под которым его следует сохранить. Для этого функция прямого сохранения вызывается с первым аргументом need-name, не равным
- Функция: x-dnd-save-direct need-name filename
-
При вызове с аргументом need-name, не равным
nil, эта функция запрашивает у пользователя абсолютное имя файла, под которым его следует сохранить. Если указанный файл уже существует, она также спрашивает пользователя, следует ли его перезаписать, и возвращает абсолютное имя файла только в том случае, если пользователь подтверждает перезапись.При вызове с аргументом need-name, равным
nil, функция перечитывает список Dired, если текущий буфер находится в режиме Dired или одном из его производных режимов; в противном случае она открывает файл, вызываяfind-file(см. Функции открытия файлов).
- Функция: x-dnd-save-direct-immediately need-name filename
Эта функция работает как
x-dnd-save-direct, но при вызове с аргументом need-name, не равнымnil, она не запрашивает у пользователя полное имя сохраняемого файла, а возвращает свой аргумент filename, раскрытый относительно каталога по умолчанию текущего буфера (см. Функции раскрытия имён файлов). (Если файл с таким именем уже существует в каталоге по умолчанию, подтверждение всё равно запрашивается.)
Если это поддерживается текущей оконной системой, можно также перетаскивать содержимое из Emacs в другие программы. Для этого предназначены следующие функции:
- Функция: dnd-begin-text-drag text &optional frame action allow-same-frame
-
Эта функция начинает операцию перетаскивания из frame в другую программу (называемую целью сброса) и возвращает управление, когда text будет сброшен или операция будет отменена.
action должен быть одним из символов
copyилиmove;copyозначает, что цель сброса должна вставить text, аmoveозначает то же, что иcopy, но вызывающая сторона также должна удалить text из источника, как объясняется в приведённом ниже списке.frame — это рамка, в которой в данный момент удерживается нажатой кнопка мыши, либо
nil, что означает использование выбранной рамки. Поскольку эта функция может сразу вернуть управление, если ни одна кнопка мыши не нажата, её следует вызывать только в ответ на событиеdown-mouse-1или аналогичное событие (см. События мыши), задав для frame рамку, в которой произошло это событие (см. События щелчка).Если allow-same-frame равен
nil, сбросы на frame игнорируются.Возвращаемое значение отражает действие, фактически выполненное целью сброса, а следовательно, и действие, которое при необходимости должна выполнить вызывающая сторона. Это один из следующих символов:
copy-
Цель сброса вставила сброшенный текст.
move-
Цель сброса вставила сброшенный текст, и вызывающая сторона должна удалить text из буфера, из которого он был извлечён, если применимо.
private-
Цель сброса выполнила какое-либо другое неуказанное действие.
nilОперация перетаскивания была отменена.
- Функция: dnd-begin-file-drag file &optional frame action allow-same-frame
-
Эта функция начинает операцию перетаскивания из frame в другую программу (называемую целью сброса) и возвращает управление, когда file будет сброшен или операция будет отменена.
Если file — удалённый файл, будет создана его временная локальная копия.
action должен быть одним из символов
copy,moveилиlink;copyозначает, что цель сброса должна открыть или скопировать file,moveозначает, что цель сброса должна переместить файл в другое место, аlinkозначает, что цель сброса должна создать символическую ссылку на file. Указаниеlinkв качестве действия, если file является удалённым файлом, приводит к ошибке.frame и allow-same-frame имеют тот же смысл, что и при вызовах
dnd-begin-text-drag.Возвращаемое значение — действие, фактически выполненное целью сброса, то есть один из следующих символов:
copy-
Цель сброса открыла file или скопировала его в другое место.
move-
Цель сброса переместила file в другое место.
link-
Цель сброса (обычно файловый менеджер) создала символическую ссылку на file.
private-
Цель сброса выполнила какое-либо другое неуказанное действие.
nilОперация перетаскивания была отменена.
- Функция: dnd-begin-drag-files files &optional frame action allow-same-frame
Эта функция аналогична
dnd-begin-file-drag, за исключением того, что files — это список файлов. Если цель сброса не поддерживает сброс нескольких файлов, вместо этого будет использован первый файл.
- Функция: dnd-direct-save file name &optional frame allow-same-frame
Эта функция работает аналогично
dnd-begin-file-drag(если используется действие по умолчаниюcopy), за исключением того, что принимает имя, под которым должна быть сохранена копия.
Высокоуровневые интерфейсы, описанные выше, реализованы на основе низкоуровневой примитивной функции. Низкоуровневый интерфейс x-begin-drag также можно использовать для перетаскивания содержимого, отличного от текста и файлов. Для этого требуется подробное знание типов данных и действий, поддерживаемых программами на каждой платформе, для которой вызывающая сторона хочет обеспечить поддержку.
- Функция: x-begin-drag targets &optional action frame return-frame allow-current-frame follow-tooltip
-
Эта функция начинает перетаскивание из frame и возвращает управление по завершении операции перетаскивания, будь то успешный сброс или отклонённый сброс. Сброс выполняется, когда все кнопки мыши отпущены над окном X, отличным от frame (целью сброса), либо над любым окном X, если allow-current-frame не равен
nil. Если в начале операции перетаскивания не нажата ни одна кнопка мыши, эта функция может немедленно вернутьnil.targets — это список строк, представляющих цели выделения, подобный аргументу data-type функции
gui-get-selection, которые цель сброса может запросить у Emacs (см. Выделения оконной системы).action — символ, обозначающий действие, рекомендуемое для цели. Это может быть
XdndActionCopyилиXdndActionMove; оба значения подразумевают копирование содержимого выделенияXdndSelectionв цель сброса, но второе дополнительно означает обещание удалить содержимое выделения после копирования.action также может быть списком соответствий между символами, обозначающими доступные действия, и строками, которые цель сброса показывает пользователю для выбора одного из этих действий.
Если return-frame не равен
nilи после выхода за пределы frame мышь перемещается над рамкой Emacs, немедленно возвращается рамка, над которой оказалась мышь. Если return-frame — это символnow, будет возвращена любая рамка под указателем мыши без ожидания, пока мышь сначала выйдет за пределы frame. return-frame полезен, если нужно особым образом обрабатывать перетаскивание содержимого из одной рамки в другую, сохраняя при этом возможность перетаскивать содержимое в другие программы, однако его работа не гарантируется во всех системах и со всеми оконными менеджерами.Если follow-tooltip не равен
nil, положение любой всплывающей подсказки (например, отображаемой функциейtooltip-show) будет следовать за указателем мыши во время операции перетаскивания. Подсказка будет скрыта, как только все кнопки мыши будут отпущены.Если сброс был отклонён или цель сброса не найдена, эта функция возвращает
nil. В противном случае она возвращает символ, обозначающий действие, выбранное целью; оно может отличаться от action, если цель сброса его не поддерживает. ПомимоXdndActionCopyиXdndActionMove, допустимым возвращаемым значением является такжеXdndActionPrivate; оно означает, что цель сброса выбрала неопределённое действие и вызывающей стороне не нужно предпринимать никаких дополнительных действий.Чтобы завершить выбранное целью действие, вызывающая сторона должна взаимодействовать с целью. Например, если эта функция возвращает
XdndActionMove, вызывающая сторона должна удалить перетаскиваемый текст из буфера; то же относится и к другим перетаскиваемым данным, для которых применимы аналогичные условия.
Функция x-begin-drag «за кулисами» использует несколько протоколов перетаскивания. Если перетаскивается содержимое, поддержка которого конкретным протоколом не предусмотрена, этот протокол можно отключить, изменив значения следующих переменных:
- Переменная: x-dnd-disable-motif-protocol
Если значение этой переменной не равно
nil, протоколы перетаскивания Motif отключаются, и перетаскивание в программы, поддерживающие только эти протоколы, работать не будет.
- Переменная: x-dnd-use-offix-drop
Если значение этой переменной равно
nil, протокол перетаскивания OffiX (старый KDE) отключается. Если значение этой переменной — символfiles, протокол OffiX используется только в том случае, если"FILE_NAME"входит в число целей, переданных функцииx-begin-drag. Любое другое значение означает, что протокол OffiX будет использоваться для сброса всего поддерживаемого содержимого.
- Переменная: x-dnd-use-unsupported-drop
-
Если один из типов целей
"STRING","UTF8_STRING","COMPOUND_TEXT"или"TEXT"присутствует в списке, переданном функцииx-begin-drag, Emacs попытается использовать синтезированные события мыши и основное выделение для вставки текста, если цель сброса вообще не поддерживает никаких протоколов перетаскивания.Побочным эффектом будет то, что после такого сброса Emacs станет владельцем основного выделения. Эту эмуляцию можно отключить, установив для данной переменной значение
nil.
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/Drag-and-Drop.html