[comp.windows.open-look] xview selections and epoch/emacs

kramer@ai.toronto.edu ("Bryan M. Kramer") (12/13/90)

Does anyone have mechanisms that will tie xview/openwindows
selections to epoch selections. I'd really like to move
both ways, i.e. from cmdtool or mailtool to epoch and vice
versa. 

While we're on the topic, the ability to drag files from
the file manager into epoch would be very nice. Has anyone
tried this?


 Bryan M. Kramer	- 416-978-7330 -
 Department of Computer Science, University of Toronto
 Toronto, ON      M5S 1A4

rberlin@eng.sun.com (Rich Berlin) (12/13/90)

In article <90Dec12.131353est.133326@wotan.ai.toronto.edu>, kramer@ai.toronto.edu ("Bryan M. Kramer") writes:
|> 
|> Does anyone have mechanisms that will tie xview/openwindows
|> selections to epoch selections. I'd really like to move
|> both ways, i.e. from cmdtool or mailtool to epoch and vice
|> versa. 
|> 
|> While we're on the topic, the ability to drag files from
|> the file manager into epoch would be very nice. Has anyone
|> tried this?
|> 
|> 
|>  Bryan M. Kramer	- 416-978-7330 -
|>  Department of Computer Science, University of Toronto
|>  Toronto, ON      M5S 1A4

I made an attempt to do this, so let me give you a rundown on what I discovered.
There is no selection handling in epoch (as of 3.2).  I have heard it might be
in the next version, but I don't know exactly what they're planning.  The stuff
normally used to handle selections is XGetSelectionOwner, XSetSelectionOwner,
XConvertSelection, and of course the code to handle the 3 selection events.

A lot more functionality would be needed to do the mouse properly; for example,
you need to be able to query keyboard state and catch key "up" events in order to
do secondary selection.  To make the select operation match OpenWindows'
behavior, you need to detect double-, triple-, and quadruple-clicks.  And
the handling of properties would have to be extended to allow you to set the
type of a property to something other than INTEGER or STRING; at the very
least, LENGTH must be supported as a type.

But I don't think that's all there is to it.  There's a technique that XView
clients use to "share" the up-event when doing secondary selection, and I
haven't been able to figure out what it is, much less what it would take to do
it in Xlib.

Sigh.


If it's any consolation, the filemgr drop is pretty easy:
When the filemgr drops onto a window, it asserts ownership of the PRIMARY
selection and then sends a ClientMessage event (with the name XV_DO_DRAG_LOAD)
to the window that is to receive the drop.  To process it, you need a function
which calls XConvertSelection.  I have appended such a function definition,
along with elisp code I wrote to catch the drop.  You'll need to link the
function into epoch and add a call in emacs.c in order to get this to work.
Of course, when/if the folks at uiuc come out with a version that handles
selections, you should use it instead!


-- Rich


Byte-compile this and load it in your .emacs
----------begin filemgr.el
;;
;; Code to make epoch understand the filemanager drop.
;; This requires the function epoch::convert-selection.
;;
;; Author: Richard Berlin
;; 11/13/90
;;

(defun filemgr::handle-drag-load (type actual-event scr)
  (epoch::convert-selection "PRIMARY" "STRING" "FILEMGR_DROP"))

(defun filemgr::handle-drop (prop p scr)
  (epoch::select-screen scr)
  ;; Multiple files are possible.  A list is separated by tabs.
  (let (pos str (numfiles 1)  (new (epoch::get-property p)))
    (while (setq pos (string-match "\t" new))
      (setq numfiles (1+ numfiles))
      (setq str (substring new 0 pos))
      (find-file str)
      (setq new (substring new (1+ pos))))
    (find-file new)
    (if (= 1 numfiles)
	(message (concat "Visiting file: " new))
      (message "%d files read." numfiles))))

(defun filemgr::init ()
  (push-property "FILEMGR_DROP" 'filemgr::handle-drop)
  (push-message "XV_DO_DRAG_LOAD" 'filemgr::handle-drag-load))

(epoch-add-setup-hook 'filemgr::init)

----------end filemgr.el

Put this in epoch-3.2/src, add it to the list of files in ymakefile, and edit
emacs.c, adding a call to syms_of_convertselection() beneath syms_of_xfns().
----------begin convertselection.c

/* 
 * Code for selection handling, to be used with Epoch 3.2
 * Author: Richard Berlin
 */

#include <stdio.h>
#undef NULL

#include <signal.h>
#include <sys/ioctl.h>
/* load sys/types.h, but make sure we haven't done it twice */
#ifndef makedev
#include <sys/types.h>
#endif

#include "config.h"
#include "lisp.h"
#include "x11term.h"
#include "xresource.h"
#include "screen.h"
#include "screenX.h"

Lisp_Object Qx_screen_p;

DEFUN ("epoch::convert-selection", Fx_convert_selection,
       Sx_convert_selection, 3, 5, 0,
"Convert the desired SELECTION to FORMAT and transfer it as the given PROPERTY.\n\
You may optionally specify the SCREEN on which the property should be\n\
stored and the TIME at which the transfer should take place.\n\
\n\
SELECTION and PROPERTY are strings, i.e. not the X atoms but their names.\n\
FORMAT is a string and may be one of: {XA_STRING, XA_FILE_NAME}.")
       (sel_name, format, property, screen, time)
       Lisp_Object sel_name, format, property, screen, time;
{
    Display *dpy = XXSCREEN(mini_root->x11)->display;
    BLOCK_INPUT_DECLARE();
    int plane = XXSCREEN(mini_root->x11)->plane;
    Atom seln, targ, prop;
    Window requestor;
    int grab_time;
    CHECK_STRING(sel_name, 0);
    CHECK_STRING(format, 0);
    CHECK_STRING(property, 0);
    if (EQ(Qt, screen))
	requestor = None;
    else
    {
	if (EQ(Qnil, screen))
	    screen = Fcurrent_screen();
	screen = find_block(screen);
	if (EQ(Qnil, screen))
	    screen = wrong_type_argument (Qx_screen_p, (screen));
	requestor = XXSCREEN(XROOT(screen)->x11)->xid;
    }

    if (EQ(Qnil, time))
	grab_time = CurrentTime;
    else
    {
	CHECK_NUMBER(time, 0)
	grab_time = XINT(time);
    }

    BLOCK_INPUT ();
    seln = XInternAtom(dpy, XSTRING(sel_name)->data, False);
    targ = XInternAtom(dpy, XSTRING(format)->data, False);
    prop = XInternAtom(dpy, XSTRING(property)->data, False);
    {
	XConvertSelection(dpy, seln, targ, prop, requestor, grab_time);
	XFlush(dpy);
    }
    return Qnil;
}

syms_of_convertselection()
{
    staticpro(&Qx_screen_p);
    Qx_screen_p = intern("epoch::screen-p");

    defsubr(&Sx_convert_selection);
}
---------- end convertselection.c