Re: Gtk Drag & Drop changes




> On 13 Jan 1998, Owen Taylor wrote:
> 
> > * http://www.igpm.rwth-aachen.de/~albrecht/hungry.html
> > 
> >  "Inside Lesstif" book. By far the best description of Motif DND
> >  available, though still incomplete in regards to the Pre-register
> >  variant.
> 
> ftp://ftp.red-bean.com/ has a good one on official Motif, somewhere. It's
> the one I read, anyways.

ftp://ftp.red-bean.com/pub/teak/, if anybody is interested. (It is
in the Motif FAQ). But "sketchy overview" was more my opinion than
"good one" when I looked at it. The Lesstif chapter is _much_ better.
 
> > Two major problems with Xde:
> > 
> > * There is no way of telling whether an application supports the Xde
> > protocol or not. (Except for seeing if it responds to messages).  This
> > makes it impossible to properly support this protocol on the drag end
> > along with other protocols. (Xdnd sets a Xdnd aware property on the
> > window, and Motif does something similar.)
> 
> What we can do is just require that _XDE_TYPELIST be set, even if it is
> zero-length.

That would work. 

> > * Data is not transferred via the selection, but by setting
> > a property on the source window.
> 
> I see that as an advantage. From what I understand, using
> XConvertSelection (or whatever Gtk wrapper you have) would make it
> impossible to differentiate between a paste and a drop.

Nope. There are multiple selections. A normal X Button-2 "paste"
is a request for the PRIMARY selection. A real paste is a request
for the CLIPBOARD selection. A drop would be a request for 
a different selection. (Xdnd uses XdndSelection). (Selections
are identified by atoms).
 
> >   Property name = atom for drag type (!)
> >   Property type = XA_PRIMARY         (!!!!!!!)
> 
> With this scheme, you can store the same data in different formats on the
> window, and when a drop target asks for it, it's already there.

OK, but setting the type to PRIMARY is a bit odd. But if you use
selections, you don't have to store the data in all the types.
You just write code that supplies the data in the various types,
set up your handlers and let the selection code handle the rest.
 
> > If nothing else, using the selection would keep this type of
> > odd choice from being made. But more also,
> > 
> >   Using the selection gives the possibility of using INCR style
> >   transfers (required by the ICCCM). Otherwise it may be
> >   impossible to transfer large amounts of data across a server 
> >   with little memory.
> 
> I discussed this with Marc & Mike & Carsten (the RHAD Labs team) and
> probably what we will want to do is not use INCR at all, just define
> different possible methods of transfer, and let the applications negotiate
> them. X is not meant to be high performance data transfer anyways - if
> you're transferring a huge file, negotiate a direct connect...

And modify your protocol to do so while your at it... With selections,
it just works. (Probably a bit slowly, but I suspect not by more
than a factor of 2 or so).

> > * There is no way of telling if a drag operation finished successfully.
> > (In Xdnd, the target justs asks for the selection.  One could assume
> > that if the selection transfer finished successfully, then that was the
> > end of the drop. But it might make sense to ask for multiple targets.
> > For Xde, the situation is even worse.  The source just has to keep the
> > data in the window property until things are deleted) 
> 
> You *always* assume that if the application says that it will accept the
> drop, and no X errors ensue from sending the drop event, that the drop
> happened. This is to eliminate a round trips.

User grabs some text and drags it to another application. After the
drop event, but before the data is transferred, user quickly grabs
some different text and drags it to a different application. Window
property is replaced, target 1 gets the wrong data.

Yes, the protocol may work most of the time, but it would be nice
if it was robust against these type of things. An extra message
isn't all that bad, considering the number that were sent during
the drag.

(Speaking of that, the XDE protocol suffers from event-bombing
in the case of fast source-server connection, slow source-client
connection, since for motion outside the drag zone, XDE_ENTER
events are continually sent but not echoed.)

> BTW Gtk needs to handle X errors a lot better. Would be nice to have a
> stack of error handlers to push and pop on, or perhaps support for a
> try/catch type of thing...

