xembed.py
1 #!/usr/bin/env python 2 # vim: sts=4 sw=4 et 3 """ 4 XEmbed helper functions to allow correct embeding inside Axis 5 """ 6 7 import gtk 8 9 def reparent(window, parent): 10 """ Forced reparent. When reparenting Gtk applications into Tk 11 some extra protocol calls are needed. 12 """ 13 from Xlib import display 14 from Xlib.xobject import drawable 15 16 if not parent: 17 return window 18 19 plug = gtk.Plug(long(parent)) 20 plug.show() 21 22 d = display.Display() 23 w = drawable.Window(d.display, plug.window.xid, 0) 24 # Honor XEmbed spec 25 atom = d.get_atom('_XEMBED_INFO') 26 w.change_property(atom, atom, 32, [0, 1]) 27 w.reparent(parent, 0, 0) 28 w.map() 29 d.sync() 30 31 for c in window.get_children(): 32 window.remove(c) 33 plug.add(c) 34 35 # Hide window if it's displayed 36 window.unmap() 37 38 return plug 39 40 def add_plug(window): 41 """Replace top level with a plug so it can be reparented. 42 This doesn't actually reparent the widget 43 """ 44 plug = gtk.Plug(0l) 45 plug.show() 46 for c in window.get_children(): 47 window.remove(c) 48 plug.add(c) 49 50 # Hide window if it's displayed 51 window.unmap() 52 return plug 53 54 def keyboard_forward(window, forward): 55 """ XXX: Keyboard events forwardind 56 This is kind of hack needed to properly function inside Tk windows. 57 Gtk app will receive _all_ events, even not needed. So we have to forward 58 back things that left over after our widgets. Connect handlers _after_ 59 all others and listen for key-presss and key-release events. If key is not 60 in ignore list - forward it to window id found in evironment. 61 """ 62 if not forward: 63 return 64 try: 65 forward = int(forward, 0) 66 except: 67 return 68 69 from Xlib.protocol import event 70 from Xlib import display, X 71 from Xlib.xobject import drawable 72 73 d = display.Display() 74 fw = drawable.Window(d.display, forward, 0) 75 76 ks = gtk.keysyms 77 ignore = [ ks.Tab, ks.Page_Up, ks.Page_Down 78 , ks.KP_Page_Up, ks.KP_Page_Down 79 , ks.Left, ks.Right, ks.Up, ks.Down 80 , ks.KP_Left, ks.KP_Right, ks.KP_Up, ks.KP_Down 81 , ks.bracketleft, ks.bracketright 82 ] 83 84 def gtk2xlib(e, fw, g, type=None): 85 if type is None: type = e.type 86 if type == gtk.gdk.KEY_PRESS: 87 klass = event.KeyPress 88 elif type == gtk.gdk.KEY_RELEASE: 89 klass = event.KeyRelease 90 else: 91 return 92 kw = dict(window=fw, detail=e.hardware_keycode, 93 state=e.state & 0xff, 94 child=X.NONE, root=g._data['root'], 95 root_x=g._data['x'], root_y=g._data['y'], 96 event_x=0, event_y=0, same_screen=1) 97 return klass(time=e.time, **kw) 98 99 def forward(w, e, fw): 100 if e.keyval in ignore: 101 return 102 103 g = fw.get_geometry() 104 fe = gtk2xlib(e, fw, g) 105 if not fe: return 106 107 fw.send_event(fe) 108 109 window.connect_after("key-press-event", forward, fw) 110 window.connect("key-release-event", forward, fw) 111 window.add_events(gtk.gdk.KEY_PRESS_MASK) 112 window.add_events(gtk.gdk.KEY_RELEASE_MASK)