github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/examples/create-window/main.go (about) 1 // Example create-window shows how to create a window, map it, resize it, 2 // and listen to structure and key events (i.e., when the window is resized 3 // by the window manager, or when key presses/releases are made when the 4 // window has focus). The events are printed to stdout. 5 package main 6 7 import ( 8 "fmt" 9 10 "github.com/robotn/xgb" 11 "github.com/robotn/xgb/xproto" 12 ) 13 14 func main() { 15 X, err := xgb.NewConn() 16 if err != nil { 17 fmt.Println(err) 18 return 19 } 20 21 // xproto.Setup retrieves the Setup information from the setup bytes 22 // gathered during connection. 23 setup := xproto.Setup(X) 24 25 // This is the default screen with all its associated info. 26 screen := setup.DefaultScreen(X) 27 28 // Any time a new resource (i.e., a window, pixmap, graphics context, etc.) 29 // is created, we need to generate a resource identifier. 30 // If the resource is a window, then use xproto.NewWindowId. If it's for 31 // a pixmap, then use xproto.NewPixmapId. And so on... 32 wid, _ := xproto.NewWindowId(X) 33 34 // CreateWindow takes a boatload of parameters. 35 xproto.CreateWindow(X, screen.RootDepth, wid, screen.Root, 36 0, 0, 500, 500, 0, 37 xproto.WindowClassInputOutput, screen.RootVisual, 0, []uint32{}) 38 39 // This call to ChangeWindowAttributes could be factored out and 40 // included with the above CreateWindow call, but it is left here for 41 // instructive purposes. It tells X to send us events when the 'structure' 42 // of the window is changed (i.e., when it is resized, mapped, unmapped, 43 // etc.) and when a key press or a key release has been made when the 44 // window has focus. 45 // We also set the 'BackPixel' to white so that the window isn't butt ugly. 46 xproto.ChangeWindowAttributes(X, wid, 47 xproto.CwBackPixel|xproto.CwEventMask, 48 []uint32{ // values must be in the order defined by the protocol 49 0xffffffff, 50 xproto.EventMaskStructureNotify | 51 xproto.EventMaskKeyPress | 52 xproto.EventMaskKeyRelease}) 53 54 // MapWindow makes the window we've created appear on the screen. 55 // We demonstrated the use of a 'checked' request here. 56 // A checked request is a fancy way of saying, "do error handling 57 // synchronously." Namely, if there is a problem with the MapWindow request, 58 // we'll get the error *here*. If we were to do a normal unchecked 59 // request (like the above CreateWindow and ChangeWindowAttributes 60 // requests), then we would only see the error arrive in the main event 61 // loop. 62 // 63 // Typically, checked requests are useful when you need to make sure they 64 // succeed. Since they are synchronous, they incur a round trip cost before 65 // the program can continue, but this is only going to be noticeable if 66 // you're issuing tons of requests in succession. 67 // 68 // Note that requests without replies are by default unchecked while 69 // requests *with* replies are checked by default. 70 err = xproto.MapWindowChecked(X, wid).Check() 71 if err != nil { 72 fmt.Printf("Checked Error for mapping window %d: %s\n", wid, err) 73 } else { 74 fmt.Printf("Map window %d successful!\n", wid) 75 } 76 77 // This is an example of an invalid MapWindow request and what an error 78 // looks like. 79 err = xproto.MapWindowChecked(X, 0).Check() 80 if err != nil { 81 fmt.Printf("Checked Error for mapping window 0x1: %s\n", err) 82 } else { // neva 83 fmt.Printf("Map window 0x1 successful!\n") 84 } 85 86 // Start the main event loop. 87 for { 88 // WaitForEvent either returns an event or an error and never both. 89 // If both are nil, then something went wrong and the loop should be 90 // halted. 91 // 92 // An error can only be seen here as a response to an unchecked 93 // request. 94 ev, xerr := X.WaitForEvent() 95 if ev == nil && xerr == nil { 96 fmt.Println("Both event and error are nil. Exiting...") 97 return 98 } 99 100 if ev != nil { 101 fmt.Printf("Event: %s\n", ev) 102 } 103 if xerr != nil { 104 fmt.Printf("Error: %s\n", xerr) 105 } 106 } 107 }