diff options
author | Christian Linhart <chris@demorecorder.com> | 2017-01-25 10:31:18 +0100 |
---|---|---|
committer | Christian Linhart <chris@demorecorder.com> | 2017-03-11 10:49:27 +0100 |
commit | 4aa40fbd5e05833b72327ea37421b09dff246732 (patch) | |
tree | d64322ef12b8c29517646e77bc613fb9f366c26e | |
parent | 89b022fdacfe7b39b2122c6ec1a4097767b1ee29 (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.txt | 29 | ||||
-rw-r--r-- | src/xcb.xsd | 17 | ||||
-rw-r--r-- | xcbgen/matcher.py | 7 | ||||
-rw-r--r-- | xcbgen/state.py | 41 | ||||
-rw-r--r-- | xcbgen/xtypes.py | 87 |
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)) |