File: xembed.py

package info (click to toggle)
linuxcnc 2.9.0~pre1%2Bgit20230208.f1270d6ed7-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 274,984 kB
  • sloc: python: 142,166; ansic: 103,241; cpp: 99,140; tcl: 16,045; xml: 10,608; sh: 10,124; makefile: 1,229; javascript: 226; sql: 72; asm: 15
file content (116 lines) | stat: -rw-r--r-- 3,354 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python3
# vim: sts=4 sw=4 et
"""
XEmbed helper functions to allow correct embedding inside Axis
"""

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk

def reparent(window, parent):
    """ Forced reparent. When reparenting Gtk applications into Tk
    some extra protocol calls are needed.
    """
    from Xlib import display
    from Xlib.xobject import drawable

    if not parent:
        return window

    plug = Gtk.Plug.new(int(parent))
    plug.show_all()

    d = display.Display()
    w = drawable.Window(d.display, plug.get_window().get_xid(), 0)
    # Honor XEmbed spec
    atom = d.get_atom('_XEMBED_INFO')
    w.change_property(atom, atom, 32, [0, 1])
    w.reparent(parent, 0, 0)
    w.map()
    d.sync()

    for c in window.get_children():
        window.remove(c)
        plug.add(c)

    # Hide window if it's displayed
    window.unmap()

    return plug

def add_plug(window):
    """Replace top level with a plug so it can be reparented.
    This doesn't actually reparent the widget
    """
    plug = Gtk.Plug(0)
    plug.show()
    for c in window.get_children():
        window.remove(c)
        plug.add(c)

    # Hide window if it's displayed
    window.unmap()
    return plug

def keyboard_forward(window, forward):
    """ XXX: Keyboard events forwardind
        This is kind of hack needed to properly function inside Tk windows.
        Gtk app will receive _all_ events, even not needed. So we have to forward
        back things that left over after our widgets. Connect handlers _after_
        all others and listen for key-press and key-release events. If key is not
        in ignore list - forward it to window id found in environment.
    """
    if not forward:
        return
    try:
        forward = int(forward, 0)
    except:
        return

    from Xlib.protocol import event
    from Xlib import display, X
    from Xlib.xobject import drawable

    d = display.Display()
    fw = drawable.Window(d.display, forward, 0)
#TODO: GTK3
#    ks = gtk.keysyms
    ignore = []#[ ks.Tab, ks.Page_Up, ks.Page_Down
#             , ks.KP_Page_Up, ks.KP_Page_Down
#             , ks.Left, ks.Right, ks.Up, ks.Down
#             , ks.KP_Left, ks.KP_Right, ks.KP_Up, ks.KP_Down
#             , ks.bracketleft, ks.bracketright
#             ]

    def gtk2xlib(e, fw, g, type=None):
        if type is None: type = e.type
        if type == Gdk.EventType.KEY_PRESS:
            klass = event.KeyPress
        elif type == Gdk.EventType.KEY_RELEASE:
            klass = event.KeyRelease
        else:
            return
        kw = dict(window=fw, detail=e.hardware_keycode,
                  state=e.state & 0xff,
                  child=X.NONE, root=g._data['root'],
                  root_x=g._data['x'], root_y=g._data['y'],
                  event_x=0, event_y=0, same_screen=1)
        return klass(time=e.time, **kw)

    def forward(w, e, fw):
        if e.keyval in ignore:
            return

        g = fw.get_geometry()
        fe = gtk2xlib(e, fw, g)
        if not fe: return

        fw.send_event(fe)

    window.connect_after("key-press-event", forward, fw)
    window.connect("key-release-event", forward, fw)
    #TODO:
    #window.add_events(Gdk.EventType.KEY_PRESS_MASK)
    #window.add_events(Gdk.EventType.KEY_RELEASE_MASK)