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-v3.patch

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

updated patch with device discovery

  • setup.py

     
    914914                   "xpra/x11/bindings/core_bindings.c",
    915915                   "xpra/x11/bindings/posix_display_source.c",
    916916                   "xpra/x11/bindings/ximage.c",
     917                   "xpra/x11/bindings/xi2_bindings.c",
    917918                   "xpra/platform/win32/propsys.cpp",
    918919                   "xpra/platform/darwin/gdk_bindings.c",
    919920                   "xpra/net/bencode/cython_bencode.c",
     
    17341735                ["xpra/x11/bindings/ximage.pyx"],
    17351736                **pkgconfig("x11", "xcomposite", "xdamage", "xext")
    17361737                ))
     1738    cython_add(Extension("xpra.x11.bindings.xi2_bindings",
     1739                ["xpra/x11/bindings/xi2_bindings.pyx"],
     1740                **pkgconfig("x11", "xi")
     1741                ))
    17371742
    17381743toggle_packages(gtk_x11_ENABLED, "xpra.x11.gtk_x11")
    17391744if gtk_x11_ENABLED:
  • xpra/client/client_window_base.py

     
    644644        #overriden in GTKClientWindowBase
    645645        return self._id
    646646
     647    def do_xi_motion(self, *args):
     648        log.warn("do_xi_motion%s", args)
     649
     650
    647651    def do_motion_notify_event(self, event):
    648652        if self._client.readonly:
    649653            return
  • xpra/client/gtk_base/gtk_client_window_base.py

     
    3636                       MOVERESIZE_SIZE_LEFT, MOVERESIZE_MOVE)
    3737
    3838from xpra.gtk_common.gobject_compat import import_gtk, import_gdk, import_cairo, import_pixbufloader, get_xid
    39 from xpra.gtk_common.gobject_util import no_arg_signal
     39from xpra.gtk_common.gobject_util import no_arg_signal, one_arg_signal
    4040from xpra.gtk_common.gtk_util import (get_pixbuf_from_data, get_default_root_window, is_realized,
    4141    WINDOW_POPUP, WINDOW_TOPLEVEL, GRAB_STATUS_STRING, GRAB_SUCCESS, SCROLL_UP, SCROLL_DOWN, SCROLL_LEFT, SCROLL_RIGHT)
    4242from xpra.gtk_common.keymap import KEY_TRANSLATIONS
     
    145145
    146146    __common_gsignals__ = {
    147147        "state-updated"         : no_arg_signal,
     148        "xi-motion"             : one_arg_signal,
    148149        }
    149150
    150151    #maximum size of the actual window:
  • xpra/client/ui_client_base.py

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

     
    1515from xpra.gtk_common.error import trap, XError
    1616from xpra.x11.gtk2.common import X11Event
    1717from xpra.monotonic_time cimport monotonic_time
     18from xpra.util import csv
    1819
    1920from xpra.log import Logger
    2021log = Logger("x11", "bindings", "gtk")
     
    819820    verbose("names_to_event_type=%s", names_to_event_type)
    820821
    821822def set_debug_events():
     823    global debug_route_events
    822824    XPRA_X11_DEBUG_EVENTS = os.environ.get("XPRA_X11_DEBUG_EVENTS", "")
    823825    debug_set = set()
    824826    ignore_set = set()
     
    836838        elif name in names_to_event_type:
    837839            events = [name]
    838840        else:
    839             log.warn("unknown X11 debug event type: %s", name)
     841            log("unknown X11 debug event type: %s", name)
    840842            continue
    841843        #add to correct set:
    842844        for e in events:
    843845            event_set.add(e)
    844846    events = debug_set.difference(ignore_set)
     847    debug_route_events = [names_to_event_type.get(x) for x in events]
    845848    if len(events)>0:
    846         log.warn("debugging of X11 events enabled for: %s", ", ".join(events))
    847     debug_route_events = [names_to_event_type.get(x) for x in events]
     849        log.warn("debugging of X11 events enabled for:")
     850        log.warn(" %s", csv(events))
     851        log.warn(" event codes: %s", csv(debug_route_events))
    848852
    849853
    850854x_event_parsers = {}
     
    911915            log.info("  not forwarding to %s handler, it has no %s signal (it has: %s)",
    912916                type(handler).__name__, signal, signals)
    913917
    914 cdef _route_event(event, signal, parent_signal):
     918cdef _route_event(int etype, event, signal, parent_signal):
    915919    # Sometimes we get GDK events with event.window == None, because they are
    916920    # for windows we have never created a GdkWindow object for, and GDK
    917921    # doesn't do so just for this event.  As far as I can tell this only
     
    918922    # matters for override redirect windows when they disappear, and we don't
    919923    # care about those anyway.
    920924    global debug_route_events, x_event_type_names
    921     DEBUG = event.type in debug_route_events
     925    DEBUG = etype in debug_route_events
    922926    if DEBUG:
    923         log.info("%s event %#x : %s", x_event_type_names.get(event.type, event.type), event.serial, event)
     927        log.info("%s event %#x : %s", x_event_type_names.get(etype, etype), event.serial, event)
    924928    handlers = None
    925929    if event.window is None:
    926930        if DEBUG:
    927931            log.info("  event.window is None, ignoring")
    928         assert event.type in (UnmapNotify, DestroyNotify), \
    929                 "event window is None for event type %s!" % (x_event_type_names.get(event.type, event.type))
     932        assert etype in (UnmapNotify, DestroyNotify), \
     933                "event window is None for event type %s!" % (x_event_type_names.get(etype, etype))
    930934    elif event.window is event.delivered_to:
    931935        if signal is not None:
    932936            window = event.window
     
    933937            if DEBUG:
    934938                log.info("  delivering event to window itself: %#x  (signal=%s)", window.xid, signal)
    935939            handlers = window.get_data(_ev_receiver_key)
    936             _maybe_send_event(DEBUG, handlers, signal, event, "window %s" % window.xid)
     940            _maybe_send_event(DEBUG, handlers, signal, event, "window %#x" % window.xid)
    937941        elif DEBUG:
    938942            log.info("  received event on window itself but have no signal for that")
    939943    else:
     
    942946            if DEBUG:
    943947                log.info("  delivering event to parent window: %#x (signal=%s)", window.xid, parent_signal)
    944948            handlers = window.get_data(_ev_receiver_key)
    945             _maybe_send_event(DEBUG, handlers, parent_signal, event, "parent window %s" % window.xid)
     949            _maybe_send_event(DEBUG, handlers, parent_signal, event, "parent window %#x" % window.xid)
    946950        else:
    947951            if DEBUG:
    948952                log.info("  received event on a parent window but have no parent signal")
     
    10021006    etype = pyev.type
    10031007    try:
    10041008        global x_event_signals, x_event_type_names
    1005         my_events = x_event_signals
    1006         event_args = my_events.get(etype)
     1009        event_args = x_event_signals.get(etype)
     1010        #log("signals(%s)=%s", pyev, event_args)
    10071011        if event_args is not None:
    10081012            signal, parent_signal = event_args
    1009             _route_event(pyev, signal, parent_signal)
     1013            _route_event(etype, pyev, signal, parent_signal)
    10101014        log("x_event_filter event=%s/%s took %.1fms", event_args, x_event_type_names.get(etype, etype), 1000.0*(monotonic_time()-start))
    10111015    except (KeyboardInterrupt, SystemExit):
    10121016        verbose("exiting on KeyboardInterrupt/SystemExit")
     
    10421046        if parser:
    10431047            #log("calling %s%s", parser, (d, <uintptr_t> &e.xcookie))
    10441048            pyev = parser(d, <uintptr_t> &e.xcookie)
     1049            log.info("pyev=%s (window=%#x)", pyev, e.xany.window)
    10451050            pyev.window = _gw(d, pyev.window)
     1051            pyev.delivered_to = pyev.window
    10461052            return pyev
    10471053        return None
    10481054