Selecciones

Resumen

Las selecciones son un tipo de comunicación entre procesos, que esta soportado por las X y GTK. Una selección identifica una porción de datos, por ejemplo, una porción de texto, que ha sido seleccionado dentro de una tarea que esta ejecutando un usuario, por ejemplo una forma de seleccionar un contenido podria ser arrastrando el ratón, sobre él. Solo una aplicación ( la propietaria ) puede tener una selección al mismo momento, por tanto cuando otra aplicación quiere poseer dicha selección, la que poseia dicha selección en un primer momento debe indicar al usuario que esta, ha sido abandonada. Otras aplicaciones pueden pedir el contenido de una selección de diferentes formas, que se conocen con el nombre de objetivos. Las aplicaciones pueden manejar cualquier numero de selecciones, pero la mayoria solo tienen en cuenta una, la llamada selección primaria.

En la mayoria de los casos, no es necesario que la propia aplicación GTK maneje las selecciones. Los Widgets estandar, como por ejemplo la caja de texto, tienen la capacidad de solicitar la selección cuando sea necesario ( por ejemplo cuando el usuario arrastra el raton sobre el texto ), y obtener los contenidos de la selección que pertenecen a otro widget o incluso otra aplicacion ( por ejemplo cuando el usuario pulsa el segundo botón del ratón ). Sin embargo, puede darse el caso en el cual se quiera tener la posibilidad para que un widget pueda proveer un objetivo que no este diseñado por defecto.

Un concepto fundamental a la hora de entender el manejo de selecciones es el significado de un átomo. Un átomo es un entero que identifica inequivocamente una cadena ( en un determinado display). Algunos átomos estan predefinidos por el servidor X y en algunos casos en constantes , que se corresponden con los átomos, dentro de gtk.h. Por ejemplo la constante GDK_PRIMARY_SELECTION corresponde con la cadena PRIMARY. En otros casos se debe usar las funciones gdk_atom_intern(), para obtener el átomo correspondiente a una cadena, y gdk_atom_name(), para obtener el nombre de un átomo. Ambas cosas, selecciones y objetivos estan identificados por átomos.

Obteniendo la selección

Obtener la selección es un proceso asincrono. Para comenzar el proceso, se llama a:

gboolean gtk_selection_convert (widget,  
 selection,  
 target,  
 time); 
GtkWidget * widget;
GdkAtom  selection;
GdkAtom  target;
guint32  time;

Esta llamada convierte la selección en el tipo especificado por el parametro target. Si es posible , el parametro time deberia ser el tiempo del el evento que ha lanzado la selección. Esto ayuda para asegurarse que los eventos ocurren en el orden que el usuario los ha lanzado. Sin embargo si esto no es posible ( por ejemplo , si la conversión fue disparada por una señal clicked ), entonces se puede usar la constante GDK_CURRENT_TIME.

Cuando la aplicacion propietaria de la selección responde a la petición, la señal "selection_received" se manda a la aplicación que ha realizado la petición. El manejador para esta señal recibe un puntero a una estructura GtkSelectionData, que esta definida como:

	struct _GtkSelectionData
	{
	GdkAtom selection;
	GdkAtom target;
	GdkAtom type;
	gint    format;
	guchar *data;
	gint    length;
	};
      

selection y target son los valores que se dieron en la llamada a gtk_selection_convert(). type es un átomo que identifica el tipo de datos que va a ser devuelto por el propietario de la selección. Algunos valores posibles son "STRING" para una cadena de caracteres, "ATOM", una serie de átomos, "INTEGER", un entero, etc. La mayoria de objetivos solo pueden devolver un tipo.format nos indica la longitud de las unidades ( por ejemplo los caracteres ) en bits. Normalmente, no hay que preocuparse de esto cuando se recibe los datos. data es un puntero a los datos devueltos, en bytes. Si la longitud es negativa la seleccion no puede ser recuperada ya que se ha producido un error. Esto podria pasar si ninguna aplicación posee la selección, o si se solicita un objetivo que la aplicación no tiene definido. La longitud del buffer se garantiza que sera un byte mas grande que lo que se indica en length; este byte extra sera siempre cero, por lo que si es una cadena no nos tenemos que preocupar de terminarla en este caracter nulo.

En el siguiente ejemplo, Vamos a obtener el objetivo especial "TARGETS", el cual es una lista de todos los objetivos en los que una selección puede ser convertida

Suministrando la selección

Suministrar la selección es un poco mas complicado, Se debe registrar manejadores que seran llamados cuando se solicite la selección. Para cada pareja selección/objetivo que se quiera controlar, se debe hacer una llamada a:

void gtk_selection_add_target (widget,  
 selection,  
 target,  
 info); 
GtkWidget * widget;
GdkAtom  selection;
GdkAtom  target;
guint  info;

widget, selection y target identifica las peticiones que el manejador puede gestionar. Cuando una petición de una selección es recibida, se llamara a la señal "selection_get". info puede ser usado como una enumeración para identificar el objetivo especifico que acompaña a la función de callback.

La función de callback tiene la forma:

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

El elemento GtkSelectionData es el mismo que antes, solo que ahora, Debemos rellenar los campos type, format, data y legth. ( El campo format es importante aqui - el servidor X lo usa para saber si los datos necesitan ser intercambiados a nivel de byte o no. Normalmente sera 8, para un caracter, o 32 para un entero) Esto se hace llamando a la función:

void gtk_selection_data_set (selection_data,  
 type,  
 format,  
 data,  
 lenght); 
GtkSelectionData *  selection_data ;
GdkAtom  type;
gint  format;
guchar * data;
gint  lenght;

Esta función se encarga de hacer una copia de el parametro data por lo que no hay que preocuparse de mantenerlo. ( No se deberia rellenar a mano los campos de selection_data

Cuando sea necesario, se establecera la propiedad de la selección llamando a la función

gboolean gtk_selection_ownet_set (widget,  
 selection,  
 time); 
GtkWidget * widget;
GdkAtom  selection;
guint32  time;

Si otra aplicación reclama la propiedad de la selección, se recibira una señal del tiposelection_clear_event

Como el ejemplo anterior de obtener una selección, la siguiente aplicación añade la funcionalidad de selección a un toggle button. Cuando el toggle button esta no activo, el programa reclamara la selección primaria. El unico objetivo disponible ( junto con otros objetivos, como TARGET, suministrados por la propia GTK ), es STRING. Cuando se hace una petición a este objetivo, se retorna una cadena que contiene la hora actual