github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xgbgen/go_event.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  )
     6  
     7  // Event types
     8  func (e *Event) Define(c *Context) {
     9  	c.Putln("// %s is the event number for a %s.", e.SrcName(), e.EvType())
    10  	c.Putln("const %s = %d", e.SrcName(), e.Number)
    11  	c.Putln("")
    12  	c.Putln("type %s struct {", e.EvType())
    13  	if !e.NoSequence {
    14  		c.Putln("Sequence uint16")
    15  	}
    16  	for _, field := range e.Fields {
    17  		field.Define(c)
    18  	}
    19  	c.Putln("}")
    20  	c.Putln("")
    21  
    22  	// Read defines a function that transforms a byte slice into this
    23  	// event struct.
    24  	e.Read(c)
    25  
    26  	// Write defines a function that transforms this event struct into
    27  	// a byte slice.
    28  	e.Write(c)
    29  
    30  	// Makes sure that this event type is an Event interface.
    31  	c.Putln("// SequenceId returns the sequence id attached to the %s event.",
    32  		e.SrcName())
    33  	c.Putln("// Events without a sequence number (KeymapNotify) return 0.")
    34  	c.Putln("// This is mostly used internally.")
    35  	c.Putln("func (v %s) SequenceId() uint16 {", e.EvType())
    36  	if e.NoSequence {
    37  		c.Putln("return uint16(0)")
    38  	} else {
    39  		c.Putln("return v.Sequence")
    40  	}
    41  	c.Putln("}")
    42  	c.Putln("")
    43  	c.Putln("// String is a rudimentary string representation of %s.",
    44  		e.EvType())
    45  	c.Putln("func (v %s) String() string {", e.EvType())
    46  	EventFieldString(c, e.Fields, e.SrcName())
    47  	c.Putln("}")
    48  	c.Putln("")
    49  
    50  	// Let's the XGB event loop read this event.
    51  	c.Putln("func init() {")
    52  	if c.protocol.isExt() {
    53  		c.Putln("xgb.NewExtEventFuncs[\"%s\"][%d] = %sNew",
    54  			c.protocol.ExtXName, e.Number, e.EvType())
    55  	} else {
    56  		c.Putln("xgb.NewEventFuncs[%d] = %sNew", e.Number, e.EvType())
    57  	}
    58  	c.Putln("}")
    59  	c.Putln("")
    60  }
    61  
    62  func (e *Event) Read(c *Context) {
    63  	c.Putln("// %sNew constructs a %s value that implements xgb.Event from "+
    64  		"a byte slice.", e.EvType(), e.EvType())
    65  	c.Putln("func %sNew(buf []byte) xgb.Event {", e.EvType())
    66  	c.Putln("v := %s{}", e.EvType())
    67  	c.Putln("b := 1 // don't read event number")
    68  	c.Putln("")
    69  	for i, field := range e.Fields {
    70  		if i == 1 && !e.NoSequence {
    71  			c.Putln("v.Sequence = xgb.Get16(buf[b:])")
    72  			c.Putln("b += 2")
    73  			c.Putln("")
    74  		}
    75  		field.Read(c, "v.")
    76  		c.Putln("")
    77  	}
    78  	c.Putln("return v")
    79  	c.Putln("}")
    80  	c.Putln("")
    81  }
    82  
    83  func (e *Event) Write(c *Context) {
    84  	c.Putln("// Bytes writes a %s value to a byte slice.", e.EvType())
    85  	c.Putln("func (v %s) Bytes() []byte {", e.EvType())
    86  	c.Putln("buf := make([]byte, %s)", e.Size())
    87  	c.Putln("b := 0")
    88  	c.Putln("")
    89  	c.Putln("// write event number")
    90  	c.Putln("buf[b] = %d", e.Number)
    91  	c.Putln("b += 1")
    92  	c.Putln("")
    93  	for i, field := range e.Fields {
    94  		if i == 1 && !e.NoSequence {
    95  			c.Putln("b += 2 // skip sequence number")
    96  			c.Putln("")
    97  		}
    98  		field.Write(c, "v.")
    99  		c.Putln("")
   100  	}
   101  	c.Putln("return buf")
   102  	c.Putln("}")
   103  	c.Putln("")
   104  }
   105  
   106  // EventCopy types
   107  func (e *EventCopy) Define(c *Context) {
   108  	c.Putln("// %s is the event number for a %s.", e.SrcName(), e.EvType())
   109  	c.Putln("const %s = %d", e.SrcName(), e.Number)
   110  	c.Putln("")
   111  	c.Putln("type %s %s", e.EvType(), e.Old.(*Event).EvType())
   112  	c.Putln("")
   113  
   114  	// Read defines a function that transforms a byte slice into this
   115  	// event struct.
   116  	e.Read(c)
   117  
   118  	// Write defines a function that transoforms this event struct into
   119  	// a byte slice.
   120  	e.Write(c)
   121  
   122  	// Makes sure that this event type is an Event interface.
   123  	c.Putln("// SequenceId returns the sequence id attached to the %s event.",
   124  		e.SrcName())
   125  	c.Putln("// Events without a sequence number (KeymapNotify) return 0.")
   126  	c.Putln("// This is mostly used internally.")
   127  	c.Putln("func (v %s) SequenceId() uint16 {", e.EvType())
   128  	if e.Old.(*Event).NoSequence {
   129  		c.Putln("return uint16(0)")
   130  	} else {
   131  		c.Putln("return v.Sequence")
   132  	}
   133  	c.Putln("}")
   134  	c.Putln("")
   135  	c.Putln("func (v %s) String() string {", e.EvType())
   136  	EventFieldString(c, e.Old.(*Event).Fields, e.SrcName())
   137  	c.Putln("}")
   138  	c.Putln("")
   139  
   140  	// Let's the XGB event loop read this event.
   141  	c.Putln("func init() {")
   142  	if c.protocol.isExt() {
   143  		c.Putln("xgb.NewExtEventFuncs[\"%s\"][%d] = %sNew",
   144  			c.protocol.ExtXName, e.Number, e.EvType())
   145  	} else {
   146  		c.Putln("xgb.NewEventFuncs[%d] = %sNew", e.Number, e.EvType())
   147  	}
   148  	c.Putln("}")
   149  	c.Putln("")
   150  }
   151  
   152  func (e *EventCopy) Read(c *Context) {
   153  	c.Putln("// %sNew constructs a %s value that implements xgb.Event from "+
   154  		"a byte slice.", e.EvType(), e.EvType())
   155  	c.Putln("func %sNew(buf []byte) xgb.Event {", e.EvType())
   156  	c.Putln("return %s(%sNew(buf).(%s))",
   157  		e.EvType(), e.Old.(*Event).EvType(), e.Old.(*Event).EvType())
   158  	c.Putln("}")
   159  	c.Putln("")
   160  }
   161  
   162  func (e *EventCopy) Write(c *Context) {
   163  	c.Putln("// Bytes writes a %s value to a byte slice.", e.EvType())
   164  	c.Putln("func (v %s) Bytes() []byte {", e.EvType())
   165  	c.Putln("return %s(v).Bytes()", e.Old.(*Event).EvType())
   166  	c.Putln("}")
   167  	c.Putln("")
   168  }
   169  
   170  // EventFieldString works for both Event and EventCopy. It assembles all of the
   171  // fields in an event and formats them into a single string.
   172  func EventFieldString(c *Context, fields []Field, evName string) {
   173  	c.Putln("fieldVals := make([]string, 0, %d)", len(fields))
   174  	if evName != "KeymapNotify" {
   175  		c.Putln("fieldVals = append(fieldVals, "+
   176  			"xgb.Sprintf(\"Sequence: %s\", v.Sequence))", "%d")
   177  	}
   178  	for _, field := range fields {
   179  		switch f := field.(type) {
   180  		case *PadField:
   181  			continue
   182  		case *SingleField:
   183  			switch f.Type.(type) {
   184  			case *Base:
   185  			case *Resource:
   186  			case *TypeDef:
   187  			default:
   188  				continue
   189  			}
   190  
   191  			switch field.SrcType() {
   192  			case "string":
   193  				format := fmt.Sprintf("xgb.Sprintf(\"%s: %s\", v.%s)",
   194  					field.SrcName(), "%s", field.SrcName())
   195  				c.Putln("fieldVals = append(fieldVals, %s)", format)
   196  			case "bool":
   197  				format := fmt.Sprintf("xgb.Sprintf(\"%s: %s\", v.%s)",
   198  					field.SrcName(), "%t", field.SrcName())
   199  				c.Putln("fieldVals = append(fieldVals, %s)", format)
   200  			default:
   201  				format := fmt.Sprintf("xgb.Sprintf(\"%s: %s\", v.%s)",
   202  					field.SrcName(), "%d", field.SrcName())
   203  				c.Putln("fieldVals = append(fieldVals, %s)", format)
   204  			}
   205  		}
   206  	}
   207  	c.Putln("return \"%s {\" + xgb.StringsJoin(fieldVals, \", \") + \"}\"",
   208  		evName)
   209  }