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(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 = False 24 return 25 26 # Called when another application claims the selection 27 def selection_clear(self, widget, event): 28 self.have_selection = False 29 widget.set_active(False) 30 return 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 = 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() |