Yes. There is some rudimentary support in there now. For example
gdk_atom_name is implemented as:

  gdk_error_warnings = 0;
  t = XGetAtomName (gdk_display, atom);
  gdk_error_warnings = 1;

  if (gdk_error_code == -1)
    {
      return NULL;
    }
  else
    {
     ...
    }

There are a lot of places in GDK where this (or something better)
should be used, but isn't.

> > This means:
> > 
> >   If a destructive operation is being performed (Possible with
> >   Xde, maybe possible with Xdnd) data could be lost since there
> >   is no confirmation of success/failure.
> > 
> >   Feedback animation isn't possible. (Motif has snapback for
> >   failure (nice) and melting for success (for me, highly 
> >   disturbing, for some reason)
> 
> You know that it happened, so you can do your animation.

It's not a big deal as long as the applications are robust. If
they aren't then explicit confirmation makes things easier
on the user. But I think the scenario above and variants are
a more compelling reason.

> > * Data types are represented by MIME types, _interned as X atoms_.
> > While this makes sense in some ways, interning arbitrary strings
> > as atoms is certainly against the spirit of the ICCCM. The alternate
> > approach is to use the standard ICCCM targets, suitably enhanced.
> > (Motif does this, so a translation table would be necessary
> > when taking the first approach.)
> > 
> > I like the MIME types better than the ICCCM approach, really,
> > _except_ for the fact that we need to use the ICCCM approach
> > when doing selections, clipboard cut-and-paste, and Motif DND.
> 
> Well, when in Rome, do as the Romans do. We can find some MIME type ->
> ICCCM crap name converter for use with Motif etc.

