Xfce
Foundation Classes |
|||
« Main Page | Index | |||
Data SelectionsTable of ContentsOverviewOne type of interprocess communication supported by X and GTK+ is selections. A selection identifies a chunk of data, for instance, a portion of text, selected by the user in some fashion, for instance, by dragging with the mouse. Only one application on a display (the owner) can own a particular selection at one time, so when a selection is claimed by one application, the previous owner must indicate to the user that selection has been relinquished. Other applications can request the contents of a selection in different forms, called targets. There can be any number of selections, but most X applications only handle one, the primary selection.In most cases, it isn't necessary for a XFC application to deal with selections itself. The standard widgets, such as the Entry widget, already have the capability to claim the selection when appropriate (e.g., when the user drags over text), and to retrieve the contents of the selection owned by another widget or another application (e.g., when the user clicks the second mouse button). However, there may be cases in which you want to give other widgets the ability to supply the selection, or you wish to retrieve targets not supported by default. A fundamental concept needed to understand selection handling is that of the Atom. An atom is an integer that uniquely identifies a string (on a certain display). Certain atoms are predefined by the X server, and in some cases there are constants in <gdk/gdkselection.h> corresponding to these atoms. For instance the constant GDK_SELECTION_PRIMARY corresponds to the string "PRIMARY". In other cases, you should use the functions gdk_atom_intern(), to get the atom corresponding to a string, and gdk_atom_name(), to get the name of an atom. Both selections and targets are identified by atoms. Retrieving the selectionRetrieving the selection is an asynchronous process. To start the process, you call the Gtk::Widget method:bool selection_convert(Gdk::Atom
selection, Gdk::Atom target, unsigned int time = GDK_CURRENT_TIME); This converts the selection into the form specified by target. If at all possible, the time field should be the time from the event that triggered the selection. This helps make sure that events occur in the order that the user requested them. However, if it is not available (for instance, if the conversion was triggered by a "clicked" signal), then you can use the constant GDK_CURRENT_TIME. When the selection owner responds to the request, a "selection_received" signal is sent to your application. The signal handler for this signal receives a reference to a Gtk::SelectionData object which provides the following accessor functions: Gdk::Atom selection() const; The selection() and target() functions return the values you gave in your Gtk::Widget::selection_convert() call. The type() function returns an atom that identifies the type of data returned by the selection owner. Some possible values are "STRING" (a string of latin-1 characters), "ATOM" (a series of atoms), "INTEGER" (an integer), etc. Most targets can only return one type. The format() function returns the length of the units (8 for characters, 32 for integers) in bits. Usually, you don't care about this when receiving data. The data() function returns a pointer to the returned data, and length() returns the length of the returned data, in bytes. If length() is negative, then an error occurred and the selection could not be retrieved. This might happen if no application owned the selection, or if you requested a target that the application didn't support. The buffer is actually guaranteed to be one byte longer than length; the extra byte will always be zero, so it isn't necessary to make a copy of strings just to null-terminate them. For convenience, there are accessors that return the selection, target and type as a String: String get_selection() const; You can retrieve the
selection_data as a vector of supported targets. This can be used to
interpret the results of getting the standard "TARGETS" target that is
always supplied for any selection.
bool
get_targets(std::vector<Gdk::Atom>& targets) const; The first get_targets() function retrieves the targets as a vector of Gdk::Atom. The second retrieves the target names as a vector of String. The following function returns true if the length of the selection data is greater than 0. bool is_valid() const; You can connect directly to the "selection_received" signal with the following code: widget->signal_selection_received().connect(sigc::mem_fun(this,
&MyClass::selection_received_handler)); where the "selection_received" signal handler has the following prototype: void
MyClass::selection_received_handler(const
Gtk::SelectionData& selection_data, unsigned int time); Supplying the selectionBeing the owner of a selection is a bit more complicated and only makes sense when there is data for transmission. Data can exist in a variety of formats so first you have to define the targets that correspond to these formats. You are free to come up with target names yourself but this is only useful within the same application. Therefore, a number of standard targets have been agreed upon. A list of targets and information on their use can be found in the ICCCM. The targets MULTIPLE, TARGETS and TIMESTAMP are defined byX11 architecture as mandatory and are automatically provided by GTK+. To define the supported target(s) for a certain selection and widget use one of the following Gtk::Widget methods: void selection_add_target(Gdk::Atom
selection, Gdk::Atom target, unsigned int info); The 'selection' argument is the atom corresponding to the selection for which the target(s) will be registered, the 'target' argument is the atom corresponding to the target name you want to register and the 'info' argument is a unique integer id that will be passed back through signals later on. The first two methods register a single target. The second method takes a Gtk::TargetEntry rather than separate target and info arguments. The last method lets you register multiple targets at once by passing a vector of Gtk::TargetEntry. You can create a new TargetEntry object with one of the following constructors: TargetEntry(); The first constructor creates an empty TargetEntry. The second constructor creates a target entry with the specified name and unique id. The 'target_name' argument is a string corresponding to the target atom and 'unique_id' is the unique integer id. The 'drag_flags' argument is only used when implementing Drag and Drop. It restricts the validity of the corresponding target to the same application or the same widget. If you create an empty TargetEntry, you can set its target_name and unique_id by calling the Gtk::TargetEntry method: void set(const String& target_name,
unsigned int unique_id, Gtk::TargetFlagsField drag_flags = 0); The 'target_name' is the string corresponding to the target atom and unique_id is the unique integer id. The 'drag_flags' argument is used to restrict the validity of the corresponding target and can either be Gtk::TARGET_SAME_APP or Gtk::TARGET_SAME_WIDGET. Now the targets have been registered, when prompted by the user you need to take ownership of a certain selection. This is done with the following Gtk::Widget method: bool selection_owner_set(Gdk::Atom
selection, unsigned int time, const Gdk::Display *display = 0); The 'selection' argument is the atom corresponding the selection for which the owner should be changed, 'time' is a timestamp with which to claim the selection, or GDK_CURRENT_TIME. The 'display' is the Gdk::Display where the selection is set, or null for the default display. If the return value is true the calling widget owns the selection. If you need to check whether a widget owns a certain selection you can call the Gtk::Widget accessor: bool selection_owner_get(Gdk::Atom
selection); The 'selection' is an interned atom representing the selection to check. The return value is true if the calling widget owns the specified selection. To be able to respond to a Gtk::Widget::selection_convert() request, you must either connect to the "selection_get" signal or derive a new class for the selection widget and override the Gtk::WidgetSignals::on_selection_get() virtual signal handler. To connect to the "selection_get" signal, use the following code: widget->signal_selection_get().connect(sigc::mem_fun(this,
&MyClass::selection_get_handler)); The selection_get handler has the following prototype: void
MyClass::selection_get_handler(Gtk::SelectionData& selection_data,
unsigned int info, unsigned int time); The 'selection_data' is the SelectionData object to be filled in, 'info' is the info integer that was set when the target was registered, and 'time' is the time of the conversion request as set by the requestor with Gtk::Widget::selection_convert(). When the "selection_get" signal returns, the widget requesting the selection will receive the selection_data. You must call the following Gtk::SelectionData methods to set the selection_data fields: void set(Gdk::Atom type, int format,
const void *data, int length); These methods should only be called from a selection handler callback. The 'type' argument is an atom that describes the 'data' provided and the 'format' is the number of bits required to store one element of the target type. Usually it will be 8 for a character or 32 for an integer. The most commonly used target types are: ATOM, COMPOUND_TEXT, INTEGER and STRING. This method takes care of properly making a copy of the data so that you don't have to worry about keeping it around. The length argument is the data length. The data should be null-terminated. For convenience, the set_text() method sets the contents of the selection from a UTF-8 encoded string. The string is converted to the form determined by the target and true is returned if the selection was successfully set. If another application claims ownership of the selection, you will receive a "selection_clear_event" signal. To explicitly release ownership of a selection call the following Gtk::Widget method: bool selection_owner_unset(Gdk::Atom
selection, unsigned int time, const Gdk::Display *display = 0); The 'selection' argument is an interned atom representing the selection to release, 'time' is a timestamp, or GDK_CURRENT_TIME and 'display' is the Gdk::Display where the selection is set, or null for the default display. True is returned if the operation succeeded. Selection ExampleIn the following example, we retrieve the special target "TARGETS", which is a list of all targets into which the selection can be converted.The header file for the selection example is <selection.hh>: #include <xfc/main.hh> and the source file is <selection.cc>: #include "selection.hh" Compiling Selection
If you compiled and installed XFC yourself, you will find the source
code for Selection in the
<examples/selection> source directory along with a Makefile. If
XFC came pre-installed, or you installed it from an RPM package, you
will
find the source code in the
</usr/share/doc/xfcui-X.X/examples/selection> subdirectory. In
this case you will have to create the Makefile yourself (replace X.X
with the
version number of the libXFCui library you have installed). |
Copyright © 2004-2005 The XFC Development Team | Top |
XFC
4.4 |