Is there a simple way to get text from clipboard on X11?

47 views
Skip to first unread message

Will B

unread,
Apr 20, 2017, 6:16:51 PM4/20/17
to fltk.general
Greetings everyone!

Here is the scenario:

  * I am using Fl::add_clipboard_notify() to run a callback when text is explicitly copied or cut in another app.

  * I am not concerned about the selection buffer, only the clipboard.

  * I am not concerned about copy/cut events from my FLTK app.

  * I am only wanting text and not images from the clipboard.

  * I do not want to use the Fl::paste() method because I don't want to paste anything to a control -- I only want the clipboard text.

I have been looking at the Fl::paste() code from Fl_x.cxx, which I'll include below for reference:

// Call this when a "paste" operation happens:
void Fl::paste(Fl_Widget &receiver, int clipboard, const char *type) {
 
if (fl_i_own_selection[clipboard]) {
   
// We already have it, do it quickly without window server.
   
// Notice that the text is clobbered if set_selection is
   
// called in response to FL_PASTE!
   
// However, for now, we only paste text in this function
   
if (fl_selection_type[clipboard] != Fl::clipboard_plain_text) return; //TODO: allow copy/paste of image within same app
   
Fl::e_text = fl_selection_buffer[clipboard];
   
Fl::e_length = fl_selection_length[clipboard];
   
if (!Fl::e_text) Fl::e_text = (char *)"";
    receiver
.handle(FL_PASTE);
   
return;
 
}
 
// otherwise get the window server to return it:
  fl_selection_requestor
= &receiver;
 
Atom property = clipboard ? CLIPBOARD : XA_PRIMARY;
 
Fl::e_clipboard_type = type;
 
XConvertSelection(fl_display, property, TARGETS, property,
                    fl_xid
(Fl::first_window()), fl_event_time);
}

I understand the section of code where FLTK is checking to see if it owns the selection, but I'm not understanding the X code below it, specifically, what is XConvertSelection() doing?  I've visited the documentation page, and it's pretty light on important details. 

All I want to do is get the text from the clipboard and not the selection buffer.  Do you all have any suggestions on how to accomplish this?

Thank you so much!  :-)

Will Brokenbourgh




Albrecht Schlosser

unread,
Apr 20, 2017, 7:56:49 PM4/20/17
to fltkg...@googlegroups.com
On 21.04.2017 00:16 Will B wrote:

> * I am using Fl::add_clipboard_notify() to run a callback when text is
> explicitly copied or cut in another app.
>
> * I am only wanting text and /not/ images from the clipboard.
>
> * I do /not/ want to use the Fl::paste() method because I don't want
> to paste anything to a control -- I only want the clipboard text.

Hmm, why not use Fl::paste() anyway? I assume that it's not necessary to
show() the widget to make it receive the FL_PASTE event.

You may want to take a look at examples/clipboard.cxx. You can compile
it with 'make' in the examples directory and run it to see it in action
(I'm sometimes using it and it works pretty well on Windows and Linux).

You'll find the text in Fl::event_text(). See handle() at line #111++:

else { // text is being pasted
display->buffer()->text(Fl::event_text()); // [1]
value(display);
display->redraw();
}

[1] here Fl::event_text() is assigned to a text buffer, but you may just
use it as you like.

Disclaimer: I don't know much about FLTK's clipboard handling and I
didn't write the code of clipboard.cxx, so I don't know if it will
really help you.

Will B

unread,
Apr 20, 2017, 8:47:35 PM4/20/17
to fltk.general, Albrech...@online.de
On Thursday, April 20, 2017 at 4:56:49 PM UTC-7, Albrecht Schlosser wrote:
Hmm, why not use Fl::paste() anyway? I assume that it's not necessary to
show() the widget to make it receive the FL_PASTE event.

You may want to take a look at examples/clipboard.cxx. You can compile
it with 'make' in the examples directory and run it to see it in action
(I'm sometimes using it and it works pretty well on Windows and Linux).

You'll find the text in Fl::event_text(). See handle() at line #111++:

     else { // text is being pasted
       display->buffer()->text(Fl::event_text()); // [1]
       value(display);
       display->redraw();
     }

[1] here Fl::event_text() is assigned to a text buffer, but you may just
use it as you like.

Disclaimer: I don't know much about FLTK's clipboard handling and I
didn't write the code of clipboard.cxx, so I don't know if it will
really help you.

Thank you for that.  That's close to what I was doing before and it just wasn't working out.

I'll keep looking for a solution.

Sincerely,

Will Brokenbourgh
Message has been deleted

Will B

unread,
Apr 20, 2017, 9:52:20 PM4/20/17
to fltk.general, Albrech...@online.de
For anyone in the future looking for a clue to achieve this, here's what I used for my callback for Fl::add_clipboard_notify():

void svHandleLocalClipboard (int source, void* notused)
{
   
ulong nitems;
   
ulong rem;
   
int format;
    uchar
* data;
   
Atom type;
   
const Atom xtarget = XInternAtom(fl_display, "UTF8_STRING", 0);
   
XEvent ev;

   
// do XConvertSelection and wait for correct event to process
   
while (true) {
       
XConvertSelection(fl_display, XA_PRIMARY, xtarget, XA_PRIMARY,
            fl_xid
(app->mainWin), CurrentTime);

       
XNextEvent(fl_display, &ev);

       
if (XFilterEvent(&ev, None))
           
continue;

       
// selectionnotify event - let's process it
       
if (ev.type == SelectionNotify) {

           
if (XGetWindowProperty(fl_display, fl_xid(app->mainWin), XA_PRIMARY, 0, 32, false,
               
AnyPropertyType, &type, &format, &nitems, &rem, &data)) {
                std
::cout << "Clipboard allocation failed\n";
               
return;
           
} else
               
break;
       
}
   
}

   
if (source == 1 && data != NULL) {

       
int nSize = static_cast<int>(nitems);

       
char strData[nSize + 1];
       
char charP;
       
int i = 0;

        memset
(strData, 0, sizeof(strData));

       
// convert uchar to char
       
for (; i < nSize; i++) {
            charP
= static_cast<char>(data[i]);
            strData
[i] = charP;
       
}

       
// send clipboard text to remote server
       
if (strData != NULL) {
            std
::cout << "The clipboard text is: " << strData << "\n";
       
}
   
}
}



Reply all
Reply to author
Forward
0 new messages