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 gtk.SelectionData is the same as above, but this time, we're responsible for filling in the fields type, format and data. (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("INTEGER", 32, data)
|
The following method sets the selection data from the given string:
selection_data.set_text(str, len) |
When prompted by the user, you claim ownership of the selection by calling:
result = widget.selection_owner_set(selection, time=0L) |
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 enclosed in a gtk.EventBox. (The gtk.Eventbox is needed because the selection must be associated with a gtk.gdk.Window and a gtk.Button is a "windowless" object in GTK+ 2.0.) 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 21.2, “Set Selection Example” illustrates the program display when the program has taken the primary selection ownership:
The setselection.py source code is:
1 #!/usr/bin/env python
2
3 # example setselection.py
4
5 import pygtk
6 pygtk.require('2.0')
7 import gtk
8 import time
9
10 class SetSelectionExample:
11 # Callback when the user toggles the selection
12 def selection_toggled(self, widget, window):
13 if widget.get_active():
14 self.have_selection = window.selection_owner_set("PRIMARY")
15 # if claiming the selection failed, we return the button to
16 # the out state
17 if not self.have_selection:
18 widget.set_active(gtk.FALSE)
19 else:
20 if self.have_selection:
21 # Not possible to release the selection in PyGTK
22 # just mark that we don't have it
23 self.have_selection = gtk.FALSE
24 return
25
26 # Called when another application claims the selection
27 def selection_clear(self, widget, event):
28 self.have_selection = gtk.FALSE
29 widget.set_active(gtk.FALSE)
30 return gtk.TRUE
31
32 # Supplies the current time as the selection.
33 def selection_handle(self, widget, selection_data, info, time_stamp):
34 current_time = time.time()
35 timestr = time.asctime(time.localtime(current_time))
36
37 # When we return a single string, it should not be null terminated.
38 # That will be done for us
39 selection_data.set_text(timestr, len(timestr))
40 return
41
42 def __init__(self):
43 self.have_selection = gtk.FALSE
44 # Create the toplevel window
45 window = gtk.Window(gtk.WINDOW_TOPLEVEL)
46 window.set_title("Set Selection")
47 window.set_border_width(10)
48 window.connect("destroy", lambda w: gtk.main_quit())
49 self.window = window
50 # Create an eventbox to hold the button since it no longer has
51 # a GdkWindow
52 eventbox = gtk.EventBox()
53 eventbox.show()
54 window.add(eventbox)
55
56 # Create a toggle button to act as the selection
57 selection_button = gtk.ToggleButton("Claim Selection")
58 eventbox.add(selection_button)
59
60 selection_button.connect("toggled", self.selection_toggled, eventbox)
61 eventbox.connect_object("selection_clear_event", self.selection_clear,
62 selection_button)
63
64 eventbox.selection_add_target("PRIMARY", "STRING", 1)
65 eventbox.selection_add_target("PRIMARY", "COMPOUND_TEXT", 1)
66 eventbox.connect("selection_get", self.selection_handle)
67 selection_button.show()
68 window.show()
69
70 def main():
71 gtk.main()
72 return 0
73
74 if __name__ == "__main__":
75 SetSelectionExample()
76 main()
|