[comp.windows.open-look] ICC with OpenLook Desktop print tool

kevin@drogges.tti.com (04/04/91)

Hi -
Although this is primarily an OpenLook/XView question, I am circulating it
to c.w.x hoping to get some illumination on InterClientCommunications.

Does anyone have any idea as to what the protocol sequence is to send 
a filename for printing to the Sun Desktop "print tool" from a client OTHER
than OpenLook's "file manager"?

The sequence of events that I see (while running "xscope") that are generated
by file manager are:

1.   filemgr generates an "InternAtom" request for name: "FVDROP670614812"
     (this happens when I start "dragging" a filename glyph). returns 
     Atom = 0xb6;

2.   filemgr gets a set of "FocusOut"  events.

3.   filemgr does a "ChangeProperty" request to  set Atom (0xb6) to  the 
     compleat pathname/filename string "/usr/kevin/abc.dat"

4.   filemgr does a "GetSelectionOwner" request to (i assume) find out
     what window "owns" the glyph.

5.   filemgr now generates another "InternAtom" request for name: 
     "SELECTION_PROPERTY0". returns Atom = 0x76.   (---IS THIS EVEN 
     RELATED???---)

6.   filemgr does a "ConvertSelection" request on Atom 0x75 to 
     to type 0x76 ("_SUN_SELN_YIELD") (AGAIN; related??)

7.   filemgr now generates ANOTHER "InternAtom" request for name:
     "_SUN_SELN_END_REQUEST". returns Atom = 0x7ce;

8.   filemgr does a "GetSelectionOwner" request to find the window id
     of the owner of "XA_PRIMARY"  (why? i have NO idea)

9.   filemgr now generates "InternAtom" for name: "XV_DO_DRAG_LOAD".
     server returns 0xb2;

10.  filemgr does a "SendEvent" call, using the win id of the print too
     as the destination in the XClientMessage. The data sent is:

	event->ie_xevent->xclient.data.l[0] = protocol (=0)
        event->ie_xevent->xclient.data.l[1] = timestamp
        event->ie_xevent->xclient.data.l[2] = serial no
        event->ie_xevent->xclient.data.l[3] = win id
        event->ie_xevent->xclient.data.l[4] = Atom # (XV_DO_DRAG_LOAD, = 0xb6


...And at THIS point, "Printtool" magically starts printing the file.


whew!   Now MY question:

   does anybody know how I can DUPLICATE" the drag-n-drop protocol sequence above 
   without actually *DOING* a drag-n-drop, such that printtool will act on the 
   XClientMessage?
   

   Angst in Advance:
--
Kevin Carothers   {csun,psivax,philabs,retix}!ttidca!kevin

leif@winsoft.se (Leif Samuelsson) (04/07/91)

In article <25276@ttidca.TTI.COM> kevin@drogges.tti.com writes:
>whew!   Now MY question:
>
>   does anybody know how I can DUPLICATE" the drag-n-drop protocol sequence above 
>   without actually *DOING* a drag-n-drop, such that printtool will act on the 
>   XClientMessage?

I had the same need with PageView a while back and came up with the
following program. It sends an ACTION_DRAG_LOAD event to the receiving
application and passes on a filename.  It is a bit kludgey and will
most definitely not work on any version of OpenWindows other than 2.0.

It can be used with other applications as well, the problem is just
to find out which subwindow to send the message to. I suggest using
xlswins for browsing.

Does anyone know of an easier way of finding the id of the receiving window?


----
Leif Samuelsson

Winsoft Data AB			Phone: +46 8 7301240
Lidgatan 18			Fax:   +46 8 7303102
S-171 58 SOLNA			E-mail: leif@winsoft.se
Sweden

----Cut---here----
/*
 *	dragload.c  --  Send an ACTION_DRAG_LOAD event to predefined application
 *
 *	Only works with OpenWindows 2.0
 *
 *	Compile with:

cc -o dragload dragload.c -lxview -lolgx -lX11

 */


#include <xview/xview.h>
#include <xview/seln.h>

enum apptype { PageView, PrintTool };

enum apptype app = PrintTool;

