func main() { X, err := xgb.NewConn() if err != nil { log.Fatal(err) } // Get the window id of the root window. setup := xproto.Setup(X) root := setup.DefaultScreen(X).Root // Get the atom id (i.e., intern an atom) of "_NET_ACTIVE_WINDOW". aname := "_NET_ACTIVE_WINDOW" activeAtom, err := xproto.InternAtom(X, true, uint16(len(aname)), aname).Reply() if err != nil { log.Fatal(err) } // Get the atom id (i.e., intern an atom) of "_NET_WM_NAME". aname = "_NET_WM_NAME" nameAtom, err := xproto.InternAtom(X, true, uint16(len(aname)), aname).Reply() if err != nil { log.Fatal(err) } // Get the actual value of _NET_ACTIVE_WINDOW. // Note that 'reply.Value' is just a slice of bytes, so we use an // XGB helper function, 'Get32', to pull an unsigned 32-bit integer out // of the byte slice. We then convert it to an X resource id so it can // be used to get the name of the window in the next GetProperty request. reply, err := xproto.GetProperty(X, false, root, activeAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { log.Fatal(err) } windowId := xproto.Window(xgb.Get32(reply.Value)) fmt.Printf("Active window id: %X\n", windowId) // Now get the value of _NET_WM_NAME for the active window. // Note that this time, we simply convert the resulting byte slice, // reply.Value, to a string. reply, err = xproto.GetProperty(X, false, windowId, nameAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { log.Fatal(err) } fmt.Printf("Active window name: %s\n", string(reply.Value)) }
// Replace existing window manager func usurpWM(X *xgb.Conn, screen *xproto.ScreenInfo) { wmName := fmt.Sprintf("WM_S%d", X.DefaultScreen) managerAtom, err := xproto.InternAtom(X, true, uint16(len(wmName)), wmName).Reply() if err != nil { log.Fatal(err) } fakeWindow, _ := xproto.NewWindowId(X) xproto.CreateWindow(X, // Connection screen.RootDepth, // Depth fakeWindow, // Window Id screen.Root, // Parent Window -1000, -1000, // x, y 1, 1, // width, height 0, // border_width xproto.WindowClassInputOutput, // class screen.RootVisual, // visual xproto.CwEventMask|xproto.CwOverrideRedirect, []uint32{1, xproto.EventMaskPropertyChange}) // masks xproto.MapWindow(X, fakeWindow) err = xproto.SetSelectionOwnerChecked(X, fakeWindow, managerAtom.Atom, xproto.TimeCurrentTime).Check() if err != nil { log.Fatal(err) } }
func (s *screenImpl) internAtom(name string) (xproto.Atom, error) { r, err := xproto.InternAtom(s.xc, false, uint16(len(name)), name).Reply() if err != nil { return 0, fmt.Errorf("x11driver: xproto.InternAtom failed: %v", err) } if r == nil { return 0, fmt.Errorf("x11driver: xproto.InternAtom failed") } return r.Atom, nil }
func internAtom(name string) xp.Atom { r, err := xp.InternAtom(xConn, false, uint16(len(name)), name).Reply() if err != nil { log.Fatal(err) } if r == nil { return 0 } return r.Atom }
func (logger *WindowLogger) getCurWindowTitle() (name string, err error) { // Get the window id of the root window. setup := xproto.Setup(logger.X11Connection) root := setup.DefaultScreen(logger.X11Connection).Root // Get the atom id (i.e., intern an atom) of "_NET_ACTIVE_WINDOW". aname := "_NET_ACTIVE_WINDOW" activeAtom, err := xproto.InternAtom(logger.X11Connection, true, uint16(len(aname)), aname).Reply() if err != nil { return "", err } // Get the atom id (i.e., intern an atom) of "_NET_WM_NAME". aname = "_NET_WM_NAME" nameAtom, err := xproto.InternAtom(logger.X11Connection, true, uint16(len(aname)), aname).Reply() if err != nil { return "", err } // Get the actual value of _NET_ACTIVE_WINDOW. // Note that 'reply.Value' is just a slice of bytes, so we use an // XGB helper function, 'Get32', to pull an unsigned 32-bit integer out // of the byte slice. We then convert it to an X resource id so it can // be used to get the name of the window in the next GetProperty request. reply, err := xproto.GetProperty(logger.X11Connection, false, root, activeAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { return "", err } windowId := xproto.Window(xgb.Get32(reply.Value)) // Now get the value of _NET_WM_NAME for the active window. // Note that this time, we simply convert the resulting byte slice, // reply.Value, to a string. reply, err = xproto.GetProperty(logger.X11Connection, false, windowId, nameAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { return "", err } return string(reply.Value), nil }
func (a *atomic) atom(name string, onlyIfExists bool) (xproto.Atom, error) { if aid, ok := a.atomGet(name); ok { return aid, nil } reply, err := xproto.InternAtom(a.c, onlyIfExists, uint16(len(name)), name).Reply() if err != nil { return 0, AtomInternError(name, err) } a.cacheAtom(name, reply.Atom) return reply.Atom, nil }
func main() { X, err := xgb.NewConn() if err != nil { log.Fatal(err) } names := seqNames(flagRequests) fcpu, err := os.Create(flagCpuProfName) if err != nil { log.Fatal(err) } defer fcpu.Close() pprof.StartCPUProfile(fcpu) defer pprof.StopCPUProfile() start := time.Now() cookies := make([]xproto.InternAtomCookie, flagRequests) for i := 0; i < flagRequests; i++ { cookies[i] = xproto.InternAtom(X, false, uint16(len(names[i])), names[i]) } for _, cookie := range cookies { cookie.Reply() } fmt.Printf("Exec time: %s\n\n", time.Since(start)) fmem, err := os.Create(flagMemProfName) if err != nil { log.Fatal(err) } defer fmem.Close() pprof.WriteHeapProfile(fmem) memStats := &runtime.MemStats{} runtime.ReadMemStats(memStats) // This isn't right. I'm not sure what's wrong. lastGcTime := time.Unix(int64(memStats.LastGC/1000000000), int64(memStats.LastGC-memStats.LastGC/1000000000)) fmt.Printf("Alloc: %d\n", memStats.Alloc) fmt.Printf("TotalAlloc: %d\n", memStats.TotalAlloc) fmt.Printf("LastGC: %s\n", lastGcTime) fmt.Printf("PauseTotalNs: %d\n", memStats.PauseTotalNs) fmt.Printf("PauseNs: %d\n", memStats.PauseNs) fmt.Printf("NumGC: %d\n", memStats.NumGC) }
// Atom interns an atom and panics if there is any error. func Atom(xu *xgbutil.XUtil, name string, onlyIfExists bool) (xproto.Atom, error) { // Check the cache first if aid, ok := atomGet(xu, name); ok { return aid, nil } reply, err := xproto.InternAtom(xu.Conn(), onlyIfExists, uint16(len(name)), name).Reply() if err != nil { return 0, fmt.Errorf("Atom: Error interning atom '%s': %s", name, err) } // If we're here, it means we didn't have this atom cached. So cache it! cacheAtom(xu, name, reply.Atom) return reply.Atom, nil }
func newBrightness(Xu *xgbutil.XUtil) (*brightness, error) { const atomName = "Backlight" atomReply, err := xproto.InternAtom(Xu.Conn(), true, uint16(len(atomName)), atomName).Reply() if err != nil { return nil, fmt.Errorf("no backlight: %v", err) } b := &brightness{ prop: atomReply.Atom, } if err := bind(Xu, binding{"XF86MonBrightnessUp", b.up}, binding{"XF86MonBrightnessDown", b.down}, ); err != nil { return nil, err } return b, nil }
func main() { var serve *bool = flag.Bool("serve", false, "Listen for connections") flag.Usage = usage flag.Parse() if remote := os.Getenv("SSH_CONNECTION"); remote == "" && len(flag.Args()) != 0 { invoked_as := os.Args[0] actual_binary, err := os.Readlink("/proc/self/exe") if err != nil { log.Panic("/proc/self/exe doesn't exist!") } log.Print("Invoked as: '", invoked_as, "' (actual=", actual_binary, ")") log.Panic("Not yet implemented: Would have run locally") return } c, err := xgb.NewConn() if err != nil { log.Panic("cannot connect: %v\n", err) } s := xproto.Setup(c).DefaultScreen(c) rl_execute_reply, err := xproto.InternAtom(c, false, uint16(len(atomname)), atomname).Reply() if err != nil { panic(err) } rl_execute_atom := rl_execute_reply.Atom if *serve { //log.Printf("c = %v, s = %v, a = %v", c, s, rl_execute_atom) start_server(c, s, rl_execute_atom) } else { if len(flag.Args()) == 0 { usage() } connect(c, s, rl_execute_atom, fixup_args(flag.Args())) } }
// Listen ... func Listen(fn func(e Event)) error { X, err := xgb.NewConn() if err != nil { log.Fatal(err) } setup := xproto.Setup(X) root := setup.DefaultScreen(X).Root var prevWindowID xproto.Window var prevClasses []string for { <-time.After(msRefresh * time.Millisecond) // From one of the xgb examples. aname := "_NET_ACTIVE_WINDOW" activeAtom, err := xproto.InternAtom(X, true, uint16(len(aname)), aname).Reply() if err != nil { log.Println(err) continue } reply, err := xproto.GetProperty(X, false, root, activeAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { log.Println(err) continue } windowID := xproto.Window(xgb.Get32(reply.Value)) aname = "WM_CLASS" nameAtom, err := xproto.InternAtom(X, true, uint16(len(aname)), aname).Reply() if err != nil { log.Println(err) continue } reply, err = xproto.GetProperty(X, false, windowID, nameAtom.Atom, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply() if err != nil { log.Println(err) continue } classes := stringSlice(reply.Value) // Check if active window has changed since last time. if windowID != prevWindowID { fn(Lost{ WMClass: prevClasses, }) fn(Gained{ WMClass: classes, }) prevWindowID = windowID prevClasses = classes } } }
func main() { // Open the connection to the X server X, err := xgb.NewConn() if err != nil { log.Fatal(err) } defer X.Close() setup := xproto.Setup(X) // Get the first screen screen := setup.DefaultScreen(X) // Replace existing window manager wmName := fmt.Sprintf("WM_S%d", X.DefaultScreen) managerAtom, err := xproto.InternAtom(X, true, uint16(len(wmName)), wmName).Reply() if err != nil { log.Fatal(err) } fakeWindow, _ := xproto.NewWindowId(X) xproto.CreateWindow(X, // Connection screen.RootDepth, // Depth fakeWindow, // Window Id screen.Root, // Parent Window -1000, -1000, // x, y 1, 1, // width, height 0, // border_width xproto.WindowClassInputOutput, // class screen.RootVisual, // visual xproto.CwEventMask|xproto.CwOverrideRedirect, []uint32{1, xproto.EventMaskPropertyChange}) // masks xproto.MapWindow(X, fakeWindow) err = xproto.SetSelectionOwnerChecked(X, fakeWindow, managerAtom.Atom, xproto.TimeCurrentTime).Check() if err != nil { fmt.Println("foo") log.Fatal(err) } arcs := []xproto.Arc{ {10, 100, 60, 40, 0, 90 << 6}, {90, 100, 55, 40, 0, 270 << 6}} // Create black (foreground) graphic context foreground, _ := xproto.NewGcontextId(X) mask := uint32(xproto.GcForeground | xproto.GcGraphicsExposures) values := []uint32{screen.BlackPixel, 0} xproto.CreateGC(X, foreground, xproto.Drawable(screen.Root), mask, values) // Ask for our window's Id win, _ := xproto.NewWindowId(X) winDrawable := xproto.Drawable(win) // Create the window mask = uint32(xproto.CwBackPixel | xproto.CwEventMask) values = []uint32{screen.WhitePixel, xproto.EventMaskExposure} xproto.CreateWindow(X, // Connection screen.RootDepth, // Depth win, // Window Id screen.Root, // Parent Window 0, 0, // x, y 150, 150, // width, height 10, // border_width xproto.WindowClassInputOutput, // class screen.RootVisual, // visual mask, values) // masks // Map the window on the screen xproto.MapWindow(X, win) // Obey the window-delete protocol tp := "WM_PROTOCOLS" prp := "WM_DELETE_WINDOW" typeAtom, _ := xproto.InternAtom(X, true, uint16(len(tp)), tp).Reply() propertyAtom, _ := xproto.InternAtom(X, true, uint16(len(prp)), prp).Reply() data := make([]byte, 4) xgb.Put32(data, uint32(propertyAtom.Atom)) xproto.ChangeProperty(X, xproto.PropModeReplace, win, typeAtom.Atom, xproto.AtomAtom, 32, 1, data) // Main loop for { evt, err := X.WaitForEvent() fmt.Printf("An event of type %T occured.\n", evt) if evt == nil && err == nil { fmt.Println("Exiting....") return } else if err != nil { log.Fatal(err) } switch event := evt.(type) { case xproto.ExposeEvent: /* We draw the arcs */ xproto.PolyArc(X, winDrawable, foreground, arcs) case xproto.ClientMessageEvent: if len(event.Data.Data32) > 0 { data := xproto.Atom(event.Data.Data32[0]) if data == propertyAtom.Atom { return } else { atomName, _ := xproto.GetAtomName(X, data).Reply() fmt.Println(atomName.Name) } } else { atomName, _ := xproto.GetAtomName(X, event.Type).Reply() fmt.Println(atomName.Name) } default: /* Unknown event type, ignore it */ } } return }
func main() { sleepy := time.Millisecond X, _ := xgbutil.NewConn() conn := X.Conn() aDesktop := "_NET_WM_DESKTOP" aActive := "_NET_ACTIVE_WINDOW" xwindow.Listen(X, X.RootWin(), xproto.EventMaskPropertyChange) xevent.PropertyNotifyFun( func(X *xgbutil.XUtil, ev xevent.PropertyNotifyEvent) { for i := 0; i < 1; i++ { log.Println("PROPERTY CHANGE") } }).Connect(X, X.RootWin()) go func() { for { reply, err := xproto.InternAtom(conn, true, uint16(len(aDesktop)), aDesktop).Reply() if err != nil { log.Fatal(err) } log.Println("A1-299", reply.Sequence, reply.Atom) time.Sleep(sleepy) } }() go func() { for { reply, err := xproto.InternAtom(conn, true, uint16(len(aActive)), aActive).Reply() if err != nil { log.Fatal(err) } log.Println("A2-294", reply.Sequence, reply.Atom) time.Sleep(sleepy) } }() go func() { for { reply, err := xproto.GetGeometry(conn, 0x1).Reply() if err != nil { log.Println("0x1:", err) } else { log.Println("0x1:", reply) } time.Sleep(sleepy) } }() go func() { for { reply, err := xproto.GetGeometry(conn, 0x2).Reply() if err != nil { log.Println("0x2:", err) } else { log.Println("0x2:", reply) } time.Sleep(sleepy) } }() go xevent.Main(X) select {} }
func xwmInit(fd uintptr) { X := fromFd(fd) defer X.Conn().Close() root := xwindow.New(X, X.RootWin()) if _, err := root.Geometry(); err != nil { panic(err) } // if names, _ := ewmh.DesktopNamesGet(X); len(names) > 0 { // println(names) // } composite.Init(X.Conn()) atomNames := []string{ "WL_SURFACE_ID", "WM_DELETE_WINDOW", "WM_PROTOCOLS", "WM_S0", "WM_NORMAL_HINTS", "WM_TAKE_FOCUS", "WM_STATE", "WM_CLIENT_MACHINE", "_NET_WM_CM_S0", "_NET_WM_NAME", "_NET_WM_PID", "_NET_WM_ICON", "_NET_WM_STATE", "_NET_WM_STATE_FULLSCREEN", "_NET_WM_USER_TIME", "_NET_WM_ICON_NAME", "_NET_WM_WINDOW_TYPE", "_NET_WM_WINDOW_TYPE_DESKTOP", "_NET_WM_WINDOW_TYPE_DOCK", "_NET_WM_WINDOW_TYPE_TOOLBAR", "_NET_WM_WINDOW_TYPE_MENU", "_NET_WM_WINDOW_TYPE_UTILITY", "_NET_WM_WINDOW_TYPE_SPLASH", "_NET_WM_WINDOW_TYPE_DIALOG", "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", "_NET_WM_WINDOW_TYPE_POPUP_MENU", "_NET_WM_WINDOW_TYPE_TOOLTIP", "_NET_WM_WINDOW_TYPE_NOTIFICATION", "_NET_WM_WINDOW_TYPE_COMBO", "_NET_WM_WINDOW_TYPE_DND", "_NET_WM_WINDOW_TYPE_NORMAL", "_NET_WM_MOVERESIZE", "_NET_SUPPORTING_WM_CHECK", "_NET_SUPPORTED", "_MOTIF_WM_HINTS", "CLIPBOARD", "CLIPBOARD_MANAGER", "TARGETS", "UTF8_STRING", "_WL_SELECTION", "INCR", "TIMESTAMP", "MULTIPLE", "UTF8_STRING", "COMPOUND_TEXT", "TEXT", "STRING", "text/plain;charset=utf-8", "text/plain", "XdndSelection", "XdndAware", "XdndEnter", "XdndLeave", "XdndDrop", "XdndStatus", "XdndFinished", "XdndTypeList", "XdndActionCopy", } cookies := make([]xproto.InternAtomCookie, len(atomNames)) for i := 0; i < len(atomNames); i++ { cookies[i] = xproto.InternAtom(X.Conn(), false, uint16(len(atomNames[i])), atomNames[i]) } /* Try to select for substructure redirect. */ evMasks := xproto.EventMaskPropertyChange | xproto.EventMaskFocusChange | xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease | xproto.EventMaskStructureNotify | xproto.EventMaskSubstructureNotify | xproto.EventMaskSubstructureRedirect root.Listen(evMasks) composite.RedirectSubwindows(X.Conn(), root.Id, composite.RedirectManual) // change config // data := []byte{1} // propAtom, _ := xprop.Atm(X, "_NET_SUPPORTED") // var format byte = 32 // xproto.ChangePropertyChecked(X.Conn(), xproto.PropModeReplace, // root.Id, propAtom, xproto.AtomAtom, format, // uint32(len(data)/(int(format)/8)), data) ewmh.SupportedSet(X, []string{ "_NET_SUPPORTED", "_NET_CLIENT_LIST", "_NET_NUMBER_OF_DESKTOPS", "_NET_DESKTOP_GEOMETRY", "_NET_CURRENT_DESKTOP", "_NET_VISIBLE_DESKTOPS", "_NET_DESKTOP_NAMES", "_NET_ACTIVE_WINDOW", "_NET_SUPPORTING_WM_CHECK", "_NET_CLOSE_WINDOW", "_NET_MOVERESIZE_WINDOW", "_NET_RESTACK_WINDOW", "_NET_WM_NAME", "_NET_WM_DESKTOP", "_NET_WM_WINDOW_TYPE", "_NET_WM_WINDOW_TYPE_DESKTOP", "_NET_WM_WINDOW_TYPE_DOCK", "_NET_WM_WINDOW_TYPE_TOOLBAR", "_NET_WM_WINDOW_TYPE_MENU", "_NET_WM_WINDOW_TYPE_UTILITY", "_NET_WM_WINDOW_TYPE_SPLASH", "_NET_WM_WINDOW_TYPE_DIALOG", "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", "_NET_WM_WINDOW_TYPE_POPUP_MENU", "_NET_WM_WINDOW_TYPE_TOOLTIP", "_NET_WM_WINDOW_TYPE_NOTIFICATION", "_NET_WM_WINDOW_TYPE_COMBO", "_NET_WM_WINDOW_TYPE_DND", "_NET_WM_WINDOW_TYPE_NORMAL", "_NET_WM_STATE", "_NET_WM_STATE_STICKY", "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_SKIP_TASKBAR", "_NET_WM_STATE_SKIP_PAGER", "_NET_WM_STATE_HIDDEN", "_NET_WM_STATE_FULLSCREEN", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_BELOW", "_NET_WM_STATE_DEMANDS_ATTENTION", "_NET_WM_STATE_FOCUSED", "_NET_WM_ALLOWED_ACTIONS", "_NET_WM_ACTION_MOVE", "_NET_WM_ACTION_RESIZE", "_NET_WM_ACTION_MINIMIZE", "_NET_WM_ACTION_STICK", "_NET_WM_ACTION_MAXIMIZE_HORZ", "_NET_WM_ACTION_MAXIMIZE_VERT", "_NET_WM_ACTION_FULLSCREEN", "_NET_WM_ACTION_CHANGE_DESKTOP", "_NET_WM_ACTION_CLOSE", "_NET_WM_ACTION_ABOVE", "_NET_AM_ACTION_BELOW", "_NET_WM_STRUT_PARTIAL", "_NET_WM_ICON", "_NET_FRAME_EXTENTS", "WM_TRANSIENT_FOR", }) // create wm window win, _ := xwindow.Create(X, root.Id) xproto.MapWindow(X.Conn(), win.Id) atomValues := make([]xproto.Atom, len(atomNames)) for num, cookie := range cookies { reply, _ := cookie.Reply() atomValues[num] = reply.Atom } /* take WM_S0 selection last, which * signals to Xwayland that we're done with setup. */ xproto.SetSelectionOwner(X.Conn(), win.Id, atomValues[3], xproto.TimeCurrentTime, ) mapResquest := func(event xgb.Event) { ev, _ := event.(xproto.MapRequestEvent) log.Info("MapRequest: ", ev) xproto.MapWindow(X.Conn(), ev.Window) icccm.WmStateSet(X, ev.Window, &icccm.WmState{ State: icccm.StateNormal, Icon: ev.Window, }) // TODO: set _net_wm_state } for { x := X.Conn() ev, xerr := x.WaitForEvent() if ev == nil && xerr == nil { fmt.Println("Both event and error are nil. Exiting...") return } // if ev != nil { // fmt.Printf("Event: %s\n", ev) // } if xerr != nil { fmt.Printf("Error: %s\n", xerr) } switch ev.(type) { case xproto.CreateNotifyEvent: createNotify(X, ev) fmt.Printf("Event: %s\n", ev) case xproto.DestroyNotifyEvent: destroyNotify(X, ev) fmt.Printf("Event: %s\n", ev) case xproto.MapRequestEvent: mapResquest(ev) case xproto.ConfigureNotifyEvent: configureNotify(X, ev) case xproto.PropertyNotifyEvent: fmt.Printf("Event: %s\n", ev) case xproto.ClientMessageEvent: clientMessage(X, ev) case xproto.ConfigureRequestEvent: configureRequest(X, ev) case xproto.UnmapNotifyEvent: unmapNotify(X, ev) default: log.Info("Event:", ev) } } // xevent.MapRequestFun( // func(X *xgbutil.XUtil, e xevent.MapRequestEvent) { // println(e.Window) // }).Connect(X, root.Id) // xevent.ConfigureNotifyFun( // func(X *xgbutil.XUtil, e xevent.ConfigureNotifyEvent) { // fmt.Printf("(%d, %d) %dx%d\n", e.X, e.Y, e.Width, e.Height) // }).Connect(X, root.Id) // xevent.FocusInFun( // func(X *xgbutil.XUtil, e xevent.FocusInEvent) { // fmt.Printf("(%v, %v)\n", e.Mode, e.Detail) // }).Connect(X, root.Id) // xevent.Main(X) }
func main() { // Open the connection to the X server X, err := xgb.NewConn() if err != nil { log.Fatal(err) } defer X.Close() // geometric objects points := []xproto.Point{ {10, 10}, {10, 20}, {20, 10}, {20, 20}} polyline := []xproto.Point{ {50, 10}, {5, 20}, // rest of points are relative {25, -20}, {10, 10}} segments := []xproto.Segment{ {100, 10, 140, 30}, {110, 25, 130, 60}} rectangles := []xproto.Rectangle{ {10, 50, 40, 20}, {80, 50, 10, 40}} arcs := []xproto.Arc{ {10, 100, 60, 40, 0, 90 << 6}, {90, 100, 55, 40, 0, 270 << 6}} setup := xproto.Setup(X) // Get the first screen screen := setup.DefaultScreen(X) // Create black (foreground) graphic context foreground, _ := xproto.NewGcontextId(X) mask := uint32(xproto.GcForeground | xproto.GcGraphicsExposures) values := []uint32{screen.BlackPixel, 0} xproto.CreateGC(X, foreground, xproto.Drawable(screen.Root), mask, values) // Ask for our window's Id win, _ := xproto.NewWindowId(X) winDrawable := xproto.Drawable(win) // Create the window mask = uint32(xproto.CwBackPixel | xproto.CwEventMask) values = []uint32{screen.WhitePixel, xproto.EventMaskExposure} xproto.CreateWindow(X, // Connection screen.RootDepth, // Depth win, // Window Id screen.Root, // Parent Window 0, 0, // x, y 150, 150, // width, height 10, // border_width xproto.WindowClassInputOutput, // class screen.RootVisual, // visual mask, values) // masks // Map the window on the screen xproto.MapWindow(X, win) // Obey the window-delete protocol tp := "WM_PROTOCOLS" prp := "WM_DELETE_WINDOW" typeAtom, _ := xproto.InternAtom(X, true, uint16(len(tp)), tp).Reply() propertyAtom, _ := xproto.InternAtom(X, true, uint16(len(prp)), prp).Reply() // It turns out that we need the window ID as a byte-stream... WTF!! // xprop.ChangeProp(xu, win, 8, "WM_NAME", "STRING", ([]byte)(name)) // ChangeProp(xu *xgbutil.XUtil, win xproto.Window, format byte, prop string, typ string, data []byte) data := make([]byte, 4) xgb.Put32(data, uint32(propertyAtom.Atom)) xproto.ChangeProperty(X, xproto.PropModeReplace, win, typeAtom.Atom, xproto.AtomAtom, 32, 1, data) for { evt, err := X.WaitForEvent() fmt.Printf("An event of type %T occured.\n", evt) if evt == nil && err == nil { fmt.Println("Exiting....") return } else if err != nil { log.Fatal(err) } switch event := evt.(type) { case xproto.ExposeEvent: /* We draw the points */ xproto.PolyPoint(X, xproto.CoordModeOrigin, winDrawable, foreground, points) /* We draw the polygonal line */ xproto.PolyLine(X, xproto.CoordModePrevious, winDrawable, foreground, polyline) /* We draw the segments */ xproto.PolySegment(X, winDrawable, foreground, segments) /* We draw the rectangles */ xproto.PolyRectangle(X, winDrawable, foreground, rectangles) /* We draw the arcs */ xproto.PolyArc(X, winDrawable, foreground, arcs) case xproto.ClientMessageEvent: if len(event.Data.Data32) > 0 { data := xproto.Atom(event.Data.Data32[0]) if data == propertyAtom.Atom { return } else { atomName, _ := xproto.GetAtomName(X, data).Reply() fmt.Println(atomName.Name) } } else { atomName, _ := xproto.GetAtomName(X, event.Type).Reply() fmt.Println(atomName.Name) } default: /* Unknown event type, ignore it */ } } return }