xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #173: xi-events-v4.patch

File xi-events-v4.patch, 29.4 KB (added by Antoine Martin, 4 years ago)

updated patch for r15794

  • xpra/log.py

     
    264264                ])),
    265265    ("X11", OrderedDict([
    266266                ("x11"          , "All X11 code"),
     267                ("xinput"       , "XInput bindings"),
    267268                ("bindings"     , "X11 Cython bindings"),
    268269                ("core"         , "X11 core bindings"),
    269270                ("randr"        , "X11 RandR bindings"),
  • xpra/platform/features.py

     
    1515SYSTEM_TRAY_SUPPORTED = False
    1616REINIT_WINDOWS = False
    1717
     18INPUT_DEVICES = ["auto"]
     19
    1820CLIPBOARDS = []
    1921CLIPBOARD_WANT_TARGETS = envbool("XPRA_CLIPBOARD_WANT_TARGETS")
    2022CLIPBOARD_GREEDY = envbool("XPRA_CLIPBOARD_GREEDY")
     
    6264                   "CLIPBOARD_NATIVE_CLASS",
    6365                   "UI_THREAD_POLLING",
    6466                   "CLIENT_MODULES",
     67                   "INPUT_DEVICES",
    6568                   ]
    6669from xpra.platform import platform_import
    6770platform_import(globals(), "features", False,
  • xpra/platform/xposix/features.py

     
    2121
    2222DEFAULT_SSH_CMD = "ssh"
    2323CLIPBOARDS=["CLIPBOARD", "PRIMARY", "SECONDARY"]
     24
     25INPUT_DEVICES = ["auto", "xi"]
  • xpra/platform/xposix/gui.py

     
    499499    _toggle_wm_state(window, "_NET_WM_STATE_SHADED", shaded)
    500500
    501501
     502
     503WINDOW_ENHANCERS = []
     504def add_window_hooks(window):
     505    global WINDOW_ENHANCERS
     506    for x in WINDOW_ENHANCERS:
     507        x(window)
     508    log.warn("add_window_hooks(%s) added %s", window, WINDOW_ENHANCERS)
     509
     510
    502511def get_info():
    503512    from xpra.platform.gui import get_info_base
    504513    i = get_info_base()
     
    516525    return i
    517526
    518527
     528class XI2_Window(object):
     529    def __init__(self, xi2, window):
     530        log.warn("XI2_Window(%s, %s)", xi2, window)
     531        self.xi2 = xi2
     532        self.window = window
     533        window.do_motion_notify_event = self.do_motion_notify_event
     534
     535    def do_motion_notify_event(self, event):
     536        log("do_motion_notify_event(%s)", event)
     537        #find the motion events in the xi2 event list:
     538        events = self.xi2.find_events("XI_Motion")
     539        log.warn("events=%s", events)
     540        self.xi2.reset_events()
     541
     542
     543
    519544class ClientExtras(object):
    520545    def __init__(self, client, opts):
    521546        self.client = client
     
    528553        self.x11_filter = None
    529554        if client.xsettings_enabled:
    530555            self.setup_xprops()
     556        if client.input_devices=="xi":
     557            self.setup_xi()
    531558        self.setup_dbus_signals()
    532559
    533560    def ready(self):
     
    565592                bus._clean_up_signal_match(self.upower_sleeping_match)
    566593            if self.login1_match:
    567594                bus._clean_up_signal_match(self.login1_match)
     595        global WINDOW_METHOD_OVERRIDES
     596        WINDOW_METHOD_OVERRIDES = {}
    568597
    569598    def resuming_callback(self, *args):
    570599        eventlog("resuming_callback%s", args)
     
    647676        except ImportError as e:
    648677            log.error("failed to load X11 properties/settings bindings: %s - root window properties will not be propagated", e)
    649678
     679    def setup_xi(self):
     680        from xpra.gtk_common.error import xsync
     681        def enable_xi2():
     682            try:
     683                with xsync:
     684                    self.init_x11_filter()
     685                    xi2.select_xi2_events()
     686            except Exception as e:
     687                log("enable_xi2()", exc_info=True)
     688                log.error("Error: cannot enable XI2 events")
     689                log.error(" %s", e)
     690            else:
     691                #register our enhanced event handlers:
     692                self.add_xi2_method_overrides(xi2)
     693        with xsync:
     694            try:
     695                from xpra.x11.bindings.xi2_bindings import X11XI2Bindings   #@UnresolvedImport
     696                xi2 = X11XI2Bindings()
     697                xi2.gdk_inject()
     698                #this would trigger warnings with our temporary opengl windows:
     699                #only enable it after we have connected:
     700                self.client.after_handshake(enable_xi2)
     701            except Exception as e:
     702                log("setup_xi()", exc_info=True)
     703                log.error("Error: failed to load the XI2 bindings")
     704                log.error(" %s", e)
     705
     706    def add_xi2_method_overrides(self, xi2):
     707        global WINDOW_ENHANCERS
     708        def add_xi2_to_window(window):
     709            XI2_Window(xi2, window)
     710        WINDOW_ENHANCERS = [add_xi2_to_window]
     711
     712
    650713    def _get_xsettings(self):
    651714        try:
    652715            return self._xsettings_watcher.get_settings()
  • xpra/scripts/config.py

     
    489489                    "dbus-launch"       : str,
    490490                    "webcam"            : str,
    491491                    "mousewheel"        : str,
     492                    "input-devices"     : str,
    492493                    #ssl options:
    493494                    "ssl"               : str,
    494495                    "ssl-key"           : str,
     
    619620                  "quality", "min-quality", "speed", "min-speed",
    620621                  "compression_level",
    621622                  "dpi", "video-scaling", "auto-refresh-delay",
    622                   "webcam", "mousewheel", "pings",
     623                  "webcam", "mousewheel", "input-devices", "pings",
    623624                  "tray", "keyboard-sync", "cursors", "bell", "notifications",
    624625                  "xsettings", "system-tray", "sharing",
    625626                  "delay-tray", "windows", "readonly",
     
    811812                    "dbus-launch"       : "dbus-launch --close-stderr",
    812813                    "webcam"            : ["auto", "no"][OSX],
    813814                    "mousewheel"        : "on",
     815                    "input-devices"     : "auto",
    814816                    #ssl options:
    815817                    "ssl"               : "auto",
    816818                    "ssl-key"           : "",
  • xpra/scripts/main.py

     
    562562    group.add_option("--mousewheel", action="store",
    563563                      dest="mousewheel", default=defaults.mousewheel,
    564564                      help="Mouse wheel forwarding, can be used to disable the device or invert some axes. Default: %s." % defaults.webcam)
     565    from xpra.platform.features import INPUT_DEVICES
     566    if len(INPUT_DEVICES)>1:
     567        group.add_option("--input-devices", action="store", metavar="APINAME",
     568                          dest="input_devices", default=defaults.input_devices,
     569                          help="Which API to use for input devices. Default: %s." % defaults.input_devices)
     570    else:
     571        ignore({"input-devices" : INPUT_DEVICES[0]})
    565572    legacy_bool_parse("global-menus")
    566573    group.add_option("--global-menus", action="store",
    567574                      dest="global_menus", default=defaults.global_menus, metavar="yes|no",
  • xpra/x11/bindings/core_bindings.pyx

     
    3333    ctypedef int Bool
    3434
    3535    Atom XInternAtom(Display * display, char * atom_name, Bool only_if_exists)
     36    char *XGetAtomName(Display *display, Atom atom)
    3637
    3738    int XFree(void * data)
    3839
     
    8384    def get_xatom(self, str_or_int):
    8485        return self.xatom(str_or_int)
    8586
     87    def XGetAtomName(self, Atom atom):
     88        v = XGetAtomName(self.display, atom)
     89        return v[:]
     90
     91
    8692    def get_error_text(self, code):
    8793        assert self.display!=NULL, "display is closed"
    8894        if type(code)!=int:
  • xpra/x11/bindings/window_bindings.pyx

     
    8181        pass
    8282
    8383    Atom XInternAtom(Display * display, char * atom_name, Bool only_if_exists)
    84     char *XGetAtomName(Display *display, Atom atom)
    8584
    8685    Window XDefaultRootWindow(Display * display)
    8786
     
    461460        return XDefaultRootWindow(self.display)
    462461
    463462
    464     cpdef XGetAtomName(self, Atom atom):
    465         v = XGetAtomName(self.display, atom)
    466         return v[:]
    467 
    468463    def MapWindow(self, Window xwindow):
    469464        XMapWindow(self.display, xwindow)
    470465
  • xpra/x11/bindings/xi2_bindings.pyx

     
     1# This file is part of Xpra.
     2# Copyright (C) 2017 Antoine Martin <antoine@devloop.org.uk>
     3# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
     4# later version. See the file COPYING for details.
     5
     6import os
     7import time
     8import collections
     9
     10from xpra.log import Logger
     11log = Logger("x11", "bindings", "xinput")
     12
     13from xpra.x11.gtk2.common import X11Event
     14
     15from libc.stdint cimport uintptr_t
     16
     17
     18###################################
     19# Headers, python magic
     20###################################
     21cdef extern from "string.h":
     22    void* memset(void * ptr, int value, size_t num)
     23
     24cdef extern from "X11/Xutil.h":
     25    pass
     26
     27######
     28# Xlib primitives and constants
     29######
     30
     31include "constants.pxi"
     32ctypedef unsigned long CARD32
     33
     34cdef extern from "X11/Xlib.h":
     35    ctypedef struct Display:
     36        pass
     37
     38    ctypedef CARD32 XID
     39    ctypedef int Bool
     40    ctypedef int Status
     41    ctypedef CARD32 Atom
     42    ctypedef XID Window
     43    ctypedef CARD32 Time
     44
     45    ctypedef struct XGenericEventCookie:
     46        int            type     # of event. Always GenericEvent
     47        unsigned long  serial
     48        Bool           send_event
     49        Display        *display
     50        int            extension    #major opcode of extension that caused the event
     51        int            evtype       #actual event type
     52        unsigned int   cookie
     53        void           *data
     54
     55    Atom XInternAtom(Display * display, char * atom_name, Bool only_if_exists)
     56    int XFree(void * data)
     57
     58    Bool XQueryExtension(Display * display, char *name,
     59                         int *major_opcode_return, int *first_event_return, int *first_error_return)
     60
     61    Bool XGetEventData(Display *display, XGenericEventCookie *cookie)
     62    void XFreeEventData(Display *display, XGenericEventCookie *cookie)
     63
     64    Window XDefaultRootWindow(Display * display)
     65
     66    Bool XQueryPointer(Display *display, Window w, Window *root_return, Window *child_return, int *root_x_return, int *root_y_return,
     67                       int *win_x_return, int *win_y_return, unsigned int *mask_return)
     68    int XFlush(Display *dpy)
     69
     70cdef extern from "X11/extensions/XInput2.h":
     71    int XI_LASTEVENT
     72    int XI_DeviceChanged
     73    int XI_KeyPress
     74    int XI_KeyRelease
     75    int XI_ButtonPress
     76    int XI_ButtonRelease
     77    int XI_Motion
     78    int XI_Enter
     79    int XI_Leave
     80    int XI_FocusIn
     81    int XI_FocusOut
     82    int XI_HierarchyChanged
     83    int XI_PropertyEvent
     84    int XI_RawKeyPress
     85    int XI_RawKeyRelease
     86    int XI_RawButtonPress
     87    int XI_RawButtonRelease
     88    int XI_RawMotion
     89    int XI_TouchBegin
     90    int XI_TouchUpdate
     91    int XI_TouchEnd
     92    int XI_TouchOwnership
     93    int XI_RawTouchBegin
     94    int XI_RawTouchUpdate
     95    int XI_RawTouchEnd
     96
     97    int XIMasterPointer
     98    int XIMasterKeyboard
     99    int XISlavePointer
     100    int XISlaveKeyboard
     101    int XIFloatingSlave
     102
     103    int XIButtonClass
     104    int XIKeyClass
     105    int XIValuatorClass
     106    int XIScrollClass
     107    int XITouchClass   
     108
     109    int XIAllDevices
     110    int XIAllMasterDevices
     111
     112    ctypedef struct XIValuatorState:
     113        int           mask_len
     114        unsigned char *mask
     115        double        *values
     116
     117    ctypedef struct XIEvent:
     118        int           type
     119        unsigned long serial
     120        Bool          send_event
     121        Display       *display
     122        int           extension
     123        int           evtype
     124        Time          time
     125
     126    ctypedef struct XIRawEvent:
     127        int           type      #GenericEvent
     128        unsigned long serial
     129        Bool          send_event
     130        Display       *display
     131        int           extension #XI extension offset
     132        int           evtype    #XI_RawKeyPress, XI_RawKeyRelease, etc
     133        Time          time
     134        int           deviceid
     135        int           sourceid
     136        int           detail
     137        int           flags
     138        XIValuatorState valuators
     139        double        *raw_values
     140
     141    ctypedef struct XIButtonState:
     142        int           mask_len
     143        unsigned char *mask
     144
     145    ctypedef struct XIModifierState:
     146        int    base
     147        int    latched
     148        int    locked
     149        int    effective
     150
     151    ctypedef XIModifierState XIGroupState
     152
     153    ctypedef struct XIDeviceEvent:
     154        int           type
     155        unsigned long serial
     156        Bool          send_event
     157        Display       *display
     158        int           extension
     159        int           evtype
     160        Time          time
     161        int           deviceid
     162        int           sourceid
     163        int           detail
     164        Window        root
     165        Window        event
     166        Window        child
     167        double        root_x
     168        double        root_y
     169        double        event_x
     170        double        event_y
     171        int           flags
     172        XIButtonState       buttons
     173        XIValuatorState     valuators
     174        XIModifierState     mods
     175        XIGroupState        group
     176
     177    ctypedef struct XIHierarchyInfo:
     178        int           deviceid
     179        int           attachment
     180        int           use
     181        Bool          enabled
     182        int           flags
     183
     184    ctypedef struct XIHierarchyEvent:
     185        int           type
     186        unsigned long serial
     187        Bool          send_event
     188        Display       *display
     189        int           extension
     190        int           evtype            #XI_HierarchyChanged
     191        Time          time
     192        int           flags
     193        int           num_info
     194        XIHierarchyInfo *info
     195
     196    ctypedef struct XIEventMask:
     197        int                 deviceid
     198        int                 mask_len
     199        unsigned char*      mask
     200
     201    ctypedef struct XIAnyClassInfo:
     202        int         type
     203        int         sourceid
     204
     205    ctypedef struct XIDeviceInfo:
     206        int                 deviceid
     207        char                *name
     208        int                 use
     209        int                 attachment
     210        Bool                enabled
     211        int                 num_classes
     212        XIAnyClassInfo      **classes
     213
     214    ctypedef struct XIButtonClassInfo:
     215        int         type
     216        int         sourceid
     217        int         num_buttons
     218        Atom        *labels
     219        XIButtonState state
     220
     221    ctypedef struct XIKeyClassInfo:
     222        int         type
     223        int         sourceid
     224        int         num_keycodes
     225        int         *keycodes
     226
     227    ctypedef struct XIValuatorClassInfo:
     228        int         type
     229        int         sourceid
     230        int         number
     231        Atom        label
     232        double      min
     233        double      max
     234        double      value
     235        int         resolution
     236        int         mode
     237
     238    ctypedef struct XIScrollClassInfo:
     239        int         type
     240        int         sourceid
     241        int         number
     242        int         scroll_type
     243        double      increment
     244        int         flags
     245
     246    ctypedef struct XITouchClassInfo:
     247        int         type
     248        int         sourceid
     249        int         mode
     250        int         num_touches
     251
     252    Status XIQueryVersion(Display *display, int *major_version_inout, int *minor_version_inout)
     253    Status XISelectEvents(Display *display, Window win, XIEventMask *masks, int num_masks)
     254    XIDeviceInfo* XIQueryDevice(Display *display, int deviceid, int *ndevices_return)
     255    void XIFreeDeviceInfo(XIDeviceInfo *info)
     256    Atom *XIListProperties(Display *display, int deviceid, int *num_props_return)
     257    Status XIGetProperty(Display *display, int deviceid, Atom property, long offset, long length,
     258                         Bool delete_property, Atom type, Atom *type_return,
     259                         int *format_return, unsigned long *num_items_return,
     260                         unsigned long *bytes_after_return, unsigned char **data)
     261
     262
     263DEF MAX_XI_EVENTS = 64
     264DEF XI_EVENT_MASK_SIZE = (MAX_XI_EVENTS+7)//8
     265
     266XI_EVENT_NAMES = {
     267    XI_DeviceChanged    : "XI_DeviceChanged",
     268    XI_KeyPress         : "XI_KeyPress",
     269    XI_KeyRelease       : "XI_KeyRelease",
     270    XI_ButtonPress      : "XI_ButtonPress",
     271    XI_ButtonRelease    : "XI_ButtonRelease",
     272    XI_Motion           : "XI_Motion",
     273    XI_Enter            : "XI_Enter",
     274    XI_Leave            : "XI_Leave",
     275    XI_FocusIn          : "XI_FocusIn",
     276    XI_FocusOut         : "XI_FocusOut",
     277    XI_HierarchyChanged : "XI_HierarchyChanged",
     278    XI_PropertyEvent    : "XI_PropertyEvent",
     279    XI_RawKeyPress      : "XI_RawKeyPress",
     280    XI_RawKeyRelease    : "XI_RawKeyRelease",
     281    XI_RawButtonPress   : "XI_RawButtonPress",
     282    XI_RawButtonRelease : "XI_RawButtonRelease",
     283    XI_RawMotion        : "XI_RawMotion",
     284    XI_TouchBegin       : "XI_TouchBegin",
     285    XI_TouchUpdate      : "XI_TouchUpdate",
     286    XI_TouchEnd         : "XI_TouchEnd",
     287    XI_TouchOwnership   : "XI_TouchOwnership",
     288    XI_RawTouchBegin    : "XI_RawTouchBegin",
     289    XI_RawTouchUpdate   : "XI_RawTouchUpdate",
     290    XI_RawTouchEnd      : "XI_RawTouchEnd",
     291    }
     292
     293XI_USE = {
     294    XIMasterPointer     : "master pointer",
     295    XIMasterKeyboard    : "master keyboard",
     296    XISlavePointer      : "slave pointer",
     297    XISlaveKeyboard     : "slave keyboard",
     298    XIFloatingSlave     : "floating slave",
     299    }
     300
     301CLASS_INFO = {
     302    XIButtonClass       : "button",
     303    XIKeyClass          : "key",
     304    XIValuatorClass     : "valuator",
     305    XIScrollClass       : "scroll",
     306    XITouchClass        : "touch",
     307    }
     308
     309
     310from core_bindings cimport _X11CoreBindings
     311
     312cdef _X11XI2Bindings singleton = None
     313def X11XI2Bindings():
     314    global singleton
     315    if singleton is None:
     316        singleton = _X11XI2Bindings()
     317    return singleton
     318
     319cdef class _X11XI2Bindings(_X11CoreBindings):
     320
     321    cdef int opcode
     322    cdef object events
     323
     324    def __init__(self):
     325        self.opcode = -1
     326        self.reset_events()
     327
     328    def __repr__(self):
     329        return "X11XI2Bindings(%s)" % self.display_name
     330
     331    def reset_events(self):
     332        self.events = collections.deque(maxlen=100)
     333
     334    def find_events(self, event_name):
     335        found = 0
     336        matches = []
     337        for x in reversed(self.events):
     338            if x.name==event_name and (found==0 or found==x.window):
     339                matches.append(x)
     340                found = x.window
     341            elif found:
     342                break
     343        return matches
     344
     345    cdef int get_xi_opcode(self, int major=2, int minor=2):
     346        if self.opcode!=-1:
     347            return self.opcode
     348        cdef int opcode, event, error
     349        if not XQueryExtension(self.display, "XInputExtension", &opcode, &event, &error):
     350            log.warn("Warning: XI2 events are not supported")
     351            self.opcode = 0
     352            return 0
     353        cdef int rmajor = major, rminor = minor
     354        cdef int rc = XIQueryVersion(self.display, &rmajor, &rminor)
     355        if rc == BadRequest:
     356            log.warn("Warning: no XI2 %i.%i support,", major, minor)
     357            log.warn(" server supports version %i.%i only", rmajor, rminor)
     358            self.opcode = 0
     359            return 0
     360        elif rc:
     361            log.warn("Warning: Xlib bug querying XI2, code %i", rc)
     362            self.opcode = 0
     363            return 0
     364        self.opcode = opcode
     365        log("get_xi_opcode%s=%i", (major, minor), opcode)
     366        return opcode
     367
     368    cdef register_parser(self):
     369        log("register_parser()")
     370        if self.opcode>0:
     371            from xpra.x11.gtk2.gdk_bindings import add_x_event_parser
     372            add_x_event_parser(self.opcode, self.parse_xi_event)
     373
     374    cdef register_gdk_events(self):
     375        log("register_gdk_events()")
     376        if self.opcode<=0:
     377            return
     378        global XI_EVENT_NAMES
     379        from xpra.x11.gtk2.gdk_bindings import add_x_event_signal, add_x_event_type_name
     380        for e, xi_event_name in {
     381            XI_DeviceChanged    : "device-changed",
     382            XI_KeyPress         : "key-press",
     383            XI_KeyRelease       : "key-release",
     384            XI_ButtonPress      : "button-press",
     385            XI_ButtonRelease    : "button-release",
     386            XI_Motion           : "motion",
     387            XI_Enter            : "enter",
     388            XI_Leave            : "leave",
     389            XI_FocusIn          : "focus-in",
     390            XI_FocusOut         : "focus-out",
     391            XI_HierarchyChanged : "focus-changed",
     392            XI_PropertyEvent    : "property-event",
     393            XI_RawKeyPress      : "raw-key-press",
     394            XI_RawKeyRelease    : "raw-key-release",
     395            XI_RawButtonPress   : "raw-button-press",
     396            XI_RawButtonRelease : "raw-button-release",
     397            XI_RawMotion        : "raw-motion",
     398            XI_TouchBegin       : "touch-begin",
     399            XI_TouchUpdate      : "touch-update",
     400            XI_TouchEnd         : "touch-end",
     401            XI_TouchOwnership   : "touch-ownership",
     402            XI_RawTouchBegin    : "raw-touch-begin",
     403            XI_RawTouchUpdate   : "raw-touch-update",
     404            XI_RawTouchEnd      : "raw-touch-end",
     405            }.items():
     406            event = self.opcode+e
     407            add_x_event_signal(event, ("xi-%s" % xi_event_name, None))
     408            name = XI_EVENT_NAMES[e]
     409            add_x_event_type_name(event, name)
     410
     411    def select_xi2_events(self):
     412        cdef Window win = XDefaultRootWindow(self.display)
     413        log("select_xi2_events() root window=%#x", win)
     414        assert XI_LASTEVENT<MAX_XI_EVENTS, "bug: source needs to be updated, XI_LASTEVENT=%i" % XI_LASTEVENT
     415        cdef XIEventMask evmasks[1]
     416        cdef unsigned char mask1[XI_EVENT_MASK_SIZE]
     417        memset(mask1, 0, XI_EVENT_MASK_SIZE)
     418        #define XISetMask(ptr, event)   (((unsigned char*)(ptr))[(event)>>3] |=  (1 << ((event) & 7)))
     419        #XISetMask(mask1, XI_RawMotion)
     420        for e in (
     421            XI_KeyPress, XI_KeyRelease,
     422            XI_Motion,
     423            XI_HierarchyChanged,
     424            XI_ButtonPress, XI_ButtonRelease,
     425            XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd,
     426            ):
     427            mask1[e>>3] |= (1<< (e & 0x7))
     428        evmasks[0].deviceid = XIAllDevices  #XIAllMasterDevices    #XIAllDevices
     429        evmasks[0].mask_len = XI_EVENT_MASK_SIZE
     430        evmasks[0].mask = mask1
     431        XISelectEvents(self.display, win, evmasks, 1)
     432        XFlush(self.display)
     433
     434    def parse_xi_event(self, display, uintptr_t _cookie):
     435        log("parse_xi_event(%s)", _cookie)
     436        cdef XGenericEventCookie *cookie = <XGenericEventCookie*> _cookie
     437        cdef XIDeviceEvent *device_e
     438        cdef XIHierarchyEvent * hierarchy_e
     439        cdef XIEvent *xie
     440        cdef XIRawEvent *raw
     441        cdef int i = 0, j = 0
     442        if not XGetEventData(self.display, cookie):
     443            return None
     444        xie = <XIEvent*> cookie.data
     445        device_e = <XIDeviceEvent*> cookie.data
     446        cdef int xi_type = cookie.evtype
     447        etype = self.opcode+xi_type
     448        global XI_EVENT_NAMES
     449        event_name = XI_EVENT_NAMES.get(xi_type)
     450        if not event_name:
     451            log("unknown XI2 event code: %i", xi_type)
     452            return None
     453
     454        pyev = X11Event(event_name)
     455        pyev.type = etype
     456        pyev.display = display
     457        pyev.send_event = bool(xie.send_event)
     458        pyev.serial = xie.serial
     459        pyev.time = int(xie.time)
     460        pyev.window = XDefaultRootWindow(self.display)
     461
     462        if xi_type in (XI_KeyPress, XI_KeyRelease,
     463                       XI_ButtonPress, XI_ButtonRelease,
     464                       XI_Motion,
     465                       XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd):
     466            device = <XIDeviceEvent*> cookie.data
     467            #pyev.source = device.sourceid    #always 0
     468            pyev.device = device.deviceid
     469            pyev.detail = device.detail
     470            pyev.flags = device.flags
     471            pyev.window = int(device.child or device.event or device.root)
     472            pyev.root_x = device.root_x
     473            pyev.root_y = device.root_y
     474            pyev.x = device.event_x
     475            pyev.y = device.event_y
     476            #mask = []
     477            #values = []
     478            #raw_values = []
     479            #if False:
     480            #    for i in range(device.valuators.mask_len):
     481            #        if device.valuators.mask[i//8] & (1 << (i & 0x7)):
     482            #            mask.append(i)
     483            #            values.append(j)
     484            #            raw_values.append(device.valuators.values[j])
     485            #            j += 1
     486            #pyev.valuators = {
     487            #    "mask"      : mask,
     488            #    "values"    : values,
     489            #    }
     490        elif xi_type == XI_HierarchyChanged:
     491            pass
     492            #hierarchy_e = <XIHierarchyEvent*> cookie.data
     493            #pyev.flags = hierarchy_e.flags
     494            #info = {}
     495            #for i in range(hierarchy_e.num_info):
     496            #
     497        XFreeEventData(self.display, cookie)
     498        self.events.append(pyev)
     499        return pyev
     500
     501    def get_devices(self, show_all=False, show_disabled=False):
     502        global XI_USE
     503        cdef int ndevices, i, j
     504        cdef XIDeviceInfo *devices
     505        cdef XIDeviceInfo *device
     506        cdef XIAnyClassInfo *clazz
     507        if show_all:
     508            device_types = XIAllDevices
     509        else:
     510            device_types = XIAllMasterDevices
     511        devices = XIQueryDevice(self.display, device_types, &ndevices)
     512        dinfo = {}
     513        for i in range(ndevices):
     514            device = &devices[i]
     515            if not device.enabled and not show_disabled:
     516                continue
     517            info = {
     518                "name"          : device.name,
     519                "id"            : device.deviceid,
     520                "use"           : XI_USE.get(device.use, "unknown use: %i" % device.use),
     521                "attachment"    : device.attachment,
     522                "enabled"       : device.enabled,
     523                }
     524            classes = {}
     525            for j in range(device.num_classes):
     526                clazz = device.classes[j]
     527                classes[j] = self.get_class_info(clazz)
     528            info["classes"] = classes
     529            dinfo[i] = info
     530        XIFreeDeviceInfo(devices)
     531        return dinfo
     532
     533    cdef get_class_info(self, XIAnyClassInfo *class_info):
     534        cdef int i
     535        cdef XIButtonClassInfo *button
     536        cdef XIKeyClassInfo *key
     537        cdef XIValuatorClassInfo *valuator
     538        cdef XIScrollClassInfo *scroll
     539        cdef XITouchClassInfo *touch
     540        info = {
     541            "type"      : CLASS_INFO.get(class_info.type, "unknown type: %i" % class_info.type),
     542            "sourceid"  : class_info.sourceid,
     543            }
     544        if class_info.type==XIButtonClass:
     545            button = <XIButtonClassInfo*> class_info
     546            buttons = []
     547            for i in range(button.num_buttons):
     548                if button.labels[i]>0:
     549                    buttons.append(self.XGetAtomName(button.labels[i]))
     550            info["buttons"] = buttons
     551            #XIButtonState state
     552        elif class_info.type==XIKeyClass:
     553            key = <XIKeyClassInfo*> class_info
     554            keys = []
     555            for i in range(key.num_keycodes):
     556                keys.append(key.keycodes[i])
     557        elif class_info.type==XIValuatorClass:
     558            valuator = <XIValuatorClassInfo*> class_info
     559            info.update({
     560                "number"    : valuator.number,
     561                "min"       : valuator.min,
     562                "max"       : valuator.max,
     563                "value"     : valuator.value,
     564                "resolution": valuator.resolution,
     565                "mode"      : valuator.mode,
     566                })
     567            if valuator.label:
     568                info["label"] = self.XGetAtomName(valuator.label)
     569        elif class_info.type==XIScrollClass:
     570            scroll = <XIScrollClassInfo*> class_info
     571            info.update({
     572                "number"        : scroll.number,
     573                "scroll-type"   : scroll.scroll_type,
     574                "increment"     : scroll.increment,
     575                "flags"         : scroll.flags,
     576                })
     577        elif class_info.type==XITouchClass:
     578            touch = <XITouchClassInfo*> class_info
     579            info.update({
     580                "mode"          : touch.mode,
     581                "num-touches"   : touch.num_touches,
     582                })
     583        return info
     584
     585
     586    def gdk_inject(self):
     587        self.get_xi_opcode()
     588        log.info("XInput Devices:")
     589        from xpra.util import print_nested_dict
     590        print_nested_dict(self.get_devices(), print_fn=log.info)
     591        self.register_parser()
     592        self.register_gdk_events()
     593        #self.select_xi2_events()