char	*filename;

static Seln_result	request_proc();
static Window		get_child_by_name(), get_nth_child();

main(argc, argv)
	int argc;
	char *argv[];
{
    Frame	frame;
    Window	window = 0;
    Window	root, w;
    Display	*dpy;
    Seln_client	client;
    int		data[4];

    if (argc != 2) {
	fprintf(stderr, "Usage: %s filename\n", argv[0]);
    	exit(1);
    }

    filename = argv[1];

    /* Create a frame just to make XView happy */
    frame = xv_create(0, FRAME, 0);

    dpy = (Display *)xv_get(frame, XV_DISPLAY);
    root = (Window)xv_get(xv_get(frame, XV_ROOT), XV_XID);

    /* Now find the window to send the event to */
    switch (app) {

      case PageView:
	window = get_child_by_name(dpy, root, "PageView");

	if (window)
	  window = get_nth_child(dpy, window, 1);
	if (window)
	  window = get_nth_child(dpy, window, 0);
	if (window)
	  window = get_nth_child(dpy, window, 0);
	break;

      case PrintTool:
	window = get_child_by_name(dpy, root, "Print Tool");

	if (window)
	  window = get_nth_child(dpy, window, 0);
	break;

      default:
	fprintf(stderr, "%s: Unknown application.\n", argv[0]);
	exit(1);
    }	

    if (!window) {
	fprintf(stderr, "%s: Can not talk to application.\n", argv[0]);
	exit(1);
    }


    /* Set up selection service */
    client = seln_create(0, request_proc, &client);
    seln_acquire(client, SELN_PRIMARY);

    /* Send the event */
    data[0] = window;
    data[3] = xv_get(frame, XV_XID);
    xv_send_message(frame, window, "XV_DO_DRAG_LOAD", 32, data, 16);
    notify_start();
}              



static Window
get_child_by_name(dpy, w, name)		/* Recursively search tree for win by name */
     Display	*dpy;
     Window	w;
     char	*name;
{
    Window	root, parent;
    Window	*children;
    int		i, nchildren;
    char	*win_name;

    XQueryTree(dpy, w, &root, &parent, &children, &nchildren);
    for (i = 0; i < nchildren; i++) {
	w = children[i];
	if (XFetchName(dpy, w, &win_name)) {
	    if (!strcmp(win_name, name)) {
		XFree(win_name);
		XFree(children);
		return (w);
	    }
	    XFree(win_name);
	}
	w = get_child_by_name(dpy, w, name);	/* recursive call */
	if (w) {
	    XFree(children);
	    return (w);
	}
    }
    XFree(children);
    return ((Window)NULL);
}


static Window
get_nth_child(dpy, w, i)		/* Return child i of window w */
     Display	*dpy;
     Window	w;
     int	i;
{
    Window	root, parent;
    Window	*children;
    int		nchildren;

    XQueryTree(dpy, w, &root, &parent, &children, &nchildren);

    if (nchildren > i)
	w = children[i];
    else
	w = (Window)NULL;

    XFree(children);

    return (w);
}


static Seln_result
request_proc(attr, context, max_length)
     int attr;
     Seln_replier_data *context;
     int max_length;
{
    int i;
    static char buf[256];
    char *p;

    switch (attr) {
      case SELN_REQ_BYTESIZE:
        *context->response_pointer++ = (char *)strlen(filename);
	return SELN_SUCCESS;

      case SELN_REQ_CONTENTS_ASCII:
	strcpy(context->response_pointer, filename);
	context->response_pointer += strlen(filename) / 4;
	if ((strlen(filename) % 4) > 0) context->response_pointer++;
	*context->response_pointer++ = 0;       /* Null terminate value */
	return SELN_SUCCESS;

      case SELN_REQ_END_REQUEST:
	notify_stop();
	return SELN_FAILED;

      case SELN_REQ_IS_READONLY:
	return SELN_FAILED;

      default:
	printf("request_proc 0x%x  0x%x %d\n", attr, context, max_length);
	fflush(stdout);
	return SELN_FAILED;
    }
    /*NOTREACHED*/
}