20.3.
Supplying the selection
Supplying the selection is a bit more complicated.
You must register handlers that will be called when your selection is requested.
For each selection/target pair you will handle, you make a call to:
widget.selection_add_target(selection, target, info)
|
widget, selection,
and
target identify the requests
this handler will manage. When a request for a selection is received, the
"selection_get" signal will
be called. info is an integer
that can be used as an enumerator to identify the specific target within
the callback.
The callback has the signature:
def selection_get(widget, selection_data, info, time):
|
The GtkSelectionData is the same as above,
but this time, we're responsible for filling in the fields type,
format,
data,
and length. (The format
field is actually important here - the X server uses it to figure out whether
the data needs to be byte-swapped or not. Usually it will be 8 - i.e.
a character - or 32 - i.e. a. integer.) This is done by calling
the method:
selection_data.set(type, format, data)
|
This PyGTK method can only handle string
data
so the data must be loaded into a Python string but format
will be whatever the appropriate size is (e.g. 32 for atoms and integers,
8 for strings). The Python struct or StringIO modules can be used to convert
non-string data to string data. For example, you can convert a list of
integers to a string and set the selection_data
by:
ilist = [1, 2, 3, 4, 5]
data = apply(struct.pack, ['%di'%len(ilist)] + ilist)
selection_data.set(SELECTION_TYPE_INTEGER, 32, data)
|
When prompted by the user, you claim ownership
of the selection by calling:
result = widget.selection_owner_set(selection, time)
|
result will be TRUE if program
successfully claimed the selection.
If another application claims ownership of the selection, you will receive
a "selection_clear_event".
As an example of supplying the selection,
the setselection.py program adds
selection functionality to a toggle button. When the toggle button is depressed,
the program claims the primary selection. The only target supported (aside
from certain targets like "TARGETS" supplied by GTK itself), is the "STRING"
target. When this target is requested, a string representation of the time
is returned. Figure 20.2 illustrates the program display when the program
has taken the primary selection ownership:

Figure 20.2 Set Selection Example
The
setselection.py source code
is:
1 #!/usr/bin/env python
2
3 # example setselection.py
4
5 import gtk
6 import GDK
7 import time
8
9 class SetSelectionExample:
10 SELECTION_PRIMARY = 1
11 CURRENT_TIME = 0
12 # Callback when the user toggles the selection
13 def selection_toggled(self, widget):
14 if widget.active:
15 self.have_selection = widget.selection_owner_set(
16 self.SELECTION_PRIMARY, self.CURRENT_TIME)
17 # if claiming the selection failed, we return the button to
18 # the out state
19 if not self.have_selection:
20 widget.set_active(gtk.FALSE)
21 else:
22 if self.have_selection:
23 # Not possible to release the selection in PyGTK
24 # just mark that we don't have it
25 self.have_selection = gtk.FALSE
26 return
27
28 # Called when another application claims the selection
29 def selection_clear(self, widget, event):
30 self.have_selection = gtk.FALSE
31 widget.set_active(gtk.FALSE)
32 return gtk.TRUE
33
34 # Supplies the current time as the selection.
35 def selection_handle(self, widget, selection_data, info, time_stamp):
36 current_time = time.time()
37 timestr = time.asctime(time.localtime(current_time))
38
39 # When we return a single string, it should not be null terminated.
40 # That will be done for us
41 selection_data.set(GDK.SELECTION_TYPE_STRING,8, timestr)
42 return
43
44 def __init__(self):
45 self.have_selection = gtk.FALSE
46 # Create the toplevel window
47 window = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL)
48 window.set_title("Set Selection")
49 window.set_border_width(10)
50 window.connect("destroy", gtk.mainquit)
51
52 # Create a toggle button to act as the selection
53 selection_button = gtk.GtkToggleButton("Claim Selection")
54 window.add(selection_button)
55 selection_button.show()
56
57 selection_button.connect("toggled", self.selection_toggled)
58 selection_button.connect("selection_clear_event",
59 self.selection_clear)
60
61 selection_button.selection_add_target(
62 self.SELECTION_PRIMARY, GDK.SELECTION_TYPE_STRING, 1)
63 selection_button.connect("selection_get", self.selection_handle)
64 selection_button.show()
65 window.show()
66
67 def main():
68 gtk.mainloop()
69 return 0
70
71 if __name__ == "__main__":
72 SetSelectionExample()
73 main()
|