1# -*- coding: utf-8 -*-
2# This file is part of Xpra.
3# Copyright (C) 2015-2019 Antoine Martin <antoine@xpra.org>
4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
5# later version. See the file COPYING for details.
6
7from xpra.log import Logger
8from xpra.os_util import strtobytes
9from xpra.gtk_common.error import xsync
10from xpra.x11.gtk_x11.prop import prop_get, get_python_type
11from xpra.x11.bindings.window_bindings import X11WindowBindings     #@UnresolvedImport
12
13window_bindings = X11WindowBindings()
14log = Logger("x11", "filters")
15
16
17def get_x11_window_value(prop, window):
18    try:
19        with xsync:
20            xid = window.get_xid()
21            x11type = window_bindings.GetWindowPropertyType(xid, prop)[0]
22    except Exception:
23        log("get_x11_window_value(%s, %s)", prop, window, exc_info=True)
24        x11type = None
25    if x11type:
26        ptype = get_python_type(x11type)
27        #log("%s: %s (%s)", filter_object.property_name, x11type, ptype)
28        assert ptype, "type '%s' is not handled!" % x11type
29        v = prop_get(window, prop, ptype)
30        log("prop_get(%s, %s, %s)=%s", window, prop, ptype, v)
31        if v and isinstance(v, str):
32            v = strtobytes(v).replace("\0", "")
33    else:
34        v = None
35    log("%s=%s (type=%s)", prop, v, x11type)
36    return v
37
38def get_window_value(filter_object, gdkwin):
39    return get_x11_window_value(filter_object.property_name, gdkwin)
40
41def get_window(filter_object, window):
42    gdkwin = window.get_property("client-window")
43    p = gdkwin
44    log("get_window%s gdkwin=%s, recurse=%s", (filter_object, window), gdkwin, filter_object.recurse)
45    while filter_object.recurse and p:
46        gdkwin = p
47        p = None
48        try:
49            prop = "WM_TRANSIENT_FOR"
50            p = prop_get(gdkwin, prop, "window", ignore_errors=True)
51            log("prop_get(%s, %s)=%s", gdkwin, prop, p)
52        except Exception:
53            log("prop_get(%s, %s)", gdkwin, prop, exc_info=True)
54            break
55    return gdkwin
56
57def init_x11_window_filters():
58    from xpra.server.window import filters
59    original_get_window_filter = filters.get_window_filter
60
61    def get_x11_window_filter(object_name, property_name, operator, value):
62        oname = object_name.lower()
63        wf = original_get_window_filter(oname.replace("x11:", ""), property_name, operator, value)
64        if oname.startswith("x11:"):
65            #same filter but use X11 properties:
66            import types
67            wf.get_window = types.MethodType(get_window, wf)
68            wf.get_window_value = types.MethodType(get_window_value, wf)
69            log("patched methods: %s, %s", wf.get_window, wf.get_window_value)
70        log("x11 get_window_filter%s=%s", (object_name, property_name, operator, value), wf)
71        return wf
72
73    filters.get_window_filter = get_x11_window_filter
74    log("init_x11_window_filters() filters.get_window_filter=%s", filters.get_window_filter)
75