If we do this, then we probably should change the selection interface
as well so that target names are always specified as mime types.
(Caching the atoms while we're at it would also be nice)

> > * The methods of specifying the operation are weak in both 
> > protocols. (By comparison, the operation move/copy/link is
> > negotatiated separately in Motif dnd.)
> > 
> >   Xde by default copies, but can specify linking by using
> >   a target URL:text/plain, etc. (And then passing the URL
> >   as the contents of the URL). The target application can
> >   also request that the operation should be destructive by
> >   setting a flag.
> 
> Right, but that lets you specify move/copy/link - what's the problem?
>
> >   Xdnd copies, but can also specify "mime types"
> >   url/url (target decides?) url/copy url/move and url/delete.
> >   (No other mime type is specified for these)
> > 
> > Both of the above approaches suffer badly from the fact that
> > the operation is usually partially chosen from the _source_ side.
> > (I.e., in Motif, it is specified by holding down modifier keys
> > while dragging - and therefore the user can change the operation
> > during the drag, necessitating a special client message.)
> 
> I don't see how it suffers, especially seeing as the operation is chosen
> by the target side (it returns that destructive vs. non-destructive in its
> reply message). If the source wishes to delete the original data source
> after the target has used it, that's its own business - the flags field is
> just so that the destination can "force" the source to delete it (or not),
> e.g. if you're dragging to a trash can you want to delete it no matter
> what the user specifies, whereas if you're dragging from the "undelete"
> area of the trash can, you may not want to remove it from the trash can no
> matter what.

Say we have a File manager where dropping text onto the "Perl" icon
means "run the script". User grabs some text in an editor, holding
down the Ctrl key to force a move, and drops it on the "Perl" icon.
Script runs, text vanishes.

Now you might argue that this is the right Unixy behavior here.
(User really wanted to run the script once and never see it again.)

But in general, I don't think this is a friendly way of doing things.
The target needs to have some way of specifying whether a "Move"
operation is possible. One could come up with examples where it
makes even less sense.

Motif actually implements changing the drag icon to indicate to
the user what operation is going to take place.

> > * For Motif DND, the user can request help by pressing F1 over
> > a drop site while dragging. This isn't possible for either
> > Xdnd or Xde.
> 
> We can add it easily, that's what the protocol_version field is for.
> (Actually, it's easier than that. Just set a property _XDE_DROPHELP)
> 
> Honestly, I think this is bloat.

Probably - I tried to be complete in this list, rather than listing
exactly what I thought should be put in or not.

> > * The client messages don't pass timestamps for the triggering
> > mouse events. This probably will lead to some race conditions
> > under high load.
> 
> This needs to be looked into a bit, but I'm pretty sure that almost all
> events of
> time

??? 

Not sure what you meant to say. But it isn't worth worrying about too
much, probably. The rest of GTK is pretty casual about time
anyways. (Problem is that once mouse events are translated into
i.e., button events, the timestamp is gone).

> >  - Can an application decide whether to accept or reject a drag based
> >    on the dynamic contents of the drag. (All the protocols support this, 
> >    but it makes the API considerably more complicated)
> 
> Our API allows for this theoretically, already. I just didn't support it
> for drags from Gtk apps, yet. (It is supported for drops to Gtk apps).

But only at the time of the _XDE_DROP message. The application can't
decide earlier and relay that information back to the source (So
it can change the drop icon) - though the protocol allows it.

> >  - Should we support full Motif style operation selection, or just
> >    use something simpler, and map that onto a portion of the Motif
> >    protocol.
> > 
> >  - Will we support drop sites that are only a portion of the widget?
> >    Multiple drop sites per widget?
> 
> It's possible, I just didn't feel like coding it. The support for it is
> there for drags, though (I think).

Sort of. The code I mentioned a while ago is still broken:

	      /* Handle all that dropzone stuff - thanks John ;-) */
	      if(dnd_drag_target != None
		 && IS_IN_ZONE(dnd_drag_oldpos.x, dnd_drag_oldpos.y)
		 && !IS_IN_ZONE(xevent->xmotion.x_root,
				xevent->xmotion.y_root))
		{
		  /* We were in the drop zone and moved out */
		  dnd_drag_target = None;
		  gdk_dnd_drag_leave(curwin);
		}
	      else
		{
		  /* We were outside drop zone but in the window
		     - have to send enter events */
		  gdk_dnd_drag_enter(curwin);
		  dnd_drag_curwin = curwin;
		  dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
		  dnd_drag_target = None;
		}

This breaks in the case where we go from IN_ZONE to IN_ZONE. If
you are done working on DND for now. I suppose I could try
to fix this, the LeaveNotify and anything else I find. But I'll
just be guessing as to your intentions for the protocol. 
 
> > - The data in the Response event needs to be correctly handled
> > in gdk_event_copy, etc.
> 
> Hmm, yes, also need to define a standard gdk_event_free thing that happens
> after all event handlers are called.

Actually, there is already is a gdk_event_free that happpens after
all event handlers are called. Literally. (But only since about
a month ago).

> > - We need to find a better way of identifying windows than querying 
> > the tree on each motion event. (I'll take a look at that further)
> 
> I've looked for it. There isn't any way AFAIK, but perhaps the other Xlib
> experts out there can find one.

Motif has a bit of an advantage in that the protocol only deals with the 
toplevel windows. That way you can get away with a single
XQueryPointer. (Which you are probably doing already, if you are
using MotionHints). But perhaps there isn't a better way for arbitrary
windows.

But the fact we are doing all these server calls makes overhead for
confirmation pretty small overhead indeed. (Though it could still be
argued that it reduces complexity to omit it.)

> > - The current code needs a window for the drop zone. (The protocol does
> > not.) One should be able to drop on pixmaps, etc. without windows.  The
> > dropzone should be on a per-widget basis. (Do we need multiple dropzones
> > per widget?)
> 
> We can do this, this is the "drop sites" feature mentioned above.
> 
> > - As a stopgap-measure/fallback for shaped window dragging, we
> > need to create some pixmap cursors for DND. The default cursor
> > font cursors are completely inadequate.
> 
> No, we need to implement a way for the application to tell Gdk what cursor
> to use whenever a drag starts up. It shouldn't be hard either, just modify
> your drag_begin signal handler to do a
> gdk_set_dnd_default_cursor_to_this()

It might be nice to have a better default cursor as well...
 
Regards,
                                        Owen



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]