Re: XForms: X Selections & xforms

Robert S. Mallozzi (mallors@crazyhorse.msfc.nasa.gov)
Sun, 17 Aug 1997 11:00:43 -0500 (CDT)

To subscribers of the xforms list from "Robert S. Mallozzi" <mallors@crazyhorse.msfc.nasa.gov> :

On 16 Aug, Dr. T.C. Zhao wrote:
>
> I don't know how you handles the selection events (using
> the unhandled XEvent leakage from from fl_do_forms ?), if
> this is the case, I could let the selection event
> leak thru fl_do_forms as before when xforms don't
> know what do to with it.
>

If you are not interested in X Selections, don't bother reading this
rather long message.

The code below shows how I was handling the X CLIPBOARD prior to version
0.87 of xforms.

The selection_handler() callback is set with fl_set_object_prehandler()
for a menu on my main form. On the FL_RELEASE event, I grap ownership of
CLIPBOARD, and set the data on the unhandled (by xforms) XSelectionRequestEvent
event. Note that CLIPBOARD is not a predefined atom (in Xatom.h), so you
have to XInternAtom() somewhere - I did it in main().

Anyway, in v0.87, the XSelectionRequestEvent is now handled by xforms,
which causes problems in fl_handle_clipboard() since we did not use
fl_stuff_clipboard() to grab ownership (as shown in clipboard.c, thanks TC)

Perhaps I am being picky, or in fact don't know what I'm talking about :-),
but I think xforms is confusingly mixing the atoms CLIPBOARD and XA_PRIMARY.
The new xforms functions set the XA_PRIMARY type, *not* the CLIPBOARD type.
You can verify this by running the application xclipboard while you run your
xforms code. You will see that xforms does not copy data to CLIPBOARD, but
rather to XA_PRIMARY. The code below happens to use CLIPBOARD, but could be
changed to XA_PRIMARY easily. So, I think the fl_*_clipboard() functions
are misnamed - maybe they should be fl_*_xa_primary(), and maybe even
change the fl_*_clipboard() to use CLIPBOARD ? Even add fl_*_xa_secondary(),
what the heck ;-)

There seems to be a problem with the way selections are handled now.
I believe an xforms application can only use XA_PRIMARY.
There appears to be no way to use CLIPBOARD, XA_SECONDARY, or any other atom.
That probably is not going to work. Perhaps an FL_SELECTION event should be
added so that you can catch it in a prehandler, like in the code below.

Lastly, a question for TC:

In clipboard.c, you make the call

XSetSelectionOwner(fl_display, XA_PRIMARY, win, CurrentTime);

But from the O'Reilly Xlib Programming Manual, 3rd ed., pg 429,

"The time used [for XSetSelectionOwner] should be from the event
that triggered the bid to own the selection (not CurrentTime)
because of race conditions that can otherwise occur."

That is why I used ((XButtonEvent *)xevent)->time below, and not CurrentTime.
Is it not correct?

Also, I noticed that in the fl_stuff_clipboard call(), one is *required* to
provide an FL_LOSE_SELECTION_CB callback, even if there is nothing to be done
when the selection is lost. I tried to use a NULL pointer, but got a seg fault.
It would be nice to be able to specify that no callback is required.

-bob

PS Last night my cat came home reeking of catnip and gin - what's up
with that?!!

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
** A prehandler to catch X Selection events. Will not work with xforms 0.87,
** which does not put a Selection event under FL_OTHER.
**
** Robert.Mallozzi@msfc.nasa.gov, 1997 August
*/

int selection_handler(FL_OBJECT *ob, int event,
FL_Coord mx, FL_Coord my, int key, void *xev)
{

char *aString;
Window owner;
Atom requestType;
int status;

Atom ret_atom;
int ret_format;
unsigned long ret_length, ret_remaining;
unsigned char *ret_data;

XSelectionRequestEvent *requestEv;
XSelectionEvent localEv;
XSelectionEvent *sendEv;

/*
** The cast XEvent
*/
XEvent *xevent;
xevent = (XEvent *)xev;

switch (fl_get_menu(ob)) {

/* Set the CLIPBOARD data (char *aString) here */
}

switch (event) {

case FL_RELEASE:

owner = FL_ObjWin(ob);

XSetSelectionOwner(fl_get_display(), CLIPBOARD,
owner, ((XButtonEvent *)xevent)->time);

if (XGetSelectionOwner(fl_get_display(), CLIPBOARD) != owner)
printf("Failed to grab CLIPBOARD!\n");

break;

/* Here we need an FL_SELECTION I guess... */

case FL_OTHER:

if (((XSelectionRequestEvent *) xevent)->type == SelectionRequest) {

requestEv = (XSelectionRequestEvent *) xevent;

if (requestEv->target == XA_STRING) {

requestType = CLIPBOARD;

/*
** Set the window property to the string corresponding to the
** menu item that was selected. Check to make sure property
** was set.
*/
status = XChangeProperty(fl_get_display(),
requestEv->requestor, CLIPBOARD,
requestEv->target, 8, PropModeReplace,
aString, (int) strlen(aString) + 1);

status = XGetWindowProperty(fl_get_display(),
requestEv->requestor, CLIPBOARD,
0L, strlen(aString) + 1, False, AnyPropertyType,
&ret_atom, &ret_format, &ret_length,
&ret_remaining, &ret_data);

if (status != Success)
printf("XGetWindowProperty failed in SelectionRequest\n");
}
else {
requestType = None;
}


/*
** Data are ready; tell the requestor
*/
sendEv = &localEv;
sendEv->type = SelectionNotify;
sendEv->send_event = True;
sendEv->display = fl_get_display();
sendEv->requestor = requestEv->requestor;
sendEv->selection = requestEv->selection;
sendEv->target = requestEv->target;
sendEv->property = requestType;
sendEv->time = requestEv->time;

status = XSendEvent(fl_get_display(), requestEv->requestor,
False, 0L, (XEvent *)sendEv);

if ((status == BadValue) || (status == BadWindow))
printf("XSendEvent failed!\n");

} /* endif SelectionRequest event */

break;

default: /* Ignore all other events */
break;
}

return 0;

}

-- 
Dr. Robert S. Mallozzi
University of Alabama in Huntsville
http://cspar.uah.edu/~mallozzir/

_________________________________________________ To unsubscribe, send the message "unsubscribe" to xforms-request@bob.usuf2.usuhs.mil or see http://bob.usuf2.usuhs.mil/mailserv/xforms.html Xforms Home Page: http://bragg.phys.uwm.edu/xforms List Archive: http://bob.usuf2.usuhs.mil/mailserv/list-archives/