summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Linhart <chris@demorecorder.com>2017-01-25 10:31:18 +0100
committerChristian Linhart <chris@demorecorder.com>2017-03-11 10:49:27 +0100
commit4aa40fbd5e05833b72327ea37421b09dff246732 (patch)
treed64322ef12b8c29517646e77bc613fb9f366c26e
parent89b022fdacfe7b39b2122c6ec1a4097767b1ee29 (diff)
add support for eventstruct
eventstruct is a new xml element that allows to use events as part of requests. This is, e.g., needed by the SendExtensionEvent request of the XINPUT extension. Signed-off-by: Christian Linhart <chris@demorecorder.com>
-rw-r--r--doc/xml-xcb.txt29
-rw-r--r--src/xcb.xsd17
-rw-r--r--xcbgen/matcher.py7
-rw-r--r--xcbgen/state.py41
-rw-r--r--xcbgen/xtypes.py87
5 files changed, 181 insertions, 0 deletions
diff --git a/doc/xml-xcb.txt b/doc/xml-xcb.txt
index 9cef1de..f5b9aed 100644
--- a/doc/xml-xcb.txt
+++ b/doc/xml-xcb.txt
@@ -76,6 +76,12 @@ Top-Level Elements
the field and pad elements described in the section "Structure Contents
below".
+<eventstruct name="identifier">event-type-selector list</struct>
+
+ This element represents a data structure that is the wire-representation of
+ an event. The event can be any type that's selected by the
+ event-type-selector list.
+
<xidtype name="identifier" />
This element represents an identifier for a particular type of resource.
@@ -359,6 +365,29 @@ Expressions
This element represents the current list-element when used inside
a list-iteration expression such as <sumof>.
+
+Event-Type-Selector List
+------------------------
+
+ The event-type-selector list selects a set of eventtypes.
+ It consists of any number of the following elements:
+
+ <allowed extension="identifier" xge="boolean"
+ opcode-min="integer" opcode-max="integer" />
+
+ The extension attribute selects events from the given extension.
+
+ If the xge attribute is true, the event is an X Generic Event and
+ will be treated as such.
+
+ opcode-min and opcode-max describe the minimum and maximum opcode
+ respectively. The opcode is the same number as the number-attribute
+ of an event definition. I.e. this is the offset from the event-base
+ to the actual number used on the wire.
+
+ In the current implementation, only xge="false" is supported.
+
+
Documentation
-------------
diff --git a/src/xcb.xsd b/src/xcb.xsd
index f0c5f44..dc3d7cc 100644
--- a/src/xcb.xsd
+++ b/src/xcb.xsd
@@ -240,6 +240,22 @@ authorization from the authors.
<xsd:attribute name="ref" type="xsd:string" use="required" />
</xsd:complexType>
+ <!-- Type for a structure that is an event
+ which can be of an event type from a set of event types -->
+ <xsd:complexType name="eventstruct">
+ <xsd:sequence>
+ <xsd:element name="allowed">
+ <xsd:complexType>
+ <xsd:attribute name="extension" type="xsd:string" use="required" />
+ <xsd:attribute name="xge" type="xsd:boolean" use="required" />
+ <xsd:attribute name="opcode-min" type="xsd:integer" use="required" />
+ <xsd:attribute name="opcode-max" type="xsd:integer" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+
<!-- Type for bit values -->
<xsd:simpleType name="bitType">
<xsd:restriction base="xsd:integer">
@@ -354,6 +370,7 @@ authorization from the authors.
<xsd:element name="errorcopy" type="packet-struct-copy" />
<xsd:element name="struct" type="struct" />
<xsd:element name="union" type="struct" />
+ <xsd:element name="eventstruct" type="eventstruct" />
<xsd:element name="xidtype">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required" />
diff --git a/xcbgen/matcher.py b/xcbgen/matcher.py
index bfa315e..97a8b43 100644
--- a/xcbgen/matcher.py
+++ b/xcbgen/matcher.py
@@ -57,6 +57,12 @@ def struct(node, module, namespace):
type = Struct(name, node)
module.add_type(id, namespace.ns, name, type)
+def eventstruct(node, module, namespace):
+ id = node.get('name')
+ name = namespace.prefix + (id,)
+ type = EventStruct(name, node)
+ module.add_type(id, namespace.ns, name, type)
+
def union(node, module, namespace):
id = node.get('name')
name = namespace.prefix + (id,)
@@ -103,6 +109,7 @@ funcs = {'import' : import_,
'xidunion' : xidunion,
'enum' : enum,
'struct' : struct,
+ 'eventstruct' : eventstruct,
'union' : union,
'request' : request,
'event' : event,
diff --git a/xcbgen/state.py b/xcbgen/state.py
index a6ad3a1..a8346bb 100644
--- a/xcbgen/state.py
+++ b/xcbgen/state.py
@@ -32,6 +32,9 @@ class Namespace(object):
self.root = parse(filename).getroot()
self.header = self.root.get('header')
self.ns = self.header + ':'
+
+ # Events
+ self.events = {}
# Get root element attributes
if self.root.get('extension-xname', False):
@@ -46,6 +49,17 @@ class Namespace(object):
self.ext_name = ''
self.prefix = ('xcb',)
+ def add_event(self, id, name, item):
+ self.events[id] = (name, item)
+
+ def get_event_by_opcode(self, opcode, is_ge_event):
+ for id, (name, event) in self.events.items():
+ if event.is_ge_event == is_ge_event:
+ opcode_specific_name = event.get_name_for_opcode( opcode )
+ if opcode_specific_name is not None:
+ return (opcode_specific_name, event)
+ return None
+
class Module(object):
'''
@@ -72,6 +86,11 @@ class Module(object):
self.errors = {}
self.all = []
+ # dict of namespaces by ext_name
+ self.namespaces = {}
+ # enter the main namespace here
+ self.namespaces[self.namespace.ext_name] = self.namespace
+
# Register some common types
self.add_type('CARD8', '', ('uint8_t',), tcard8)
self.add_type('CARD16', '', ('uint16_t',), tcard16)
@@ -94,6 +113,7 @@ class Module(object):
# Recursively resolve all types
def resolve(self):
+ self.add_events_to_namespaces()
for (name, item) in self.all:
self.pads = 0
item.resolve(self)
@@ -112,6 +132,7 @@ class Module(object):
if self.import_level == 0:
self.direct_imports.append((name, namespace.header))
self.imports.append((name, namespace.header))
+ self.namespaces[namespace.ext_name] = namespace
def has_import(self, name):
for (name_, header) in self.imports:
@@ -149,6 +170,9 @@ class Module(object):
def get_type_name(self, id):
return self.get_type_impl(id, 0)
+ def get_namespace(self, ext_name):
+ return self.namespaces[ext_name]
+
# Keeps track of request datatypes
def add_request(self, id, name, item):
if name[:-1] == self.namespace.prefix:
@@ -160,6 +184,23 @@ class Module(object):
if name[:-1] == self.namespace.prefix:
self.all.append((name, item))
+
+ def add_events_to_namespaces(self):
+ # add to its namespace object
+ for id, (name,item) in self.events.items():
+ if name[:-1] == ('xcb',):
+ # core event
+ namespace_name = ''
+ else:
+ # extension event
+ namespace_name = name[-2]
+
+ namespace = self.namespaces[namespace_name]
+
+ if namespace is not None:
+ namespace.add_event(id, name, item)
+
+
def get_event(self, id):
return self.events[id][1]
diff --git a/xcbgen/xtypes.py b/xcbgen/xtypes.py
index b83b119..c1f5986 100644
--- a/xcbgen/xtypes.py
+++ b/xcbgen/xtypes.py
@@ -36,6 +36,8 @@ class Type(object):
self.is_reply = False
self.is_union = False
self.is_pad = False
+ self.is_eventstruct = False
+ self.is_event = False
self.is_switch = False
self.is_case_or_bitcase = False
self.is_bitcase = False
@@ -1164,6 +1166,82 @@ class Request(ComplexType):
out = __main__.output['request']
+class EventStructAllowedRule:
+
+ def __init__(self, parent, elt):
+ self.elt = elt
+ self.extension = elt.get('extension')
+ self.ge_events = elt.get('xge') == "true"
+ self.min_opcode = int( elt.get('opcode-min') )
+ self.max_opcode = int( elt.get('opcode-max') )
+
+ def resolve(self, parent, module):
+ # get the namespace of the specified extension
+ extension_namespace = module.get_namespace( self.extension )
+ if extension_namespace is None:
+ raise Exception( "EventStructAllowedRule.resolve: cannot find extension \"" + self.extension + "\"" )
+ return
+
+ # find and add the selected events
+ for opcode in range(self.min_opcode, self.max_opcode):
+ name_and_event = extension_namespace.get_event_by_opcode( opcode, self.ge_events )
+ if name_and_event is None:
+ # could not find event -> error handling
+ if self.ge_events:
+ raise Exception("EventStructAllowedRule.resolve: cannot find xge-event with opcode " + str(opcode) + " in extension " + self.extension )
+ else:
+ raise Exception("EventStructAllowedRule.resolve: cannot find oldstyle-event with opcode " + str(opcode) + " in extension " + self.extension )
+ return
+
+ ( name, event ) = name_and_event
+ # add event to EventStruct
+ parent.add_event( module, self.extension, opcode, name, event )
+
+
+class EventStruct(Union):
+ '''
+ Derived class representing an event-use-as-struct data type.
+ '''
+
+ def __init__(self, name, elt):
+ Union.__init__(self, name, elt)
+ self.is_eventstruct = True
+ self.events = []
+ self.allowedRules = []
+ self.contains_ge_events = False
+ for item in list(elt):
+ if item.tag == 'allowed':
+ allowedRule = EventStructAllowedRule(self, item)
+ self.allowedRules.append( allowedRule )
+ if allowedRule.ge_events:
+ self.contains_ge_events = True
+
+ out = __main__.output['eventstruct']
+
+ def resolve(self, module):
+ if self.resolved:
+ return
+ for allowedRule in self.allowedRules:
+ allowedRule.resolve(self, module)
+ Union.resolve(self,module)
+ self.resolved = True
+
+ # add event. called by resolve
+ def add_event(self, module, extension, opcode, name, event_type ):
+ self.events.append( (extension, opcode, name, event_type) )
+ # Add the field to ourself
+ event_type.make_member_of(module, self, name, name[-1], True, True, False)
+ # Recursively resolve the event (could be another structure, list)
+ event_type.resolve(module)
+
+ def fixed_size(self):
+ is_fixed_size = True
+ for extension, opcode, name, event in self.events:
+ if not event.fixed_size():
+ is_fixed_size = False
+ return is_fixed_size
+
+
class Event(ComplexType):
'''
Derived class representing an event data type.
@@ -1183,6 +1261,8 @@ class Event(ComplexType):
self.is_ge_event = bool(elt.get('xge'))
+ self.is_event = True
+
self.doc = None
for item in list(elt):
if item.tag == 'doc':
@@ -1193,6 +1273,13 @@ class Event(ComplexType):
if main:
self.name = name
+ def get_name_for_opcode(self, opcode):
+ for name, my_opcode in self.opcodes.items():
+ if int(my_opcode) == opcode:
+ return name
+ else:
+ return None
+
def resolve(self, module):
def add_event_header():
self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))