// XEvent proccess an x11 event. func xEvent(e xgb.Event) { switch event := e.(type) { case xgb.ButtonPressEvent: w, ok := widgetTable[event.Event] if !ok { break } ev := sparta.MouseEvent{ Button: getButton(event.Detail), State: sparta.StateKey(event.State), Loc: image.Pt(int(event.EventX), int(event.EventY)), } w.OnEvent(ev) w.Focus() case xgb.ButtonReleaseEvent: if (event.Detail == 4) || (event.Detail == 5) { break } w, ok := widgetTable[event.Event] if !ok { break } ev := sparta.MouseEvent{ Button: -getButton(event.Detail), State: sparta.StateKey(event.State), Loc: image.Pt(int(event.EventX), int(event.EventY)), } w.OnEvent(ev) case xgb.ClientMessageEvent: w, ok := widgetTable[event.Window] if !ok { break } switch event.Type { case atomMsg: src := xgb.Id(event.Data.Data32[0]) val := int(int32(event.Data.Data32[1])) sw, ok := widgetTable[src] if !ok { sw = nil } w.OnEvent(sparta.CommandEvent{Source: sw, Value: val}) break case wmProtocols: if w.Property(sparta.Parent) != nil { break } if event.Type != wmProtocols { break } if xgb.Id(event.Data.Data32[0]) != atomDel { break } w.OnEvent(sparta.CloseEvent{}) } case xgb.DestroyNotifyEvent: w, ok := widgetTable[event.Window] if !ok { break } if w.Property(sparta.Parent) != nil { break } w.OnEvent(sparta.CloseEvent{}) case xgb.ConfigureNotifyEvent: w, ok := widgetTable[event.Window] if !ok { break } rect := w.Property(sparta.Geometry).(image.Rectangle) if (rect.Dx() == int(event.Width)) && (rect.Dy() == int(event.Height)) { break } ev := sparta.ConfigureEvent{image.Rect(int(event.X), int(event.Y), int(event.X)+int(event.Width), int(event.Y)+int(event.Height))} w.OnEvent(ev) xwin.ClearArea(true, event.Window, 0, 0, event.Width, event.Height) case xgb.ExposeEvent: // only proccess the last expose event if event.Count != 0 { break } w, ok := widgetTable[event.Window] if !ok { break } win := w.Window().(*window) xwin.ChangeGC(win.gc, xgb.GCForeground, []uint32{win.back}) r := xgb.Rectangle{ X: int16(event.X), Y: int16(event.Y), Width: event.Width, Height: event.Height, } xwin.PolyFillRectangle(win.id, win.gc, []xgb.Rectangle{r}) xwin.ChangeGC(win.gc, xgb.GCForeground, []uint32{win.fore}) win.isExpose = true ev := sparta.ExposeEvent{image.Rect(int(event.X), int(event.Y), int(event.X+event.Width), int(event.Y+event.Height))} w.OnEvent(ev) win.isExpose = false case xgb.KeyPressEvent: w, ok := widgetTable[event.Event] if !ok { break } ev := sparta.KeyEvent{ Key: sparta.Key(getKeyValue(int(event.Detail), int(event.State))), State: sparta.StateKey(event.State), Loc: image.Pt(int(event.EventX), int(event.EventY)), } w.OnEvent(ev) case xgb.KeyReleaseEvent: w, ok := widgetTable[event.Event] if !ok { break } ev := sparta.KeyEvent{ Key: -sparta.Key(keysyms[int(event.Detail)][0]), State: sparta.StateKey(event.State), Loc: image.Pt(int(event.EventX), int(event.EventY)), } if (ev.Key - 1) == sparta.KeyShift { ev.Key = sparta.KeyShift } if (ev.Key - 1) == sparta.KeyControl { ev.Key = sparta.KeyControl } w.OnEvent(ev) case xgb.MappingNotifyEvent: setKeyboard() case xgb.MotionNotifyEvent: w, ok := widgetTable[event.Event] if !ok { break } ev := sparta.MouseEvent{ Button: getButton(event.Detail), State: sparta.StateKey(event.State), Loc: image.Pt(int(event.EventX), int(event.EventY)), } w.OnEvent(ev) } }
func main() { c, err := xgb.Dial(os.Getenv("DISPLAY")) if err != nil { fmt.Printf("cannot connect: %v\n", err) os.Exit(1) } defer c.Close() fmt.Printf("vendor = %q\n", string(c.Setup.Vendor)) win := c.NewId() gc := c.NewId() s := c.DefaultScreen() c.CreateWindow(0, win, s.Root, 150, 150, 200, 200, 0, 0, 0, 0, nil) c.ChangeWindowAttributes(win, xgb.CWBackPixel|xgb.CWEventMask, []uint32{ s.BlackPixel, xgb.EventMaskExposure | xgb.EventMaskKeyRelease, }) c.CreateGC(gc, win, xgb.GCForeground, []uint32{s.WhitePixel}) c.MapWindow(win) atom, _ := c.InternAtom(false, "HELLO") fmt.Printf("atom = %d\n", atom.Atom) // Set WmDelete event protName := "WM_PROTOCOLS" wmProt, _ := c.InternAtom(false, protName) wmProtocols := wmProt.Atom fmt.Printf("atom wmProtocols = %d\n", wmProtocols) atomName := "ATOM" atomTp, _ := c.InternAtom(false, atomName) atomType := atomTp.Atom fmt.Printf("atom atom = %d\n", atomType) wmDel := "WM_DELETE_WINDOW" atmDel, _ := c.InternAtom(false, wmDel) atomDel := atmDel.Atom fmt.Printf("atom wmDelete = %d\n", atomDel) wmDelete := make([]byte, 4) wmDelete[0] = byte(atomDel) wmDelete[1] = byte(atomDel >> 8) wmDelete[2] = byte(atomDel >> 16) wmDelete[3] = byte(atomDel >> 32) points := make([]xgb.Point, 2) points[0] = xgb.Point{5, 5} points[1] = xgb.Point{100, 120} c.ChangeProperty(xgb.PropModeReplace, win, xgb.AtomWmName, xgb.AtomString, 8, []byte("demo window")) c.ChangeProperty(xgb.PropModeReplace, win, wmProtocols, atomType, 32, wmDelete) fontpaths, _ := c.GetFontPath() for _, fontpath := range fontpaths.Path { fmt.Printf("fontpath = %q\n", fontpath.Name) } hosts, _ := c.ListHosts() for _, host := range hosts.Hosts { fmt.Printf("hosts = %q\n", host.Address) } ecookie := c.ListExtensionsRequest() exts, _ := c.ListExtensionsReply(ecookie) for _, name := range exts.Names { fmt.Printf("exts = %q\n", name.Name) } for { reply, err := c.WaitForEvent() if err != nil { fmt.Printf("error: %v\n", err) os.Exit(1) } fmt.Printf("event %T\n", reply) switch event := reply.(type) { case xgb.ClientMessageEvent: if event.Type != wmProtocols { continue } if xgb.Id(event.Data.Data32[0]) != atomDel { continue } return case xgb.ExposeEvent: c.PolyLine(xgb.CoordModeOrigin, win, gc, points) case xgb.KeyReleaseEvent: fmt.Printf("key release!\n") points[0].X = event.EventX points[0].Y = event.EventY c.PolyLine(xgb.CoordModeOrigin, win, gc, points) c.Bell(75) } } }