github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/record/record.go (about) 1 // Package record is the X client API for the RECORD extension. 2 package record 3 4 // This file is automatically generated from record.xml. Edit at your peril! 5 6 import ( 7 "github.com/BurntSushi/xgb" 8 9 "github.com/BurntSushi/xgb/xproto" 10 ) 11 12 // Init must be called before using the RECORD extension. 13 func Init(c *xgb.Conn) error { 14 reply, err := xproto.QueryExtension(c, 6, "RECORD").Reply() 15 switch { 16 case err != nil: 17 return err 18 case !reply.Present: 19 return xgb.Errorf("No extension named RECORD could be found on on the server.") 20 } 21 22 c.ExtLock.Lock() 23 c.Extensions["RECORD"] = reply.MajorOpcode 24 c.ExtLock.Unlock() 25 for evNum, fun := range xgb.NewExtEventFuncs["RECORD"] { 26 xgb.NewEventFuncs[int(reply.FirstEvent)+evNum] = fun 27 } 28 for errNum, fun := range xgb.NewExtErrorFuncs["RECORD"] { 29 xgb.NewErrorFuncs[int(reply.FirstError)+errNum] = fun 30 } 31 return nil 32 } 33 34 func init() { 35 xgb.NewExtEventFuncs["RECORD"] = make(map[int]xgb.NewEventFun) 36 xgb.NewExtErrorFuncs["RECORD"] = make(map[int]xgb.NewErrorFun) 37 } 38 39 // BadBadContext is the error number for a BadBadContext. 40 const BadBadContext = 0 41 42 type BadContextError struct { 43 Sequence uint16 44 NiceName string 45 InvalidRecord uint32 46 } 47 48 // BadContextErrorNew constructs a BadContextError value that implements xgb.Error from a byte slice. 49 func BadContextErrorNew(buf []byte) xgb.Error { 50 v := BadContextError{} 51 v.NiceName = "BadContext" 52 53 b := 1 // skip error determinant 54 b += 1 // don't read error number 55 56 v.Sequence = xgb.Get16(buf[b:]) 57 b += 2 58 59 v.InvalidRecord = xgb.Get32(buf[b:]) 60 b += 4 61 62 return v 63 } 64 65 // SequenceId returns the sequence id attached to the BadBadContext error. 66 // This is mostly used internally. 67 func (err BadContextError) SequenceId() uint16 { 68 return err.Sequence 69 } 70 71 // BadId returns the 'BadValue' number if one exists for the BadBadContext error. If no bad value exists, 0 is returned. 72 func (err BadContextError) BadId() uint32 { 73 return 0 74 } 75 76 // Error returns a rudimentary string representation of the BadBadContext error. 77 78 func (err BadContextError) Error() string { 79 fieldVals := make([]string, 0, 1) 80 fieldVals = append(fieldVals, "NiceName: "+err.NiceName) 81 fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) 82 fieldVals = append(fieldVals, xgb.Sprintf("InvalidRecord: %d", err.InvalidRecord)) 83 return "BadBadContext {" + xgb.StringsJoin(fieldVals, ", ") + "}" 84 } 85 86 func init() { 87 xgb.NewExtErrorFuncs["RECORD"][0] = BadContextErrorNew 88 } 89 90 type ClientInfo struct { 91 ClientResource ClientSpec 92 NumRanges uint32 93 Ranges []Range // size: xgb.Pad((int(NumRanges) * 24)) 94 } 95 96 // ClientInfoRead reads a byte slice into a ClientInfo value. 97 func ClientInfoRead(buf []byte, v *ClientInfo) int { 98 b := 0 99 100 v.ClientResource = ClientSpec(xgb.Get32(buf[b:])) 101 b += 4 102 103 v.NumRanges = xgb.Get32(buf[b:]) 104 b += 4 105 106 v.Ranges = make([]Range, v.NumRanges) 107 b += RangeReadList(buf[b:], v.Ranges) 108 109 return b 110 } 111 112 // ClientInfoReadList reads a byte slice into a list of ClientInfo values. 113 func ClientInfoReadList(buf []byte, dest []ClientInfo) int { 114 b := 0 115 for i := 0; i < len(dest); i++ { 116 dest[i] = ClientInfo{} 117 b += ClientInfoRead(buf[b:], &dest[i]) 118 } 119 return xgb.Pad(b) 120 } 121 122 // Bytes writes a ClientInfo value to a byte slice. 123 func (v ClientInfo) Bytes() []byte { 124 buf := make([]byte, (8 + xgb.Pad((int(v.NumRanges) * 24)))) 125 b := 0 126 127 xgb.Put32(buf[b:], uint32(v.ClientResource)) 128 b += 4 129 130 xgb.Put32(buf[b:], v.NumRanges) 131 b += 4 132 133 b += RangeListBytes(buf[b:], v.Ranges) 134 135 return buf[:b] 136 } 137 138 // ClientInfoListBytes writes a list of ClientInfo values to a byte slice. 139 func ClientInfoListBytes(buf []byte, list []ClientInfo) int { 140 b := 0 141 var structBytes []byte 142 for _, item := range list { 143 structBytes = item.Bytes() 144 copy(buf[b:], structBytes) 145 b += len(structBytes) 146 } 147 return xgb.Pad(b) 148 } 149 150 // ClientInfoListSize computes the size (bytes) of a list of ClientInfo values. 151 func ClientInfoListSize(list []ClientInfo) int { 152 size := 0 153 for _, item := range list { 154 size += (8 + xgb.Pad((int(item.NumRanges) * 24))) 155 } 156 return size 157 } 158 159 type ClientSpec uint32 160 161 type Context uint32 162 163 func NewContextId(c *xgb.Conn) (Context, error) { 164 id, err := c.NewId() 165 if err != nil { 166 return 0, err 167 } 168 return Context(id), nil 169 } 170 171 const ( 172 CsCurrentClients = 1 173 CsFutureClients = 2 174 CsAllClients = 3 175 ) 176 177 type ElementHeader byte 178 179 type ExtRange struct { 180 Major Range8 181 Minor Range16 182 } 183 184 // ExtRangeRead reads a byte slice into a ExtRange value. 185 func ExtRangeRead(buf []byte, v *ExtRange) int { 186 b := 0 187 188 v.Major = Range8{} 189 b += Range8Read(buf[b:], &v.Major) 190 191 v.Minor = Range16{} 192 b += Range16Read(buf[b:], &v.Minor) 193 194 return b 195 } 196 197 // ExtRangeReadList reads a byte slice into a list of ExtRange values. 198 func ExtRangeReadList(buf []byte, dest []ExtRange) int { 199 b := 0 200 for i := 0; i < len(dest); i++ { 201 dest[i] = ExtRange{} 202 b += ExtRangeRead(buf[b:], &dest[i]) 203 } 204 return xgb.Pad(b) 205 } 206 207 // Bytes writes a ExtRange value to a byte slice. 208 func (v ExtRange) Bytes() []byte { 209 buf := make([]byte, 6) 210 b := 0 211 212 { 213 structBytes := v.Major.Bytes() 214 copy(buf[b:], structBytes) 215 b += len(structBytes) 216 } 217 218 { 219 structBytes := v.Minor.Bytes() 220 copy(buf[b:], structBytes) 221 b += len(structBytes) 222 } 223 224 return buf[:b] 225 } 226 227 // ExtRangeListBytes writes a list of ExtRange values to a byte slice. 228 func ExtRangeListBytes(buf []byte, list []ExtRange) int { 229 b := 0 230 var structBytes []byte 231 for _, item := range list { 232 structBytes = item.Bytes() 233 copy(buf[b:], structBytes) 234 b += len(structBytes) 235 } 236 return xgb.Pad(b) 237 } 238 239 const ( 240 HTypeFromServerTime = 1 241 HTypeFromClientTime = 2 242 HTypeFromClientSequence = 4 243 ) 244 245 type Range struct { 246 CoreRequests Range8 247 CoreReplies Range8 248 ExtRequests ExtRange 249 ExtReplies ExtRange 250 DeliveredEvents Range8 251 DeviceEvents Range8 252 Errors Range8 253 ClientStarted bool 254 ClientDied bool 255 } 256 257 // RangeRead reads a byte slice into a Range value. 258 func RangeRead(buf []byte, v *Range) int { 259 b := 0 260 261 v.CoreRequests = Range8{} 262 b += Range8Read(buf[b:], &v.CoreRequests) 263 264 v.CoreReplies = Range8{} 265 b += Range8Read(buf[b:], &v.CoreReplies) 266 267 v.ExtRequests = ExtRange{} 268 b += ExtRangeRead(buf[b:], &v.ExtRequests) 269 270 v.ExtReplies = ExtRange{} 271 b += ExtRangeRead(buf[b:], &v.ExtReplies) 272 273 v.DeliveredEvents = Range8{} 274 b += Range8Read(buf[b:], &v.DeliveredEvents) 275 276 v.DeviceEvents = Range8{} 277 b += Range8Read(buf[b:], &v.DeviceEvents) 278 279 v.Errors = Range8{} 280 b += Range8Read(buf[b:], &v.Errors) 281 282 if buf[b] == 1 { 283 v.ClientStarted = true 284 } else { 285 v.ClientStarted = false 286 } 287 b += 1 288 289 if buf[b] == 1 { 290 v.ClientDied = true 291 } else { 292 v.ClientDied = false 293 } 294 b += 1 295 296 return b 297 } 298 299 // RangeReadList reads a byte slice into a list of Range values. 300 func RangeReadList(buf []byte, dest []Range) int { 301 b := 0 302 for i := 0; i < len(dest); i++ { 303 dest[i] = Range{} 304 b += RangeRead(buf[b:], &dest[i]) 305 } 306 return xgb.Pad(b) 307 } 308 309 // Bytes writes a Range value to a byte slice. 310 func (v Range) Bytes() []byte { 311 buf := make([]byte, 24) 312 b := 0 313 314 { 315 structBytes := v.CoreRequests.Bytes() 316 copy(buf[b:], structBytes) 317 b += len(structBytes) 318 } 319 320 { 321 structBytes := v.CoreReplies.Bytes() 322 copy(buf[b:], structBytes) 323 b += len(structBytes) 324 } 325 326 { 327 structBytes := v.ExtRequests.Bytes() 328 copy(buf[b:], structBytes) 329 b += len(structBytes) 330 } 331 332 { 333 structBytes := v.ExtReplies.Bytes() 334 copy(buf[b:], structBytes) 335 b += len(structBytes) 336 } 337 338 { 339 structBytes := v.DeliveredEvents.Bytes() 340 copy(buf[b:], structBytes) 341 b += len(structBytes) 342 } 343 344 { 345 structBytes := v.DeviceEvents.Bytes() 346 copy(buf[b:], structBytes) 347 b += len(structBytes) 348 } 349 350 { 351 structBytes := v.Errors.Bytes() 352 copy(buf[b:], structBytes) 353 b += len(structBytes) 354 } 355 356 if v.ClientStarted { 357 buf[b] = 1 358 } else { 359 buf[b] = 0 360 } 361 b += 1 362 363 if v.ClientDied { 364 buf[b] = 1 365 } else { 366 buf[b] = 0 367 } 368 b += 1 369 370 return buf[:b] 371 } 372 373 // RangeListBytes writes a list of Range values to a byte slice. 374 func RangeListBytes(buf []byte, list []Range) int { 375 b := 0 376 var structBytes []byte 377 for _, item := range list { 378 structBytes = item.Bytes() 379 copy(buf[b:], structBytes) 380 b += len(structBytes) 381 } 382 return xgb.Pad(b) 383 } 384 385 type Range16 struct { 386 First uint16 387 Last uint16 388 } 389 390 // Range16Read reads a byte slice into a Range16 value. 391 func Range16Read(buf []byte, v *Range16) int { 392 b := 0 393 394 v.First = xgb.Get16(buf[b:]) 395 b += 2 396 397 v.Last = xgb.Get16(buf[b:]) 398 b += 2 399 400 return b 401 } 402 403 // Range16ReadList reads a byte slice into a list of Range16 values. 404 func Range16ReadList(buf []byte, dest []Range16) int { 405 b := 0 406 for i := 0; i < len(dest); i++ { 407 dest[i] = Range16{} 408 b += Range16Read(buf[b:], &dest[i]) 409 } 410 return xgb.Pad(b) 411 } 412 413 // Bytes writes a Range16 value to a byte slice. 414 func (v Range16) Bytes() []byte { 415 buf := make([]byte, 4) 416 b := 0 417 418 xgb.Put16(buf[b:], v.First) 419 b += 2 420 421 xgb.Put16(buf[b:], v.Last) 422 b += 2 423 424 return buf[:b] 425 } 426 427 // Range16ListBytes writes a list of Range16 values to a byte slice. 428 func Range16ListBytes(buf []byte, list []Range16) int { 429 b := 0 430 var structBytes []byte 431 for _, item := range list { 432 structBytes = item.Bytes() 433 copy(buf[b:], structBytes) 434 b += len(structBytes) 435 } 436 return xgb.Pad(b) 437 } 438 439 type Range8 struct { 440 First byte 441 Last byte 442 } 443 444 // Range8Read reads a byte slice into a Range8 value. 445 func Range8Read(buf []byte, v *Range8) int { 446 b := 0 447 448 v.First = buf[b] 449 b += 1 450 451 v.Last = buf[b] 452 b += 1 453 454 return b 455 } 456 457 // Range8ReadList reads a byte slice into a list of Range8 values. 458 func Range8ReadList(buf []byte, dest []Range8) int { 459 b := 0 460 for i := 0; i < len(dest); i++ { 461 dest[i] = Range8{} 462 b += Range8Read(buf[b:], &dest[i]) 463 } 464 return xgb.Pad(b) 465 } 466 467 // Bytes writes a Range8 value to a byte slice. 468 func (v Range8) Bytes() []byte { 469 buf := make([]byte, 2) 470 b := 0 471 472 buf[b] = v.First 473 b += 1 474 475 buf[b] = v.Last 476 b += 1 477 478 return buf[:b] 479 } 480 481 // Range8ListBytes writes a list of Range8 values to a byte slice. 482 func Range8ListBytes(buf []byte, list []Range8) int { 483 b := 0 484 var structBytes []byte 485 for _, item := range list { 486 structBytes = item.Bytes() 487 copy(buf[b:], structBytes) 488 b += len(structBytes) 489 } 490 return xgb.Pad(b) 491 } 492 493 // Skipping definition for base type 'Bool' 494 495 // Skipping definition for base type 'Byte' 496 497 // Skipping definition for base type 'Card8' 498 499 // Skipping definition for base type 'Char' 500 501 // Skipping definition for base type 'Void' 502 503 // Skipping definition for base type 'Double' 504 505 // Skipping definition for base type 'Float' 506 507 // Skipping definition for base type 'Int16' 508 509 // Skipping definition for base type 'Int32' 510 511 // Skipping definition for base type 'Int8' 512 513 // Skipping definition for base type 'Card16' 514 515 // Skipping definition for base type 'Card32' 516 517 // CreateContextCookie is a cookie used only for CreateContext requests. 518 type CreateContextCookie struct { 519 *xgb.Cookie 520 } 521 522 // CreateContext sends an unchecked request. 523 // If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. 524 func CreateContext(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) CreateContextCookie { 525 c.ExtLock.RLock() 526 defer c.ExtLock.RUnlock() 527 if _, ok := c.Extensions["RECORD"]; !ok { 528 panic("Cannot issue request 'CreateContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 529 } 530 cookie := c.NewCookie(false, false) 531 c.NewRequest(createContextRequest(c, Context, ElementHeader, NumClientSpecs, NumRanges, ClientSpecs, Ranges), cookie) 532 return CreateContextCookie{cookie} 533 } 534 535 // CreateContextChecked sends a checked request. 536 // If an error occurs, it can be retrieved using CreateContextCookie.Check() 537 func CreateContextChecked(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) CreateContextCookie { 538 c.ExtLock.RLock() 539 defer c.ExtLock.RUnlock() 540 if _, ok := c.Extensions["RECORD"]; !ok { 541 panic("Cannot issue request 'CreateContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 542 } 543 cookie := c.NewCookie(true, false) 544 c.NewRequest(createContextRequest(c, Context, ElementHeader, NumClientSpecs, NumRanges, ClientSpecs, Ranges), cookie) 545 return CreateContextCookie{cookie} 546 } 547 548 // Check returns an error if one occurred for checked requests that are not expecting a reply. 549 // This cannot be called for requests expecting a reply, nor for unchecked requests. 550 func (cook CreateContextCookie) Check() error { 551 return cook.Cookie.Check() 552 } 553 554 // Write request to wire for CreateContext 555 // createContextRequest writes a CreateContext request to a byte slice. 556 func createContextRequest(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) []byte { 557 size := xgb.Pad((((20 + xgb.Pad((int(NumClientSpecs) * 4))) + 4) + xgb.Pad((int(NumRanges) * 24)))) 558 b := 0 559 buf := make([]byte, size) 560 561 c.ExtLock.RLock() 562 buf[b] = c.Extensions["RECORD"] 563 c.ExtLock.RUnlock() 564 b += 1 565 566 buf[b] = 1 // request opcode 567 b += 1 568 569 blen := b 570 b += 2 571 572 xgb.Put32(buf[b:], uint32(Context)) 573 b += 4 574 575 buf[b] = byte(ElementHeader) 576 b += 1 577 578 b += 3 // padding 579 580 xgb.Put32(buf[b:], NumClientSpecs) 581 b += 4 582 583 xgb.Put32(buf[b:], NumRanges) 584 b += 4 585 586 for i := 0; i < int(NumClientSpecs); i++ { 587 xgb.Put32(buf[b:], uint32(ClientSpecs[i])) 588 b += 4 589 } 590 591 b = (b + 3) & ^3 // alignment gap 592 593 b += RangeListBytes(buf[b:], Ranges) 594 595 b = xgb.Pad(b) 596 xgb.Put16(buf[blen:], uint16(b/4)) // write request size in 4-byte units 597 return buf[:b] 598 } 599 600 // DisableContextCookie is a cookie used only for DisableContext requests. 601 type DisableContextCookie struct { 602 *xgb.Cookie 603 } 604 605 // DisableContext sends an unchecked request. 606 // If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. 607 func DisableContext(c *xgb.Conn, Context Context) DisableContextCookie { 608 c.ExtLock.RLock() 609 defer c.ExtLock.RUnlock() 610 if _, ok := c.Extensions["RECORD"]; !ok { 611 panic("Cannot issue request 'DisableContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 612 } 613 cookie := c.NewCookie(false, false) 614 c.NewRequest(disableContextRequest(c, Context), cookie) 615 return DisableContextCookie{cookie} 616 } 617 618 // DisableContextChecked sends a checked request. 619 // If an error occurs, it can be retrieved using DisableContextCookie.Check() 620 func DisableContextChecked(c *xgb.Conn, Context Context) DisableContextCookie { 621 c.ExtLock.RLock() 622 defer c.ExtLock.RUnlock() 623 if _, ok := c.Extensions["RECORD"]; !ok { 624 panic("Cannot issue request 'DisableContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 625 } 626 cookie := c.NewCookie(true, false) 627 c.NewRequest(disableContextRequest(c, Context), cookie) 628 return DisableContextCookie{cookie} 629 } 630 631 // Check returns an error if one occurred for checked requests that are not expecting a reply. 632 // This cannot be called for requests expecting a reply, nor for unchecked requests. 633 func (cook DisableContextCookie) Check() error { 634 return cook.Cookie.Check() 635 } 636 637 // Write request to wire for DisableContext 638 // disableContextRequest writes a DisableContext request to a byte slice. 639 func disableContextRequest(c *xgb.Conn, Context Context) []byte { 640 size := 8 641 b := 0 642 buf := make([]byte, size) 643 644 c.ExtLock.RLock() 645 buf[b] = c.Extensions["RECORD"] 646 c.ExtLock.RUnlock() 647 b += 1 648 649 buf[b] = 6 // request opcode 650 b += 1 651 652 xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units 653 b += 2 654 655 xgb.Put32(buf[b:], uint32(Context)) 656 b += 4 657 658 return buf 659 } 660 661 // EnableContextCookie is a cookie used only for EnableContext requests. 662 type EnableContextCookie struct { 663 *xgb.Cookie 664 } 665 666 // EnableContext sends a checked request. 667 // If an error occurs, it will be returned with the reply by calling EnableContextCookie.Reply() 668 func EnableContext(c *xgb.Conn, Context Context) EnableContextCookie { 669 c.ExtLock.RLock() 670 defer c.ExtLock.RUnlock() 671 if _, ok := c.Extensions["RECORD"]; !ok { 672 panic("Cannot issue request 'EnableContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 673 } 674 cookie := c.NewCookie(true, true) 675 c.NewRequest(enableContextRequest(c, Context), cookie) 676 return EnableContextCookie{cookie} 677 } 678 679 // EnableContextUnchecked sends an unchecked request. 680 // If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. 681 func EnableContextUnchecked(c *xgb.Conn, Context Context) EnableContextCookie { 682 c.ExtLock.RLock() 683 defer c.ExtLock.RUnlock() 684 if _, ok := c.Extensions["RECORD"]; !ok { 685 panic("Cannot issue request 'EnableContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 686 } 687 cookie := c.NewCookie(false, true) 688 c.NewRequest(enableContextRequest(c, Context), cookie) 689 return EnableContextCookie{cookie} 690 } 691 692 // EnableContextReply represents the data returned from a EnableContext request. 693 type EnableContextReply struct { 694 Sequence uint16 // sequence number of the request for this reply 695 Length uint32 // number of bytes in this reply 696 Category byte 697 ElementHeader ElementHeader 698 ClientSwapped bool 699 // padding: 2 bytes 700 XidBase uint32 701 ServerTime uint32 702 RecSequenceNum uint32 703 // padding: 8 bytes 704 Data []byte // size: xgb.Pad(((int(Length) * 4) * 1)) 705 } 706 707 // Reply blocks and returns the reply data for a EnableContext request. 708 func (cook EnableContextCookie) Reply() (*EnableContextReply, error) { 709 buf, err := cook.Cookie.Reply() 710 if err != nil { 711 return nil, err 712 } 713 if buf == nil { 714 return nil, nil 715 } 716 return enableContextReply(buf), nil 717 } 718 719 // enableContextReply reads a byte slice into a EnableContextReply value. 720 func enableContextReply(buf []byte) *EnableContextReply { 721 v := new(EnableContextReply) 722 b := 1 // skip reply determinant 723 724 v.Category = buf[b] 725 b += 1 726 727 v.Sequence = xgb.Get16(buf[b:]) 728 b += 2 729 730 v.Length = xgb.Get32(buf[b:]) // 4-byte units 731 b += 4 732 733 v.ElementHeader = ElementHeader(buf[b]) 734 b += 1 735 736 if buf[b] == 1 { 737 v.ClientSwapped = true 738 } else { 739 v.ClientSwapped = false 740 } 741 b += 1 742 743 b += 2 // padding 744 745 v.XidBase = xgb.Get32(buf[b:]) 746 b += 4 747 748 v.ServerTime = xgb.Get32(buf[b:]) 749 b += 4 750 751 v.RecSequenceNum = xgb.Get32(buf[b:]) 752 b += 4 753 754 b += 8 // padding 755 756 v.Data = make([]byte, (int(v.Length) * 4)) 757 copy(v.Data[:(int(v.Length)*4)], buf[b:]) 758 b += int((int(v.Length) * 4)) 759 760 return v 761 } 762 763 // Write request to wire for EnableContext 764 // enableContextRequest writes a EnableContext request to a byte slice. 765 func enableContextRequest(c *xgb.Conn, Context Context) []byte { 766 size := 8 767 b := 0 768 buf := make([]byte, size) 769 770 c.ExtLock.RLock() 771 buf[b] = c.Extensions["RECORD"] 772 c.ExtLock.RUnlock() 773 b += 1 774 775 buf[b] = 5 // request opcode 776 b += 1 777 778 xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units 779 b += 2 780 781 xgb.Put32(buf[b:], uint32(Context)) 782 b += 4 783 784 return buf 785 } 786 787 // FreeContextCookie is a cookie used only for FreeContext requests. 788 type FreeContextCookie struct { 789 *xgb.Cookie 790 } 791 792 // FreeContext sends an unchecked request. 793 // If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. 794 func FreeContext(c *xgb.Conn, Context Context) FreeContextCookie { 795 c.ExtLock.RLock() 796 defer c.ExtLock.RUnlock() 797 if _, ok := c.Extensions["RECORD"]; !ok { 798 panic("Cannot issue request 'FreeContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 799 } 800 cookie := c.NewCookie(false, false) 801 c.NewRequest(freeContextRequest(c, Context), cookie) 802 return FreeContextCookie{cookie} 803 } 804 805 // FreeContextChecked sends a checked request. 806 // If an error occurs, it can be retrieved using FreeContextCookie.Check() 807 func FreeContextChecked(c *xgb.Conn, Context Context) FreeContextCookie { 808 c.ExtLock.RLock() 809 defer c.ExtLock.RUnlock() 810 if _, ok := c.Extensions["RECORD"]; !ok { 811 panic("Cannot issue request 'FreeContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 812 } 813 cookie := c.NewCookie(true, false) 814 c.NewRequest(freeContextRequest(c, Context), cookie) 815 return FreeContextCookie{cookie} 816 } 817 818 // Check returns an error if one occurred for checked requests that are not expecting a reply. 819 // This cannot be called for requests expecting a reply, nor for unchecked requests. 820 func (cook FreeContextCookie) Check() error { 821 return cook.Cookie.Check() 822 } 823 824 // Write request to wire for FreeContext 825 // freeContextRequest writes a FreeContext request to a byte slice. 826 func freeContextRequest(c *xgb.Conn, Context Context) []byte { 827 size := 8 828 b := 0 829 buf := make([]byte, size) 830 831 c.ExtLock.RLock() 832 buf[b] = c.Extensions["RECORD"] 833 c.ExtLock.RUnlock() 834 b += 1 835 836 buf[b] = 7 // request opcode 837 b += 1 838 839 xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units 840 b += 2 841 842 xgb.Put32(buf[b:], uint32(Context)) 843 b += 4 844 845 return buf 846 } 847 848 // GetContextCookie is a cookie used only for GetContext requests. 849 type GetContextCookie struct { 850 *xgb.Cookie 851 } 852 853 // GetContext sends a checked request. 854 // If an error occurs, it will be returned with the reply by calling GetContextCookie.Reply() 855 func GetContext(c *xgb.Conn, Context Context) GetContextCookie { 856 c.ExtLock.RLock() 857 defer c.ExtLock.RUnlock() 858 if _, ok := c.Extensions["RECORD"]; !ok { 859 panic("Cannot issue request 'GetContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 860 } 861 cookie := c.NewCookie(true, true) 862 c.NewRequest(getContextRequest(c, Context), cookie) 863 return GetContextCookie{cookie} 864 } 865 866 // GetContextUnchecked sends an unchecked request. 867 // If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. 868 func GetContextUnchecked(c *xgb.Conn, Context Context) GetContextCookie { 869 c.ExtLock.RLock() 870 defer c.ExtLock.RUnlock() 871 if _, ok := c.Extensions["RECORD"]; !ok { 872 panic("Cannot issue request 'GetContext' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 873 } 874 cookie := c.NewCookie(false, true) 875 c.NewRequest(getContextRequest(c, Context), cookie) 876 return GetContextCookie{cookie} 877 } 878 879 // GetContextReply represents the data returned from a GetContext request. 880 type GetContextReply struct { 881 Sequence uint16 // sequence number of the request for this reply 882 Length uint32 // number of bytes in this reply 883 Enabled bool 884 ElementHeader ElementHeader 885 // padding: 3 bytes 886 NumInterceptedClients uint32 887 // padding: 16 bytes 888 InterceptedClients []ClientInfo // size: ClientInfoListSize(InterceptedClients) 889 } 890 891 // Reply blocks and returns the reply data for a GetContext request. 892 func (cook GetContextCookie) Reply() (*GetContextReply, error) { 893 buf, err := cook.Cookie.Reply() 894 if err != nil { 895 return nil, err 896 } 897 if buf == nil { 898 return nil, nil 899 } 900 return getContextReply(buf), nil 901 } 902 903 // getContextReply reads a byte slice into a GetContextReply value. 904 func getContextReply(buf []byte) *GetContextReply { 905 v := new(GetContextReply) 906 b := 1 // skip reply determinant 907 908 if buf[b] == 1 { 909 v.Enabled = true 910 } else { 911 v.Enabled = false 912 } 913 b += 1 914 915 v.Sequence = xgb.Get16(buf[b:]) 916 b += 2 917 918 v.Length = xgb.Get32(buf[b:]) // 4-byte units 919 b += 4 920 921 v.ElementHeader = ElementHeader(buf[b]) 922 b += 1 923 924 b += 3 // padding 925 926 v.NumInterceptedClients = xgb.Get32(buf[b:]) 927 b += 4 928 929 b += 16 // padding 930 931 v.InterceptedClients = make([]ClientInfo, v.NumInterceptedClients) 932 b += ClientInfoReadList(buf[b:], v.InterceptedClients) 933 934 return v 935 } 936 937 // Write request to wire for GetContext 938 // getContextRequest writes a GetContext request to a byte slice. 939 func getContextRequest(c *xgb.Conn, Context Context) []byte { 940 size := 8 941 b := 0 942 buf := make([]byte, size) 943 944 c.ExtLock.RLock() 945 buf[b] = c.Extensions["RECORD"] 946 c.ExtLock.RUnlock() 947 b += 1 948 949 buf[b] = 4 // request opcode 950 b += 1 951 952 xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units 953 b += 2 954 955 xgb.Put32(buf[b:], uint32(Context)) 956 b += 4 957 958 return buf 959 } 960 961 // QueryVersionCookie is a cookie used only for QueryVersion requests. 962 type QueryVersionCookie struct { 963 *xgb.Cookie 964 } 965 966 // QueryVersion sends a checked request. 967 // If an error occurs, it will be returned with the reply by calling QueryVersionCookie.Reply() 968 func QueryVersion(c *xgb.Conn, MajorVersion uint16, MinorVersion uint16) QueryVersionCookie { 969 c.ExtLock.RLock() 970 defer c.ExtLock.RUnlock() 971 if _, ok := c.Extensions["RECORD"]; !ok { 972 panic("Cannot issue request 'QueryVersion' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 973 } 974 cookie := c.NewCookie(true, true) 975 c.NewRequest(queryVersionRequest(c, MajorVersion, MinorVersion), cookie) 976 return QueryVersionCookie{cookie} 977 } 978 979 // QueryVersionUnchecked sends an unchecked request. 980 // If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. 981 func QueryVersionUnchecked(c *xgb.Conn, MajorVersion uint16, MinorVersion uint16) QueryVersionCookie { 982 c.ExtLock.RLock() 983 defer c.ExtLock.RUnlock() 984 if _, ok := c.Extensions["RECORD"]; !ok { 985 panic("Cannot issue request 'QueryVersion' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 986 } 987 cookie := c.NewCookie(false, true) 988 c.NewRequest(queryVersionRequest(c, MajorVersion, MinorVersion), cookie) 989 return QueryVersionCookie{cookie} 990 } 991 992 // QueryVersionReply represents the data returned from a QueryVersion request. 993 type QueryVersionReply struct { 994 Sequence uint16 // sequence number of the request for this reply 995 Length uint32 // number of bytes in this reply 996 // padding: 1 bytes 997 MajorVersion uint16 998 MinorVersion uint16 999 } 1000 1001 // Reply blocks and returns the reply data for a QueryVersion request. 1002 func (cook QueryVersionCookie) Reply() (*QueryVersionReply, error) { 1003 buf, err := cook.Cookie.Reply() 1004 if err != nil { 1005 return nil, err 1006 } 1007 if buf == nil { 1008 return nil, nil 1009 } 1010 return queryVersionReply(buf), nil 1011 } 1012 1013 // queryVersionReply reads a byte slice into a QueryVersionReply value. 1014 func queryVersionReply(buf []byte) *QueryVersionReply { 1015 v := new(QueryVersionReply) 1016 b := 1 // skip reply determinant 1017 1018 b += 1 // padding 1019 1020 v.Sequence = xgb.Get16(buf[b:]) 1021 b += 2 1022 1023 v.Length = xgb.Get32(buf[b:]) // 4-byte units 1024 b += 4 1025 1026 v.MajorVersion = xgb.Get16(buf[b:]) 1027 b += 2 1028 1029 v.MinorVersion = xgb.Get16(buf[b:]) 1030 b += 2 1031 1032 return v 1033 } 1034 1035 // Write request to wire for QueryVersion 1036 // queryVersionRequest writes a QueryVersion request to a byte slice. 1037 func queryVersionRequest(c *xgb.Conn, MajorVersion uint16, MinorVersion uint16) []byte { 1038 size := 8 1039 b := 0 1040 buf := make([]byte, size) 1041 1042 c.ExtLock.RLock() 1043 buf[b] = c.Extensions["RECORD"] 1044 c.ExtLock.RUnlock() 1045 b += 1 1046 1047 buf[b] = 0 // request opcode 1048 b += 1 1049 1050 xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units 1051 b += 2 1052 1053 xgb.Put16(buf[b:], MajorVersion) 1054 b += 2 1055 1056 xgb.Put16(buf[b:], MinorVersion) 1057 b += 2 1058 1059 return buf 1060 } 1061 1062 // RegisterClientsCookie is a cookie used only for RegisterClients requests. 1063 type RegisterClientsCookie struct { 1064 *xgb.Cookie 1065 } 1066 1067 // RegisterClients sends an unchecked request. 1068 // If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. 1069 func RegisterClients(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) RegisterClientsCookie { 1070 c.ExtLock.RLock() 1071 defer c.ExtLock.RUnlock() 1072 if _, ok := c.Extensions["RECORD"]; !ok { 1073 panic("Cannot issue request 'RegisterClients' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 1074 } 1075 cookie := c.NewCookie(false, false) 1076 c.NewRequest(registerClientsRequest(c, Context, ElementHeader, NumClientSpecs, NumRanges, ClientSpecs, Ranges), cookie) 1077 return RegisterClientsCookie{cookie} 1078 } 1079 1080 // RegisterClientsChecked sends a checked request. 1081 // If an error occurs, it can be retrieved using RegisterClientsCookie.Check() 1082 func RegisterClientsChecked(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) RegisterClientsCookie { 1083 c.ExtLock.RLock() 1084 defer c.ExtLock.RUnlock() 1085 if _, ok := c.Extensions["RECORD"]; !ok { 1086 panic("Cannot issue request 'RegisterClients' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 1087 } 1088 cookie := c.NewCookie(true, false) 1089 c.NewRequest(registerClientsRequest(c, Context, ElementHeader, NumClientSpecs, NumRanges, ClientSpecs, Ranges), cookie) 1090 return RegisterClientsCookie{cookie} 1091 } 1092 1093 // Check returns an error if one occurred for checked requests that are not expecting a reply. 1094 // This cannot be called for requests expecting a reply, nor for unchecked requests. 1095 func (cook RegisterClientsCookie) Check() error { 1096 return cook.Cookie.Check() 1097 } 1098 1099 // Write request to wire for RegisterClients 1100 // registerClientsRequest writes a RegisterClients request to a byte slice. 1101 func registerClientsRequest(c *xgb.Conn, Context Context, ElementHeader ElementHeader, NumClientSpecs uint32, NumRanges uint32, ClientSpecs []ClientSpec, Ranges []Range) []byte { 1102 size := xgb.Pad((((20 + xgb.Pad((int(NumClientSpecs) * 4))) + 4) + xgb.Pad((int(NumRanges) * 24)))) 1103 b := 0 1104 buf := make([]byte, size) 1105 1106 c.ExtLock.RLock() 1107 buf[b] = c.Extensions["RECORD"] 1108 c.ExtLock.RUnlock() 1109 b += 1 1110 1111 buf[b] = 2 // request opcode 1112 b += 1 1113 1114 blen := b 1115 b += 2 1116 1117 xgb.Put32(buf[b:], uint32(Context)) 1118 b += 4 1119 1120 buf[b] = byte(ElementHeader) 1121 b += 1 1122 1123 b += 3 // padding 1124 1125 xgb.Put32(buf[b:], NumClientSpecs) 1126 b += 4 1127 1128 xgb.Put32(buf[b:], NumRanges) 1129 b += 4 1130 1131 for i := 0; i < int(NumClientSpecs); i++ { 1132 xgb.Put32(buf[b:], uint32(ClientSpecs[i])) 1133 b += 4 1134 } 1135 1136 b = (b + 3) & ^3 // alignment gap 1137 1138 b += RangeListBytes(buf[b:], Ranges) 1139 1140 b = xgb.Pad(b) 1141 xgb.Put16(buf[blen:], uint16(b/4)) // write request size in 4-byte units 1142 return buf[:b] 1143 } 1144 1145 // UnregisterClientsCookie is a cookie used only for UnregisterClients requests. 1146 type UnregisterClientsCookie struct { 1147 *xgb.Cookie 1148 } 1149 1150 // UnregisterClients sends an unchecked request. 1151 // If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. 1152 func UnregisterClients(c *xgb.Conn, Context Context, NumClientSpecs uint32, ClientSpecs []ClientSpec) UnregisterClientsCookie { 1153 c.ExtLock.RLock() 1154 defer c.ExtLock.RUnlock() 1155 if _, ok := c.Extensions["RECORD"]; !ok { 1156 panic("Cannot issue request 'UnregisterClients' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 1157 } 1158 cookie := c.NewCookie(false, false) 1159 c.NewRequest(unregisterClientsRequest(c, Context, NumClientSpecs, ClientSpecs), cookie) 1160 return UnregisterClientsCookie{cookie} 1161 } 1162 1163 // UnregisterClientsChecked sends a checked request. 1164 // If an error occurs, it can be retrieved using UnregisterClientsCookie.Check() 1165 func UnregisterClientsChecked(c *xgb.Conn, Context Context, NumClientSpecs uint32, ClientSpecs []ClientSpec) UnregisterClientsCookie { 1166 c.ExtLock.RLock() 1167 defer c.ExtLock.RUnlock() 1168 if _, ok := c.Extensions["RECORD"]; !ok { 1169 panic("Cannot issue request 'UnregisterClients' using the uninitialized extension 'RECORD'. record.Init(connObj) must be called first.") 1170 } 1171 cookie := c.NewCookie(true, false) 1172 c.NewRequest(unregisterClientsRequest(c, Context, NumClientSpecs, ClientSpecs), cookie) 1173 return UnregisterClientsCookie{cookie} 1174 } 1175 1176 // Check returns an error if one occurred for checked requests that are not expecting a reply. 1177 // This cannot be called for requests expecting a reply, nor for unchecked requests. 1178 func (cook UnregisterClientsCookie) Check() error { 1179 return cook.Cookie.Check() 1180 } 1181 1182 // Write request to wire for UnregisterClients 1183 // unregisterClientsRequest writes a UnregisterClients request to a byte slice. 1184 func unregisterClientsRequest(c *xgb.Conn, Context Context, NumClientSpecs uint32, ClientSpecs []ClientSpec) []byte { 1185 size := xgb.Pad((12 + xgb.Pad((int(NumClientSpecs) * 4)))) 1186 b := 0 1187 buf := make([]byte, size) 1188 1189 c.ExtLock.RLock() 1190 buf[b] = c.Extensions["RECORD"] 1191 c.ExtLock.RUnlock() 1192 b += 1 1193 1194 buf[b] = 3 // request opcode 1195 b += 1 1196 1197 xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units 1198 b += 2 1199 1200 xgb.Put32(buf[b:], uint32(Context)) 1201 b += 4 1202 1203 xgb.Put32(buf[b:], NumClientSpecs) 1204 b += 4 1205 1206 for i := 0; i < int(NumClientSpecs); i++ { 1207 xgb.Put32(buf[b:], uint32(ClientSpecs[i])) 1208 b += 4 1209 } 1210 1211 return buf 1212 }