LINUX.ORG.RU

Достать выделенный текст с помощью X11

 


0

1

С помощью https://stackoverflow.com/questions/27378318/c-get-string-from-clipboard-on-l... я создал прототип, который достаёт мне выделенный мышкой текст:

Bool PrintSelection(Display *display, Window window, const char *bufname, const char *fmtname)
{
    char *result;
    unsigned long ressize, restail;
    int resbits;
    Atom bufid  = XInternAtom(display, bufname, False),
         fmtid  = XInternAtom(display, fmtname, False),
         propid = XInternAtom(display, "XSEL_DATA", False),
         incrid = XInternAtom(display, "INCR", False);
    XEvent event;

    XConvertSelection(display, bufid, fmtid, propid, window, CurrentTime);
    do {

        XNextEvent(display, &event);

        if (event.type == SelectionNotify && event.xselection.selection == bufid)
        {
            if  (event.xselection.property) {
                XGetWindowProperty(display, window, propid, 0, LONG_MAX/4, False, AnyPropertyType,
                  &fmtid, &resbits, &ressize, &restail, (unsigned char**)&result);

                if (fmtid == incrid) {
                    printf("Buffer is too large and INCR reading is not implemented yet.\n");
                } else {
                    printf("%s\n", result);
                    XConvertSelection(display, bufid, fmtid, propid, window, CurrentTime);
                }

                XFree(result);
            }
        }

    } while (1);

}

Но код выше не работает по событию «выделил текст - достал актуальный текст», вместо этого в переменной result всегда лежит текст последнего выделения. То есть XNextEvent всегда ловит последнее событие «выделение», даже когда оно уже случилось. Я же хочу:

  • 1. Выделить текст
  • 2. Достать выделенный текст и сделать
    result = NULL
  • 3. Когда нет выделений, то
    result = NULL

Как это можно сделать на базе X11?

Так-то у иксов встроенный буфер обмена, так что тебе не к x11.

anonymous ()

текст не читал, но надеюсь ты учитываешь тот факт, что у X11 как минимум 2 буфера обмена? первый из которых заполняется как раз при выделении чего-либо..

PexuOne ()
Ответ на: комментарий от PexuOne

@PexuOne, про буфер обмена понятно: я использую тот, который для PRIMARY selections. Но вот почему XNextEvent обрабатывает не только актуальное событие, но также уже случившееся и уже обработанное - мне не понятно... Я рассуждал так: XNextEvent достаёт событие и удаляет его из очереди событий, и пока новое событие не случится, очередь будет пуста, но вот по коду выше этого не скажешь... То есть я мышкой текст не выделяю, но XNextEvent говорит, что как будто я постоянно выделяю один и тот же текст на протяжении всего времени работы программы (а это не так).

serg_orl ()
Ответ на: комментарий от serg_orl

Но вот почему XNextEvent обрабатывает не только актуальное событие, но также уже случившееся и уже обработанное - мне не понятно...

Ты хочешь сказать, что если перед XGetWindowProperty добавить отладочную печать, то получишь много-много строк?

вместо этого в переменной result всегда лежит текст последнего выделения

Так и должно быть. Строки «result = NULL» я не вижу.

monk ★★★★★ ()

Нашёл у себя в системе стабильный софт, версия намекает. Не помню проблем за все эти десятилетия и работает куда лучше альтернатив, но что-то меня внезапно напрягает уровень этой поделки, там arbitrary code execution нигде не запрятан?

https://github.com/astrand/xclip

anonymous ()
Ответ на: комментарий от monk

Ты хочешь сказать, что если перед XGetWindowProperty добавить отладочную печать, то получишь много-много строк?

@monk, да, много одинаковых строк. Одна и та же строка выводится в цикле пока не сделаю новый селект.

serg_orl ()
Ответ на: комментарий от serg_orl

Теперь понял. XConvertSelection = «вернуть текущее выделение». Ты его вызываешь сразу после обработки результата XNextEvent и таким образом создаёшь новое событие.

Убери XConvertSelection после printf.

monk ★★★★★ ()
Ответ на: комментарий от monk

Убери XConvertSelection после printf.

Если убрать, то обрабатывается только последнее выделение и XNextEvent блокируется так, что цикл дальше не лупит, то есть новые выделения обработать я не могу. Этого мне и непонятно!

serg_orl ()
Ответ на: комментарий от serg_orl

то есть новые выделения обработать я не могу

Теперь понял, что ты хочешь. В X нет понятия «новые выделения». Ты запрашиваешь текущее.

Могу только предложить сравнивать текущее с предыдущим и обрабатывать, если они отличаются. Но учти, что в процессе пометки текста получишь «новое выделение» на каждую новую помеченную букву.

Или отлавливай событие «отпущена левая кнопка» и в этот момент читай текущее выделение.

monk ★★★★★ ()

Я же хочу:
1. Выделить текст

2. Достать выделенный текст и сделать
result = NULL

3. Когда нет выделений, то
result = NULL

После

XFree(result)
result == NULL // ?

anymouze ★★ ()
Ответ на: комментарий от monk

Могу только предложить сравнивать текущее с предыдущим и обрабатывать, если они отличаются.

Я пока так и сделал, но мне не нравится этот подход. Спасибо за разъяснение по «новому выделению».

serg_orl ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.