xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

fdi2iclass.py (6981B)


      1 #!/usr/bin/python
      2 #
      3 # Convert xorg keys from hal FDIs files to xorg.conf InputClass sections.
      4 # Modified from Martin Pitt's original fdi2mpi.py script:
      5 # http://cgit.freedesktop.org/media-player-info/tree/tools/fdi2mpi.py
      6 #
      7 # (C) 2010 Dan Nicholson
      8 # (C) 2009 Canonical Ltd.
      9 # Author: Dan Nicholson <dbn.lists@gmail.com>
     10 # Author: Martin Pitt <martin.pitt@ubuntu.com>
     11 #
     12 # Permission is hereby granted, free of charge, to any person obtaining a copy
     13 # of this software and associated documentation files (the "Software"), to
     14 # deal in the Software without restriction, including without limitation the
     15 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     16 # sell copies of the Software, and to permit persons to whom the Software is
     17 # fur- nished to do so, subject to the following conditions:
     18 #
     19 #  The above copyright notice and this permission notice shall be included in
     20 #  all copies or substantial portions of the Software.
     21 #
     22 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23 #  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24 #  FIT- NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     25 #  THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     26 #  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
     27 #  NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     28 
     29 import sys, xml.dom.minidom
     30 
     31 # dict converting <match> tags to Match* entries
     32 match_table = {
     33     'info.product': 'MatchProduct',
     34     'input.product': 'MatchProduct',
     35     'info.vendor': 'MatchVendor',
     36     'input.vendor': 'MatchVendor',
     37     'info.device': 'MatchDevicePath',
     38     'linux.device_file': 'MatchDevicePath',
     39     '/org/freedesktop/Hal/devices/computer:system.kernel.name': 'MatchOS',
     40     '@info.parent:pnp.id': 'MatchPnPID',
     41 }
     42 
     43 # dict converting info.capabilities list to Match* entries
     44 cap_match_table = {
     45     'input.keys': 'MatchIsKeyboard',
     46     'input.keyboard': 'MatchIsKeyboard',
     47     'input.keypad': 'MatchIsKeyboard',
     48     'input.mouse': 'MatchIsPointer',
     49     'input.joystick': 'MatchIsJoystick',
     50     'input.tablet': 'MatchIsTablet',
     51     'input.touchpad': 'MatchIsTouchpad',
     52     'input.touchscreen': 'MatchIsTouchscreen',
     53 }
     54 
     55 def device_glob(path):
     56     '''Convert a contains device path to a glob entry'''
     57     if path[0] != '/':
     58         path = '*' + path
     59     return path + '*'
     60 
     61 def parse_match(node):
     62     '''Parse a <match> tag to a tuple with InputClass values'''
     63     match = None
     64     value = None
     65     booltype = False
     66 
     67     # see what type of key we have
     68     if node.attributes.has_key('key'):
     69         key = node.attributes['key'].nodeValue
     70         if key in match_table:
     71             match = match_table[key]
     72         elif key == 'info.capabilities':
     73             booltype = True
     74 
     75     # bail out now if it's unrecognized
     76     if not match and not booltype:
     77         return (match, value)
     78 
     79     if node.attributes.has_key('string'):
     80         value = node.attributes['string'].nodeValue
     81     elif node.attributes.has_key('contains'):
     82         value = node.attributes['contains'].nodeValue
     83         if match == 'MatchDevicePath':
     84             value = device_glob(value)
     85         elif booltype and value in cap_match_table:
     86             match = cap_match_table[value]
     87             value = 'yes'
     88     elif node.attributes.has_key('string_outof'):
     89         value = node.attributes['string_outof'].nodeValue.replace(';','|')
     90     elif node.attributes.has_key('contains_outof'):
     91         all_values = node.attributes['contains_outof'].nodeValue.split(';')
     92         for v in all_values:
     93             if match == 'MatchDevicePath':
     94                 v = device_glob(v)
     95             elif match == 'MatchPnPID' and len(v) < 7:
     96                 v += '*'
     97             if value:
     98                 value += '|' + v
     99             else:
    100                 value = v
    101 
    102     return (match, value)
    103 
    104 def parse_options(node):
    105     '''Parse the x11_* options and return InputClass entries'''
    106     driver = ''
    107     ignore = False
    108     options = []
    109     for n in node.childNodes:
    110         if n.nodeType != xml.dom.minidom.Node.ELEMENT_NODE:
    111             continue
    112 
    113         tag = n.tagName
    114         key = n.attributes['key'].nodeValue
    115         value = ''
    116 
    117         if n.hasChildNodes():
    118             content_node = n.childNodes[0]
    119             assert content_node.nodeType == xml.dom.Node.TEXT_NODE
    120             value = content_node.nodeValue
    121 
    122         if tag == 'match':
    123             continue
    124         assert tag in ('addset', 'merge', 'append', 'remove')
    125 
    126         if tag == 'remove' and key == 'input.x11_driver':
    127             ignore = True
    128         elif key == 'input.x11_driver':
    129             driver = value
    130         elif key.startswith('input.x11_options.'):
    131             option = key.split('.', 2)[2]
    132             options.append((option, value))
    133 
    134     return (driver, ignore, options)
    135 
    136 def is_match_node(node):
    137     '''Check if a node is a <match> element'''
    138     return node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE and \
    139         node.tagName == 'match'
    140 
    141 def parse_all_matches(node):
    142     '''Parse a x11 match tag and any parents that don't supply their
    143     own options'''
    144     matches = []
    145 
    146     while True:
    147         (key, value) = parse_match(node)
    148         if key and value:
    149             matches.append((key, value))
    150 
    151         # walk up to a parent match node
    152         node = node.parentNode
    153         if node == None or not is_match_node(node):
    154             break
    155 
    156         # leave if there other options at this level
    157         children = set([n.tagName for n in node.childNodes
    158                         if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE])
    159         if children & set(['addset', 'merge', 'append']):
    160             break
    161 
    162     return matches
    163 
    164 # stupid counter to give "unique" rule names
    165 num_sections = 1
    166 def print_section(matches, driver, ignore, options):
    167     '''Print a valid InputClass section to stdout'''
    168     global num_sections
    169     print 'Section "InputClass"'
    170     print '\tIdentifier "Converted Class %d"' % num_sections
    171     num_sections += 1
    172     for m, v in matches:
    173         print '\t%s "%s"' % (m, v)
    174     if driver:
    175         print '\tDriver "%s"' % driver
    176     if ignore:
    177         print '\tOption "Ignore" "yes"'
    178     for o, v in options:
    179         print '\tOption "%s" "%s"' % (o, v)
    180     print 'EndSection'
    181 
    182 def parse_fdi(fdi):
    183     '''Parse x11 matches from fdi'''
    184     # find all <match> leaf nodes
    185     num = 0
    186     for match_node in fdi.getElementsByTagName('match'):
    187         children = set([n.tagName for n in match_node.childNodes
    188                 if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE])
    189 
    190         # see if there are any options at this level
    191         (driver, ignore, options) = parse_options(match_node)
    192         if not driver and not ignore and not options:
    193             continue
    194 
    195         matches = parse_all_matches(match_node)
    196         if num > 0:
    197             print
    198         print_section(matches, driver, ignore, options)
    199         num += 1
    200 
    201 for f in sys.argv[1:]:
    202     parse_fdi(xml.dom.minidom.parse(f))