Re: CLIPBOARD selection doesn't save content
Hi again, First of all, there was a little mistake in my posted code: xevt.xselectionrequest.requestor, wanted_atoms[i], requested, 32, PropModeReplace, (unsigned char *) TEST, 4); Should have been xevt.xselectionrequest.requestor, wanted_atoms[i], requested, 8, PropModeReplace, (unsigned char *) TEST, 4); Note that 32 has been replaced by 8, otherwise you can't sore more than 4 characters on the clipboard. Second, I tested my implementation with Xubuntu (Xfce) and openSUSE (KDE). I found that Xubuntu doesn't seem to have a clipboard manager at all, if I try to paste copied code after the termination of an application it doesn't work. So, no Xfce availability, at least for Xubuntu. openSUSE *has* a clipboard manager, the paste-after-termination thing worked quite well there. Unfortunately, my code did not. The error message No clipboard manager available got triggered, for whatever reason. Does the clipboard manager of KDE work that different? Btw. I'm testing with VirtualBox. Marvin Quintus schrieb: Thank you! Marvin ___ xorg@lists.freedesktop.org: X.Org support Archives: http://lists.freedesktop.org/archives/xorg Info: http://lists.freedesktop.org/mailman/listinfo/xorg
Re: CLIPBOARD selection doesn't save content
Hi all, I managed to get it work now! Many thanks to you all, without the resources you pointed me to I wouldn't have been able to finish this. So, here's the code: - /* *call-seq: * Clipboard.write(clipboard, text) == nil * *Writes +text+ to the specified clipboard. */ static VALUE m_write(VALUE self, VALUE rclipboard, VALUE rtext) /*VALUE is a Ruby object*/ { Display * p_display; Window win, clipboard_owner; XEvent xevt, xevt2; Atom targets[6], target_sizes[12], save_targets[2]; /*Ignore Ruby parameters as we're just debugging*/ /*Open default display*/ p_display = XOpenDisplay(NULL); /*Let Ruby handle protocol errors*/ XSetErrorHandler(handle_x_errors); /*This are the TARGETS we support*/ targets[0] = TARGETS_ATOM; targets[1] = UTF8_ATOM; targets[2] = XA_STRING; targets[3] = XInternAtom(p_display, TIMESTAMP, True); /*TODO: Implement this request*/ targets[4] = SAVE_TARGETS_ATOM; targets[5] = TARGET_SIZES_ATOM; /*These are the target's sizes*/ target_sizes[0] = TARGETS_ATOM; target_sizes[1] = 6 * sizeof(Atom); target_sizes[2] = UTF8_ATOM; target_sizes[3] = 4; target_sizes[4] = XA_STRING; target_sizes[5] = 4; target_sizes[6] = XInternAtom(p_display, TIMESTAMP, True); target_sizes[7] = -1; target_sizes[8] = SAVE_TARGETS_ATOM; target_sizes[9] = -1; target_sizes[10] = TARGET_SIZES_ATOM; target_sizes[11] = 12 * sizeof(Atom); /*We want our data have stored as UTF-8*/ save_targets[0] = UTF8_ATOM; save_targets[1] = XA_STRING; if (CLIPBOARD_MANAGER_ATOM == None) rb_raise(XError, No clipboard manager available!); /*Throw Ruby error*/ /*Output some useful information*/ printf(PID: %i\n, getpid()); printf(Owner of CLIPBOARD_MANAGER: %lu\n, XGetSelectionOwner(p_display, CLIPBOARD_MANAGER_ATOM)); /*Create a window for copying into CLIPBOARD*/ win = CREATE_REQUESTOR_WIN; if ( (clipboard_owner = XGetSelectionOwner(p_display, CLIPBOARD_MANAGER_ATOM)) == None) rb_raise(XError, No owner for the CLIPBOARD_MANAGER selection!); /*Throw Ruby error*/ /*Get control of the CLIPBOARD*/ XSetSelectionOwner(p_display, CLIPBOARD_ATOM, win, CurrentTime); /*Our application needs to exit*/ XChangeProperty(p_display, win, IMITATOR_X_CLIP_ATOM, XA_ATOM, 32, PropModeReplace, (unsigned char *) save_targets, 1); XConvertSelection(p_display, CLIPBOARD_MANAGER_ATOM, SAVE_TARGETS_ATOM, IMITATOR_X_CLIP_ATOM, win, CurrentTime); for (;;) { XNextEvent(p_display, xevt); /**DEBUGGING INFORMATION***/ if (xevt.type == SelectionRequest) { printf(SelectionRequest event; Requested target: %s\n, XGetAtomName(p_display, xevt.xselectionrequest.target)); printf(Requestor: %lu\n, xevt.xselectionrequest.requestor); } else if (xevt.type == SelectionNotify) { printf(SelectionNotify event; property: %s\n, XGetAtomName(p_display, xevt.xselection.property)); printf(Requestor: %lu\n, xevt.xselection.requestor); } /**END DEBUGGING INFORMATION*/ if (xevt.type == SelectionRequest) /*selection-related event*/ { /*This is for all anserwing events the same (except not supported)*/ xevt2.xselection.type = SelectionNotify; xevt2.xselection.display = xevt.xselectionrequest.display; xevt2.xselection.requestor = xevt.xselectionrequest.requestor; xevt2.xselection.selection = xevt.xselectionrequest.selection; xevt2.xselection.target = xevt.xselectionrequest.target; xevt2.xselection.time = xevt.xselectionrequest.time; xevt2.xselection.property = xevt.xselectionrequest.property; /*Handle individual selection requests*/ if (xevt.xselectionrequest.target == XInternAtom(p_display, TARGETS, True)) /*TARGETS information requested*/ { /*Write supported TARGETS into the requestor*/ XChangeProperty(p_display, xevt.xselectionrequest.requestor, xevt.xselectionrequest.property, XA_ATOM, 32, PropModeReplace, (unsigned char *) targets, 4); /*Notify the requestor we have set its requested property*/ XSendEvent(p_display, xevt.xselectionrequest.requestor, False, NoEventMask, xevt2); } else if (xevt.xselectionrequest.target == TARGET_SIZES_ATOM) { /*Answer how much data we want to store*/ XChangeProperty(p_display, xevt.xselectionrequest.requestor, xevt.xselectionrequest.property, ATOM_PAIR_ATOM, 32, PropModeReplace, (unsigned char *) target_sizes, 6); /*Notify the requestor we have set its requested property*/ XSendEvent(p_display, xevt.xselectionrequest.requestor, False, NoEventMask, xevt2); } else if (xevt.xselectionrequest.target == MULTIPLE_ATOM) /*Makes multiple requests at once*/ { Atom actual_type, requested = None; int actual_format, i; unsigned long nitems, bytes; unsigned char * prop;
Re: CLIPBOARD selection doesn't save content
Hi Glynn, Apart from implementing the CLIPBOARD selection, the application should implement the SAVE_TARGETS protocol for optimum behaviour with modern clipboard managers. For details, see: OK, I've done so (hopefully). http://www.freedesktop.org/wiki/ClipboardManager After rereading this document, I think I finally got how the mechanism works. Can you confirm this: 0. The clipboard manager acquires the CLIPBOARD_MANAGER and CLIPBOARD selections. 1. My application acquires CLIPBOARD, acting just as if it were PRIMARY. 2. My application wants to exit. Therefore, it 1. Sets a property, say, MY_SELECTION, to the targets it wants the clipboard manager to preserve the content. 2. Requests the X server to convert the CLIPBOARD_MANAGER selection to SAVE_TARGETS, by passing my application window and the MY_SELECTION property. 3. The clipboard manager gets notified (by a SelectionRequest event) and now queries my application for each target I set MY_SELECTION to. 4. The clipboard manager sends my application a SelectionNotify event with property SAVE_TARGETS (or None if it has failed to save the content) indicating that is has completed 5a. The clipboard manager takes ownership of the CLIPBOARD selection 5b. (parallel to 5a) My application exits In the end, my application hopefully is just my function, otherwise I would have to go to subprocesses. Marvin Glynn Clements schrieb: X itself doesn't have a persistent clipboard. If you want the clipboard contents to persist after the application terminates, a clipboard manager must be running. Clipboard managers are something of a mixed blessing, so not everyone uses one. Whether a clipboard manager is in use and its exact behaviour are dependent upon the desktop environment. All that your program can do is to implement the relevant protocols; the rest is beyond its control. Apart from implementing the CLIPBOARD selection, the application should implement the SAVE_TARGETS protocol for optimum behaviour with modern clipboard managers. For details, see: http://www.freedesktop.org/wiki/ClipboardManager If a compliant clipboard manager is running, this should cause it to take over the clipboard (ownership and contents) from the terminating process. Older clipboard managers (and clients) don't support the SAVE_TARGETS protocol, which means that the clipboard manager must retrieve the clipboard contents whenever the clipboard changes, which can be inefficient if the data is large and/or if there are many targets (some of which may be computationally expensive to generate). ___ xorg@lists.freedesktop.org: X.Org support Archives: http://lists.freedesktop.org/archives/xorg Info: http://lists.freedesktop.org/mailman/listinfo/xorg
Re: CLIPBOARD selection doesn't save content
Quintus wrote: Apart from implementing the CLIPBOARD selection, the application should implement the SAVE_TARGETS protocol for optimum behaviour with modern clipboard managers. For details, see: OK, I've done so (hopefully). http://www.freedesktop.org/wiki/ClipboardManager After rereading this document, I think I finally got how the mechanism works. Can you confirm this: 0. The clipboard manager acquires the CLIPBOARD_MANAGER and CLIPBOARD selections. 1. My application acquires CLIPBOARD, acting just as if it were PRIMARY. 2. My application wants to exit. Therefore, it 1. Sets a property, say, MY_SELECTION, to the targets it wants the clipboard manager to preserve the content. 2. Requests the X server to convert the CLIPBOARD_MANAGER selection to SAVE_TARGETS, by passing my application window and the MY_SELECTION property. 3. The clipboard manager gets notified (by a SelectionRequest event) and now queries my application for each target I set MY_SELECTION to. 4. The clipboard manager sends my application a SelectionNotify event with property SAVE_TARGETS (or None if it has failed to save the content) indicating that is has completed 5a. The clipboard manager takes ownership of the CLIPBOARD selection 5b. (parallel to 5a) My application exits I believe this is correct, but I haven't actually written low-level selection-handling code since the SAVE_TARGETS protocol was created. In the end, my application hopefully is just my function, otherwise I would have to go to subprocesses. Yes. From the X server's perspective, a function which opens a connection, runs an event loop then closes the connection is indistinguishable from a more typical client. Successive calls to that function would appear as distinct short-lived clients. The server only sees connections; what happens on the client side of those connections is irrelevant. -- Glynn Clements gl...@gclements.plus.com ___ xorg@lists.freedesktop.org: X.Org support Archives: http://lists.freedesktop.org/archives/xorg Info: http://lists.freedesktop.org/mailman/listinfo/xorg
Re: CLIPBOARD selection doesn't save content
Hi, If you can, try it under gnome too That's quite easy to do - I'm already working under GNOME, I never tried KDE. as the last time I worked with any clipboard code, I found its clipboard manager more cooperative at saving non-standard data-types than when testing under KDE. Is text a non-standard data type? I can't believe this. Also, the clipboard manager in gnome will only request the clipboard contents and take over from my app when the app closes. We explicitly call gtk_clipboard_store() as we tear down the app. Sounds reasonable, but that's GTK-specific. Since I'm writing a general-purpose extension, it should work wherever X11 is installed. I looked at your code, and then tried to integrate this into my function by only using Xlib's functions. This is how it looks now: --- /* *call-seq: * Clipboard.write(clipboard, text) == nil * *Writes +text+ to the specified clipboard. */ static VALUE m_write(VALUE self, VALUE rclipboard, VALUE rtext) /*VALUE is a Ruby object*/ { Display * p_display; Window win; XEvent xevt, xevt2; Atom targets[4]; int res; /*Open default display*/ p_display = XOpenDisplay(NULL); /*Let Ruby handle protocol errors*/ XSetErrorHandler(handle_x_errors); /*This are the TARGETS we support*/ targets[0] = XInternAtom(p_display, TARGETS, True); targets[1] = UTF8_ATOM; targets[2] = XA_STRING; targets[3] = XInternAtom(p_display, TIMESTAMP, True); /*TODO: Implement this request*/ if (CLIPBOARD_MANAGER_ATOM == None) printf(FAIL\n); /*Output some useful information*/ printf(PID: %i\n, getpid()); printf(Owner of CLIPBOARD_MANAGER: %lu\n, XGetSelectionOwner(p_display, CLIPBOARD_MANAGER_ATOM)); /*Create a window for copying into CLIPBOARD*/ win = CREATE_REQUESTOR_WIN; if (XGetSelectionOwner(p_display, CLIPBOARD_MANAGER_ATOM) == None) rb_raise(XError, No owner for the CLIPBOARD_MANAGER selection!); /*Throw Ruby error*/ res = XChangeProperty(p_display, win, CLIPBOARD_ATOM, XA_ATOM, 32, PropModeReplace, (unsigned char *) targets, 4); printf(res = %i\n, res); res = XConvertSelection(p_display, CLIPBOARD_MANAGER_ATOM, SAVE_TARGETS_ATOM, CLIPBOARD_ATOM, win, CurrentTime); printf(res = %i\n, res); /*Get control of the CLIPBOARD*/ XSetSelectionOwner(p_display, CLIPBOARD_ATOM, win, CurrentTime); for (;;) { XNextEvent(p_display, xevt); if (xevt.type == SelectionRequest) { printf(SelectionRequest event; Requested target: %s\n, XGetAtomName(p_display, xevt.xselectionrequest.target)); printf(Requestor: %lu\n, xevt.xselectionrequest.requestor); } else if (xevt.type == SelectionNotify) { printf(SelectionNotify event; property: %s\n, XGetAtomName(p_display, xevt.xselection.property)); printf(Requestor: %lu\n, xevt.xselection.requestor); } if (xevt.type == SelectionRequest) /*selection-related event*/ { if (xevt.xselectionrequest.target == XInternAtom(p_display, TARGETS, True)) /*TARGETS information requested*/ { /*Write supported TARGETS into the requestor*/ XChangeProperty(p_display, xevt.xselectionrequest.requestor, xevt.xselectionrequest.property, XA_ATOM, 32, PropModeReplace, (unsigned char *) targets, 4); /*Notify the requestor we have set its requested property*/ xevt2.xselection.type = SelectionNotify; xevt2.xselection.display = xevt.xselectionrequest.display; xevt2.xselection.requestor = xevt.xselectionrequest.requestor; xevt2.xselection.selection = xevt.xselectionrequest.selection; xevt2.xselection.target = xevt.xselectionrequest.target; xevt2.xselection.time = xevt.xselectionrequest.time; xevt2.xselection.property = xevt.xselectionrequest.property; XSendEvent(p_display, xevt.xselectionrequest.requestor, False, NoEventMask, xevt2); } else if (xevt.xselectionrequest.target == UTF8_ATOM || xevt.xselectionrequest.target == XA_STRING) /*UTF-8 or ASCII requested*/ { /*Write the string TEST into the requestor*/ XChangeProperty(p_display, xevt.xselectionrequest.requestor, xevt.xselectionrequest.property, xevt.xselectionrequest.target, 8, PropModeReplace, (unsigned char *) TEST, 4); /*Notify the requestor we've finished*/ xevt2.xselection.type = SelectionNotify; xevt2.xselection.display = xevt.xselectionrequest.display; xevt2.xselection.requestor = xevt.xselectionrequest.requestor; xevt2.xselection.selection = xevt.xselectionrequest.selection; xevt2.xselection.target = xevt.xselectionrequest.target; xevt2.xselection.time = xevt.xselectionrequest.time; xevt2.xselection.property = xevt.xselectionrequest.property; XSendEvent(p_display, xevt.xselectionrequest.requestor, False, NoEventMask, xevt2); break; /*For debugging, prevents infinite loop*/ } else /*No supported request*/ {
Re: CLIPBOARD selection doesn't save content
On Sat, 2010-04-03 at 11:09 +0200, Quintus wrote: Hi, If you can, try it under gnome too That's quite easy to do - I'm already working under GNOME, I never tried KDE. Ok, I was tired, and misread Ubuntu Karmic for Kbuntu for some reason! as the last time I worked with any clipboard code, I found its clipboard manager more cooperative at saving non-standard data-types than when testing under KDE. Is text a non-standard data type? I can't believe this. No, but our app uses some, such as application/x-geda-schematic. This saves fine under Gnome, but appeared to have issues saving after program close under KDE last time someone tested it. Also, the clipboard manager in gnome will only request the clipboard contents and take over from my app when the app closes. We explicitly call gtk_clipboard_store() as we tear down the app. Sounds reasonable, but that's GTK-specific. Since I'm writing a general-purpose extension, it should work wherever X11 is installed. I looked at your code, and then tried to integrate this into my function by only using Xlib's functions. Its GTK specific of course.. our app uses GTK, you could look how GTK implemented these functions. I was vaguely curious, so I already posted some of that code. This is how it looks now: Sorry - the xlib code is too low level for me to follow easily - there is a reason I use GTK / GDK for this kind of stuff ;) Maybe I don't get the idea, but when I call XConvertSelection() I'm always sent a SelectionNotify event as a completion notify. Have I to react to this in any way besides checking for success? I don't think so, but then... What's achieved with the call? As far as I understood, you first check wheather there is a clipoard manager. If so, you change the CLIPBOARD property of my window to the list of supported targets. Why? In the call to XConvertSelection() you request that the CLIPBOARD_MANAGER selection is converted to SAVE_TARGETS which then is written to my window as the CLIPBOARD property. This doesn't make any sense to me, CLIPBOARD_MANAGER holds a text string, and not a list of targets and therefore doesn't request the clipboard manager to take responsibility for the CLIPBOARD selection. ...is at least my interpretation of your code correct? Not my code.. a paste from GTK/GDK's sources. I'm not that familiar with all the internal details. [snip] As you can see, I had to kill the process since it never completed the for loop. I'm quite sure I'm only missing a little detail, but what is it? And where does the MULTIPLE request suddenly come from? I think you need to take a look at the ICCCM spec: http://tronche.com/gui/x/icccm/sec-2.html Regards, -- Peter Clifton Electrical Engineering Division, Engineering Department, University of Cambridge, 9, JJ Thomson Avenue, Cambridge CB3 0FA Tel: +44 (0)7729 980173 - (No signal in the lab!) Tel: +44 (0)1223 748328 - (Shared lab phone, ask for me) ___ xorg@lists.freedesktop.org: X.Org support Archives: http://lists.freedesktop.org/archives/xorg Info: http://lists.freedesktop.org/mailman/listinfo/xorg
Re: CLIPBOARD selection doesn't save content
I think I'm facing a window manager problem. When I try to get into how the GTK functions solve the CLIPBOARD problem and even if I could implement this in my function: If somebody now tries this on a KDE distro like Kubuntu or openSUSE or on one with Xfce - that wouldn't work. It seems like I would have to implement that for every single window manager... If that's the case, I'll stop here. That would become unmaintainable for a single person. Am I correct with this thought? Marvin Peter Clifton schrieb: I think you need to take a look at the ICCCM spec: http://tronche.com/gui/x/icccm/sec-2.html Regards, ___ xorg@lists.freedesktop.org: X.Org support Archives: http://lists.freedesktop.org/archives/xorg Info: http://lists.freedesktop.org/mailman/listinfo/xorg
Re: CLIPBOARD selection doesn't save content
Quintus wrote: Now, I'm trying to implement writing, only for the CLIPBOARD selection, since that one's contents should persist across program death.I know, I have to acquire CLIPBOARD's ownership; afterwards the xclipboard process would send me a TARGETS request asking me what data I provide. I answer this with TARGETS, UTF8_STRING, XA_STRING and TIMESTAMP, which should cause xclipboard to ask me for UTF8_STRING or XA_STRING, but... It doesn't. Instead, if I try to paste the copied text into an application, my program gets a request from that application rather than from xclipboard. Further more, when my program finishes, the data is gone. So I suppose, something is wrong at my side. X itself doesn't have a persistent clipboard. If you want the clipboard contents to persist after the application terminates, a clipboard manager must be running. Clipboard managers are something of a mixed blessing, so not everyone uses one. Whether a clipboard manager is in use and its exact behaviour are dependent upon the desktop environment. All that your program can do is to implement the relevant protocols; the rest is beyond its control. Apart from implementing the CLIPBOARD selection, the application should implement the SAVE_TARGETS protocol for optimum behaviour with modern clipboard managers. For details, see: http://www.freedesktop.org/wiki/ClipboardManager If a compliant clipboard manager is running, this should cause it to take over the clipboard (ownership and contents) from the terminating process. Older clipboard managers (and clients) don't support the SAVE_TARGETS protocol, which means that the clipboard manager must retrieve the clipboard contents whenever the clipboard changes, which can be inefficient if the data is large and/or if there are many targets (some of which may be computationally expensive to generate). -- Glynn Clements gl...@gclements.plus.com ___ xorg@lists.freedesktop.org: X.Org support Archives: http://lists.freedesktop.org/archives/xorg Info: http://lists.freedesktop.org/mailman/listinfo/xorg
CLIPBOARD selection doesn't save content
Hi there, OK, this is kind of a longer story. Since ~4 weeks I'm trying to create a C extension for the Ruby programming language (I'm sure you don't have to know Ruby to answer this question, since it's almost C code) that allows to read from and write to the X clipboards. I've searched through the web many, many times, but wasn't able to find any reasonable example code on how to do this, and finally I looked into the source code of the xsel and xclip commands which helped me quite a lot. With this, and with further web research and search through the X11 specification and other documents, I was able to get the reading part up and running, for the PRIMARY, SECONDARY and CLIPBOARD selections. Now, I'm trying to implement writing, only for the CLIPBOARD selection, since that one's contents should persist across program death. I know, I have to acquire CLIPBOARD's ownership; afterwards the xclipboard process would send me a TARGETS request asking me what data I provide. I answer this with TARGETS, UTF8_STRING, XA_STRING and TIMESTAMP, which should cause xclipboard to ask me for UTF8_STRING or XA_STRING, but... It doesn't. Instead, if I try to paste the copied text into an application, my program gets a request from that application rather than from xclipboard. Further more, when my program finishes, the data is gone. So I suppose, something is wrong at my side. My system is an Ubuntu Karmic machine, uname -a: Linux ikarus 2.6.31-20-generic #58-Ubuntu SMP Fri Mar 12 04:38:19 UTC 2010 x86_64 GNU/Linux gcc --version: gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1 Copyright (C) 2009 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Here's my C function binding the write functionality to Ruby: - /* *call-seq: * Clipboard.write(clipboard, text) == nil * *Writes +text+ to the specified clipboard. */ static VALUE m_write(VALUE self, VALUE rclipboard, VALUE rtext) /*VALUE is a Ruby object*/ { Display * p_display; Window win; XEvent xevt, xevt2; /*xevt2 is our response*/ Atom targets[4]; /*As long as we're debugging, ignore the parameters*/ /*Open default display*/ p_display = XOpenDisplay(NULL); /*Let Ruby handle protocol errors*/ XSetErrorHandler(handle_x_errors); /*This are the TARGETS we support*/ targets[0] = XInternAtom(p_display, TARGETS, True); targets[1] = UTF8_ATOM; targets[2] = XA_STRING; targets[3] = XInternAtom(p_display, TIMESTAMP, True); /*TODO: Implement this request*/ /*Output some useful information*/ printf(PID: %i\n, getpid()); printf(Owner of CLIPBOARD: %lu\n, XGetSelectionOwner(p_display, CLIPBOARD_ATOM)); /*Create a window for copying into CLIPBOARD*/ win = CREATE_REQUESTOR_WIN; /*Get control of the CLIPBOARD*/ XSetSelectionOwner(p_display, CLIPBOARD_ATOM, win, CurrentTime); for (;;) { XNextEvent(p_display, xevt); printf(Event received; Requested target: %s\n, XGetAtomName(p_display, xevt.xselectionrequest.target)); printf(Requestor: %lu\n, xevt.xselectionrequest.requestor); if (xevt.type == SelectionRequest) /*selection-related event*/ { if (xevt.xselectionrequest.target == XInternAtom(p_display, TARGETS, True)) /*TARGETS information requested*/ { /*Write supported TARGETS into the requestor*/ XChangeProperty(p_display, xevt.xselectionrequest.requestor, xevt.xselectionrequest.property, XA_ATOM, 32, PropModeReplace, (unsigned char *) targets, 4); /*Notify the requestor we have set its requested property*/ xevt2.xselection.type = SelectionNotify; xevt2.xselection.display = xevt.xselectionrequest.display; xevt2.xselection.requestor = xevt.xselectionrequest.requestor; xevt2.xselection.selection = xevt.xselectionrequest.selection; xevt2.xselection.target = xevt.xselectionrequest.target; xevt2.xselection.time = xevt.xselectionrequest.time; xevt2.xselection.property = xevt.xselectionrequest.property; XSendEvent(p_display, xevt.xselectionrequest.requestor, False, NoEventMask, xevt2); } else if (xevt.xselectionrequest.target == UTF8_ATOM || xevt.xselectionrequest.target == XA_STRING) /*UTF-8 or ASCII requested*/ { /*Write the string TEST into the requestor*/ XChangeProperty(p_display, xevt.xselectionrequest.requestor, xevt.xselectionrequest.property, xevt.xselectionrequest.target, 8, PropModeReplace, (unsigned char *) TEST, 4); /*Notify the requestor we've finished*/ xevt2.xselection.type = SelectionNotify; xevt2.xselection.display = xevt.xselectionrequest.display; xevt2.xselection.requestor = xevt.xselectionrequest.requestor; xevt2.xselection.selection = xevt.xselectionrequest.selection; xevt2.xselection.target = xevt.xselectionrequest.target; xevt2.xselection.time =