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 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() |