Portapapeles
Algunos tópicos sobre el portapeles en glib. Es para quien desee ahondar en el modelo o sistema de portapapeles en glib/gtk+. Esta es la primera parte y describe como trabaja el porta papeles.
Primera parte
- Lamentablemente, en la red no se encuentra mucha información del portapapeles de glib.
Este documento ha sido elaborado según la experiencia en el tema. Por lo tanto cualquier error u omisión es involuntario y se recomienda al lector hacérmelo saber. ¡¡¡ Gracias !!! ;)
Porta papeles
Es una forma de comunicación entre procesos. Se usa para guardar datos y luego recuperarlos, ya sea en el mismo proceso o en otro.
En glib/gtk, el grupo de funciones u objeto que lo hace, se llama: gtkclipboard. Por defecto, el gtkclipboard sólo guarda dos tipos de datos, que son: texto e imágenes. En principio,cuando uno desea pasar otro tipo de objeto, el gtkclipboard no dá opciones. Mirando el código del «porta papeles» se puede encontrar que probablemente se pueda hacer.
Funcionamiento
- Primero vamos a entender como es el funcionamiento del gtkclipboard y luego nos ponemos manos a la obra.
En principio si uno desea poner en el porta papeles un texto o una imagen sólo ha de llamar una de estas dos funciones: gtk_clipboard_set_text ó gtk_clipboard_set_image Para el primero, habrá que pasarle el clipboard del tipo GtkClipboard*, se le ha de pasar el texto y la longitud de éste. Para el segundo, sólo habrá que pasarle el GtkClipboard* y la imagen; la imagen ha de ser del tipo GdkPixbuf*. Por cierto GdkPixbuf no es un objeto heredable, sólo es estático.
El portapapeles hay que iniciarlo antes de usarlo, y una de las formas como se puede hacer es: gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); GDK_SELECTION_CLIPBOARD equivale a usar el porta papeles herado por defecto.
Cuando se quiere pasar información al porta-papeles, la forma de hacerlo es: Para un texto: gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),texto,long_texto); Para una imagen: gtk_clipboard_set_image(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),imagen);
gtk_clipboard_set_text
- /**
- gtk_clipboard_set_text:
@clipboard: a #GtkClipboard object
- @text: a UTF-8 string.
- @len: length of @text, in bytes, or -1, in which case
the length will be determined with <function>strlen()</function>.
- Sets the contents of the clipboard to the given UTF-8 string. GTK+ will
- make a copy of the text and take responsibility for responding
- for requests for the text, and for converting the text into
- the requested format.
- */
El nombre de la función con sus parámetros, nada raro hasta ahora.
void gtk_clipboard_set_text (GtkClipboard* clipboard,const gchar *text,
- gint len)
GtkTargetList *list;
Resulta que hace hace una variable de tipo GtkTargetList. Ésta es una estructura que depende de gtk-Selections. gtk-Selections Son un conjunto de funciones encargadas de manejar la comunicación entre procesos. No significa que sea la única manera, pero es la forma que usa el gtkclipgboard. GtkTargetList, guarda los tipos de datos que maneja gtk-Selections; que son del tipo GtkTargetEntry y que fuera de otra información, contiene identificadores de la estructura de datos y de su posible recuperación.
- GList *l; " un Glist ;)"
El tipo de datos que usa gtk-selections
GtkTargetEntry *targets;
La cantidad de elementos que posee la lista de targets.
gint n_targets, i; g_return_if_fail (clipboard != NULL); g_return_if_fail (text != NULL); list = gtk_target_list_new (NULL, 0); gtk_target_list_add_text_targets (list, 0);Esta función le agrega una cantidad determinada de targets a list. ¿Pero que són esos targets? Según lo que entiendo, los targets son «como apuntadores», que se rerefrencian dentro de una tabla de cadenas manejada por el servidor X. Los targets son del tipo GdkAtom.Hay que tener en cuenta que no es un apuntador a un tipo, ¿Pero qué tiene qué ver la función con los GdkAtom...?" Pues gtk_target_list_add_text_targets (list, 0); es la encargada de sumarle a la lista, los targets que indican el tipo de dato que se le va a pasar al porta papeles. Lo realiza de la siguiente forma:
Esta función está en gtkselection: void gtk_target_list_add_text_targets (GtkTargetList *list,guint info) { g_return_if_fail (list != NULL); si no hay objeto para qué seguir. init_atoms (); {{{ init_atoms, encargada de inicializar los tipos de atoms que por defecto trae gtkselections y la forma que lo hace es: [ ... utf8_atom = gdk_atom_intern ("UTF8_STRING", FALSE); text_atom = gdk_atom_intern ("TEXT", FALSE); ... ] Y si uds. se dan cuenta, entonces sólo hacen referencias al tipo de información que se le está pasando al porta papeles..
continuando dentro gtk_target_list_add_text_targets... Sólo se encarga de agregarle a GtkTargetList los atoms que «equivalen» a los tipos de datos que soportará el portapapeles para texto. utf8_atom, ctext_atom, etc, son los «atom» predefindos para tipos de texto plano que existen en gtk_clipboard, que para el caso son 7.
/* Keep in sync with gtk_selection_data_targets_include_text() */ gtk_target_list_add (list, utf8_atom, 0, info); gtk_target_list_add (list, ctext_atom, 0, info); gtk_target_list_add (list, text_atom, 0, info); gtk_target_list_add (list, GDK_TARGET_STRING, 0, info); gtk_target_list_add (list, text_plain_utf8_atom, 0, info); gtk_target_list_add (list, text_plain_locale_atom, 0, info); gtk_target_list_add (list, text_plain_atom, 0, info); }
continuando con gtk_clipboard_set_text:
Entrega la cantidad de atoms o tipos de texto que puede soportar, que para el caso son 7.
n_targets = g_list_length (list->list); targets = g_new (GtkTargetEntry, n_targets);
for (l = list->list, i = 0; l; l = l->next, i++)
- {
GtkTargetPair *pair = (GtkTargetPair *)l->data; targets[i].target = gdk_atom_name (pair->target);
Recupera la longitud del texto, esto es de vital importancia.
if (len < 0)
- len = strlen (text);
- targets, n_targets, text_get_func, text_clear_func, g_strndup (text, len));
La anterior función cumple su papel, pone el texto que se le pasa como parámetro al porta papeles. Los parámetros de la función son lo siguientes: clipboard: debe ser del tipo GtkClipboard*. targets: del tipo GtkTargetEntry *. n_targets: del tipo int. text_get_func: ha de ser un apuntador a una función con el siguiente modelo (*GtkClipboardReceivedFunc) (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data); Aunque el nombre no importa ni su tipo, si importa la forma que ha de ser (*nombre)(GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data); ""Y hay que tenerla en cuenta.""
- g_strndup (text, len)
sólo hace una copia del texto a memoria para no trabajar con el original. Las funciones text_get_func, text_clear_func se representan a continuación: static void text_get_func (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data) { gtk_selection_data_set_text (selection_data, data, -1); } gtk_selection_data_set_text está en gtk_selection, ¿qué hace? ¿Se acuerdan que hay unos atoms? Entonces dependiendo de la referencia del átom, así mismo se decide como convertir el tipo de texto a la forma que es aceptada por el porta papeles. Cuando se realiza tal conversión terminan llamando a: gtk_selection_data_set (selection_data, selection_data->target, 8, result,longitud)); en este momento uno no se dá cuenta de lo siguiente: Que el formato que trabaja el porta papeles es utf 8 o mejor char de 8. Bien, cuando se vea lo que hacen con pixbuf se llega a ésa conclusión.
- {
Esta función le dice al porta-papeles que la información debe ser guardada en cualquier lugar cuando la aplicación termine o cuando la función sea llamada. El valor es vuelto a su estado inicial cuando el porta -papeles cambia de dueño.
for (i = 0; i < n_targets; i++)
- g_free (targets[i].target);
}
Como ven analizamos un poco la función gtk_clipboard_set_text. Ahora leeremos la que se encarga de poner la imagen en el portapeles..
gtk_clipboard_set_image.
/**
- gtk_clipboard_set_image:
@clipboard: a #GtkClipboard object
@pixbuf: a #GdkPixbuf
Sets the contents of the clipboard to the given #GdkPixbuf.
- GTK+ will take responsibility for responding for requests
- for the image, and for converting the image into the
- requested format.
- Since: 2.6
- */
En un vuelo de pájaro, se encuentra que tiene el mismo formato que gtk_clipboard_set_text por lo tanto...
void gtk_clipboard_set_image (GtkClipboard *clipboard,
GdkPixbuf *pixbuf)
{
Ya se sabe que es la lista de los GtkTargetEntry
GtkTargetList *list;
- GList *l;
los targets que son del tipo átom
GtkTargetEntry *targets; gint n_targets, i; g_return_if_fail (clipboard != NULL); g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); list = gtk_target_list_new (NULL, 0); gtk_target_list_add_image_targets (list, 0, TRUE);
Resulta que la función tiene un comportamiento similar al presentado por gtk_target_list_add_text_targets. gtk_target_list_add_image_targets está en gtkselections.c, que a su vez llama a gdk_pixbuf_format_get_mime_types, que se encuentra en gdk-pixbuf-io.c y que a terminadas cuentas entrega los tipos de imágenes soportados. Después, gtk_target_list_add_image_targets hace cosas como la siguiente: gdk_atom_intern_static_string ("image/png")) Es resgistar un átom, con un nombre cualquiera, para el caso "image/png"
Volviendo a gtk_clipboard_set_image: La cantidad de tipos para guardar en el porta papeles..
n_targets = g_list_length (list->list); targets = g_new0 (GtkTargetEntry, n_targets); for (l = list->list, i = 0; l; l = l->next, i++)
- {
GtkTargetPair *pair = (GtkTargetPair *)l->data; targets[i].target = gdk_atom_name (pair->target);
Y la encargada de guargar la info en el porta papeles..
gtk_clipboard_set_with_data (clipboard,- targets, n_targets, pixbuf_get_func, pixbuf_clear_func, g_object_ref (pixbuf));
¿y adivinen qué...? Vamos por : pixbuf_get_func para saber, qué es lo que hace... Bien entonces : La definición: static void pixbuf_get_func (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data) { gtk_selection_data_set_pixbuf (selection_data, data); } Metamos las narices en: gtk_selection_data_set_pixbuf /** * gtk_selection_data_set_pixbuf: * @selection_data: a #GtkSelectionData * @pixbuf: a #GdkPixbuf * * Sets the contents of the selection from a #GdkPixbuf * The pixbuf is converted to the form determined by * @selection_data->target. * * Return value: %TRUE if the selection was successfully set, * otherwise %FALSE. * * Since: 2.6 **/ Una función normal que recibe algunos parámetros ;p gboolean gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data, GdkPixbuf *pixbuf) { GSList *formats, *f; gchar **mimes, **m; GdkAtom atom; gboolean result; gchar *str, *type; gsize len; formats = gdk_pixbuf_get_formats (); Los formatos y sus tipos... for (f = formats; f; f = f->next) { GdkPixbufFormat *fmt = f->data; mimes = gdk_pixbuf_format_get_mime_types (fmt); for (m = mimes; *m; m++) { atom = gdk_atom_intern (*m, FALSE); if (selection_data->target == atom) { str = NULL; type = gdk_pixbuf_format_get_name (fmt); obtiene el tipo {{{ Se acuerdan de gdkatom... bien, aquí puede ser.
result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
- type, NULL, NULL);
Resulta (jejeje) que, de alguna forma mágica se llama a esta función gdk_pixbuf_save_to_buffer para cambiar de imagen a formato char ;) de nuevo gdk_pixbuf_save_to_buffer está en gdk-pixbuf-io.c y es un poco críptica para exponerla en unas lineas. Ésa función entrega la convcersión en la variable str e igualmente sigue siendo importante su tamaño: len. y ahora qué:...¿?
if (result)- gtk_selection_data_set (selection_data,
- atom, 8, (guchar *)str, len);
¿Si todo bien? Entonces: Pone la imagen en el porta papeles .. y cómo.. tranformada a un int 8 o guchar... ¡¡¡ Es algo para tener en cuenta jajajajajajaja. !!!!
g_free (type); g_free (str); g_strfreev (mimes); g_slist_free (formats); return result;
- }
- }
- g_strfreev (mimes);
- }
- g_slist_free (formats); return FALSE;
- {
De nuevo en Volviendo a gtk_clipboard_set_image:
- gtk_clipboard_set_can_store (clipboard, NULL, 0);
for (i = 0; i < n_targets; i++)
- g_free (targets[i].target);
De forma idéntica al texto.
}
Ya conocemos la forma aproximada, el como se comporta el porta papeles cuando se guardan datos.
- Escrito por:
- Made by: Exell Enrique Franklin Jiménez.