Mausklicks in GtkLabel

Entgegen der landläufigen Behauptung ist es durchaus möglich, Mausklicks auf GtkLabel-Instanzen zu verarbeiten. Der Schlüssel liegt darin, GTK anzuweisen, dass das jeweilige Label ein GdkWindow haben soll. Aufmerksam gemacht wurde ich hierauf durch diesen Beitrag von Tadej Borovšak. Hier ein Beispiel:

#! /usr/bin/env python
 
import gtk
 
window = gtk.Window()
window.set_title('Label Button Press Test')
window.set_size_request(400, 300)
window.connect('destroy', lambda w: gtk.main_quit())
 
box = gtk.VBox(spacing=6)
window.add(box)
 
class ClickableLabel(gtk.Label):
    __gsignals__ = {'button-press-event': 'override'}
 
    def __init__(self, *args):
        gtk.Label.__init__(self, *args)
        # This is the important line to enable more signals
        self.set_has_window(True)
        self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
 
    def do_button_press_event(self, event):
        print 'Clickable: %s' % event.type
 
clickable_label = ClickableLabel()
clickable_label.set_markup('<span size="25000">Clickable label</span>')
box.pack_start(clickable_label, False)
 
def on_button_press_event(widget, event):
    print 'Regular: %s' % event.type
 
label = gtk.Label()
label.set_markup('<span size="25000">Regular label</span>')
# Does not work and renders the label invisible
label.set_has_window(True)
label.add_events(gtk.gdk.BUTTON_PRESS_MASK)
label.connect('button-press-event', on_button_press_event)
box.pack_start(label, False)
 
window.show_all()
gtk.main()

Wie zu sehen ist, lassen sich unter Nutzung einer einzelnen Zeile weitere Signale für ein GtkLabel „freischalten“. Jedoch nur für abgeleitete Typen, nicht für die Standard-GtkLabels, wie am zweiten Label zu erkennen ist. Warum dies so ist ist mir trotz Blick auf gtkwidget.c noch nicht ersichtlich. Erklärungen zur Methode set_has_window() erwähnen, dass diese nur in der Initialisierung eines Widgets aufgerufen werden sollte. Intern wird hier nur das GTK_NO_WINDOW-Flag gesetzt oder gelöscht und infolge dessen unter anderem das Zeichnen von Widgets anders gehandhabt. Aus diesem Grund hat ein GtkLabel bspw. auch keinen Hintergrund welchen man ändern könnte.