/ lib / python / gladevcp / xembed.py
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)