Selection handling changes




As some of you know, I've been working recently on re-doing
drag-and-drop handling for GTK+. The interfaces for that are pretty
closely related to that for selections, and I've become a little
disatisfied with the gtkselection interfaces I originally came up
with. So, rather than making DND conform to those interfaces, I'm
proposing changing the selection interfaces a bit.

Unfortunately, these are backwards-incompatible changes, but they are
fairly easy to fix up, and I don't think selection use is all that
extensive yet.

The change consists of dumping the

  gtk_selection_add_handler()

system in favor of registering a list of targets that the widget can
supply for a selection and then having a "selection_get" signal which
is called to get the contents of the selection.

This seemed preferable to me for several reasons:

 - The handlers added a bunch of complexity - where
   possible I think it is better to use signals
   for handlers.

 - I've never seen code that actually sets up
   multiple different handler functions for different
   selections and targets, so there  shouldn't be much 
   disadvantage of simply routing things through a single signal.

The API, as it now stands is:

struct _GtkTargetEntry {
  gchar *target;
  guint  info;
};

void gtk_selection_add_target (GtkWidget           *widget, 
			       GdkAtom              selection,
			       GdkAtom              target,
			       guint                info);
void gtk_selection_add_targets (GtkWidget           *widget, 
				GdkAtom              selection,
				GtkTargetEntry      *targets,
				guint                ntargets);

 "selection_get"           (GtkWidget          *widget,
			    GtkSelectionData   *selection_data,
			    guint               info,
			    guint               time);

The one thing that needs explaining here is the mysterious "guint
info" parameter. The point of this parameter is to make things a bit
easier to avoid gdk_atom_intern()'s all over the place.

When adding a target to the list of targets for a selection, one
supplies a guint that is later returned to you when the
"selection_get" handler is called for that target.

This allows, for instance, things like case statements to be used:

enum {
  STRING,
  TEXT,
  COMPOUND_TEXT
}

  static GtkTargetEntry targetlist[] = {
    { "STRING", STRING },
    { "TEXT",   TEXT },
    { "COMPOUND_TEXT", COMPOUND_TEXT }
  };
  static gint ntargets = sizeof(targetlist) / sizeof(targetlist[0]);
  
  gtk_selection_add_targets (selection_button, GDK_SELECTION_PRIMARY,
			     targetlist, ntargets);

  gtk_signal_connect (GTK_OBJECT(selection_button), "selection_get",
		      GTK_SIGNAL_FUNC (selection_get), NULL);


void
selection_get (GtkWidget *widget, 
	       GtkSelectionData *selection_data,
	       guint      info,
	       guint      time,
	       gpointer   data)
{

[...]

  switch (info)
    {
    case COMPOUND_TEXT:
       [...]
    case TEXT:
       [...]
    case STRING:
       [...]
    }
  
  gtk_selection_data_set (selection_data, type, 8, buffer, len);
}


I think it makes things a bit handier, but could be removed
in favor of making the target lists straight lists of 
GdkAtoms. (Unfortunately, the same capability can't be
provided on the receiving end, since GTK+ doesn't ever
get a list of targets from the app. It is provided on
both ends for DND under some circumstances. I'll elaborate
more on the DND API soon.)

Also, as a gratuitous piece of breakage, I'm planning to
make a minor change to the "selection_received" signal
to add a "time" parameter.

  void "selection_received"      (GtkWidget          *widget,
				  GtkSelectionData   *selection_data,
				  guint               time);

This probably will cause more problems with backwards
incompatibility than the more major changes ... but knowing
the time here is somewhat necessary to speak the selection
protocols correctly.

(You can fish it out of gtk_get_current_event(), but that is
 less than elegant.)

Anyways, comments or suggestions are welcome.

Regards,
                                        Owen



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