// create creates the window, initializes the keybind and mousebind packages // and sets up the window to act like a real top-level client. func (w *window) create() { keybind.Initialize(w.X) mousebind.Initialize(w.X) err := w.CreateChecked(w.X.RootWin(), 0, 0, flagWidth, flagHeight, xproto.CwBackPixel, 0xffffff) if err != nil { errLg.Fatalf("Could not create window: %s", err) } // Make the window close gracefully using the WM_DELETE_WINDOW protocol. w.WMGracefulClose(func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) keybind.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(w.X) }) // Set WM_STATE so it is interpreted as top-level and is mapped. err = icccm.WmStateSet(w.X, w.Id, &icccm.WmState{ State: icccm.StateNormal, }) if err != nil { // not a fatal error lg("Could not set WM_STATE: %s", err) } // _NET_WM_STATE = _NET_WM_STATE_NORMAL ewmh.WmStateSet(w.X, w.Id, []string{"_NET_WM_STATE_NORMAL"}) // Set the name to something. w.nameSet("Decoding all images...") w.Map() }
func NewDisplay(width, height, border, heading int, name string) (*Display, error) { d := new(Display) d.w = float64(width) d.h = float64(height) d.bord = float64(border) d.head = float64(heading) X, err := xgbutil.NewConn() if err != nil { return nil, err } keybind.Initialize(X) d.ximg = xgraphics.New(X, image.Rect( 0, 0, border*2+width, border*2+heading+height)) err = d.ximg.CreatePixmap() if err != nil { return nil, err } painter := NewXimgPainter(d.ximg) d.gc = draw2d.NewGraphicContextWithPainter(d.ximg, painter) d.gc.Save() d.gc.SetStrokeColor(color.White) d.gc.SetFillColor(color.White) d.gc.Clear() d.wid = d.ximg.XShowExtra(name, true) d.x = X go func() { xevent.Main(X) }() return d, nil }
func run() error { Xu, err := xgbutil.NewConn() if err != nil { return err } defer Xu.Conn().Close() keybind.Initialize(Xu) if err := randr.Init(Xu.Conn()); err != nil { return err } audio, err := newAudio(Xu) if err != nil { return err } defer audio.Close() brightness, err := newBrightness(Xu) if err != nil { return err } defer brightness.Close() xevent.Main(Xu) return nil }
// NewImage returns a new image canvas // that draws to the given image. The // minimum point of the given image // should probably be 0,0. func NewImage(img draw.Image, name string) (*Canvas, error) { w := float64(img.Bounds().Max.X - img.Bounds().Min.X) h := float64(img.Bounds().Max.Y - img.Bounds().Min.Y) X, err := xgbutil.NewConn() if err != nil { return nil, err } keybind.Initialize(X) ximg := xgraphics.New(X, image.Rect(0, 0, int(w), int(h))) err = ximg.CreatePixmap() if err != nil { return nil, err } painter := NewPainter(ximg) gc := draw2d.NewGraphicContextWithPainter(ximg, painter) gc.SetDPI(dpi) gc.Scale(1, -1) gc.Translate(0, -h) wid := ximg.XShowExtra(name, true) go func() { xevent.Main(X) }() c := &Canvas{ Canvas: vgimg.NewWith(vgimg.UseImageWithContext(img, gc)), x: X, ximg: ximg, wid: wid, } vg.Initialize(c) return c, nil }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatalln(err) } // The message box uses the keybind module, so we must initialize it. keybind.Initialize(X) // Creating a new message prompt is as simple as supply an X connection, // a theme and a configuration. We use built in defaults here. msgPrompt := prompt.NewMessage(X, prompt.DefaultMessageTheme, prompt.DefaultMessageConfig) // Show maps the message prompt window. // If a duration is specified, the window does NOT acquire focus and // automatically disappears after the specified time. // If a duration is not specified (i.e., '0'), then the window is mapped, // and acquires focus. It does not disappear until it loses focus or when // the user hits the "confirm" or "cancel" keys (usually "enter" and // "escape"). timeout := 2 * time.Second // or "0" for no timeout. msgPrompt.Show(xwindow.RootGeometry(X), "Hello, world!", timeout, hidden) xevent.Main(X) }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } keybind.Initialize(X) // call once before using keybind package // Read an example gopher image into a regular png image. img, _, err := image.Decode(bytes.NewBuffer(gopher.GopherPng())) if err != nil { log.Fatal(err) } // Now convert it into an X image. ximg := xgraphics.NewConvert(X, img) // Now show it in a new window. // We set the window title and tell the program to quit gracefully when // the window is closed. // There is also a convenience method, XShow, that requires no parameters. win := showImage(ximg, "The Go Gopher!", true) // Listen for key press events. win.Listen(xproto.EventMaskKeyPress) err = keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { println("fullscreen!") err := ewmh.WmStateReq(X, win.Id, ewmh.StateToggle, "_NET_WM_STATE_FULLSCREEN") if err != nil { log.Fatal(err) } }).Connect(X, win.Id, "f", false) if err != nil { log.Fatal(err) } err = keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { println("quit fullscreen!") err := ewmh.WmStateReq(X, win.Id, ewmh.StateToggle, "_NET_WM_STATE_FULLSCREEN") if err != nil { log.Fatal(err) } }).Connect(X, win.Id, "Escape", false) if err != nil { log.Fatal(err) } // If we don't block, the program will end and the window will disappear. // We could use a 'select{}' here, but xevent.Main will emit errors if // something went wrong, so use that instead. xevent.Main(X) }
func grabKeyboardAndMouse(m *Manager) { if m == nil { return } //go func() { X, err := xgbutil.NewConn() if err != nil { logger.Info("Get New Connection Failed:", err) return } keybind.Initialize(X) mousebind.Initialize(X) err = keybind.GrabKeyboard(X, X.RootWin()) if err != nil { logger.Info("Grab Keyboard Failed:", err) return } grabAllMouseButton(X) xevent.ButtonPressFun( func(X *xgbutil.XUtil, e xevent.ButtonPressEvent) { dbus.Emit(m, "KeyReleaseEvent", "") ungrabAllMouseButton(X) keybind.UngrabKeyboard(X) logger.Info("Button Press Event") xevent.Quit(X) }).Connect(X, X.RootWin()) xevent.KeyPressFun( func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { value := parseKeyEnvent(X, e.State, e.Detail) pressKeyStr = value dbus.Emit(m, "KeyPressEvent", value) }).Connect(X, X.RootWin()) xevent.KeyReleaseFun( func(X *xgbutil.XUtil, e xevent.KeyReleaseEvent) { if strings.ToLower(pressKeyStr) == "super_l" || strings.ToLower(pressKeyStr) == "super_r" { pressKeyStr = "Super" } dbus.Emit(m, "KeyReleaseEvent", pressKeyStr) pressKeyStr = "" ungrabAllMouseButton(X) keybind.UngrabKeyboard(X) logger.Infof("Key: %s\n", pressKeyStr) xevent.Quit(X) }).Connect(X, X.RootWin()) xevent.Main(X) //}() }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatalf("Could not connect to X: %v", err) } keybind.Initialize(X) keybind.KeyPressFun( func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { fmt.Println("Key press!") }).Connect(X, X.RootWin(), "Mod4-j") xevent.Main(X) }
func initEGL(controlCh *controlCh, width, height int) *platform.EGLState { X, err := xgbutil.NewConn() if err != nil { panic(err) } mousebind.Initialize(X) keybind.Initialize(X) xWindow := newWindow(controlCh, X, width, height) go xevent.Main(X) return xorg.Initialize( egl.NativeWindowType(uintptr(xWindow.Id)), xorg.DefaultConfigAttributes, xorg.DefaultContextAttributes, ) }
func initXUtil() error { var err error if X, err = xgbutil.NewConn(); err != nil { fmt.Println("New XUtil Failed:", err) return err } if !initFlag { keybind.Initialize(X) initFlag = true } return nil }
func main() { X, err := xgbutil.NewConn() fatal(err) keybind.Initialize(X) slct := prompt.NewSelect(X, prompt.DefaultSelectTheme, prompt.DefaultSelectConfig) // Create some artifical groups to use. artGroups := []prompt.SelectGroup{ slct.NewStaticGroup("Group 1"), slct.NewStaticGroup("Group 2"), slct.NewStaticGroup("Group 3"), slct.NewStaticGroup("Group 4"), slct.NewStaticGroup("Group 5"), } // And now create some artificial items. items := []*item{ newItem("andrew", 1), newItem("bruce", 2), newItem("kaitlyn", 3), newItem("cauchy", 4), newItem("plato", 1), newItem("platonic", 2), newItem("andrew gallant", 3), newItem("Andrew Gallant", 4), newItem("Andrew", 1), newItem("jim", 1), newItem("jimmy", 2), newItem("jimbo", 3), } groups := make([]*prompt.SelectGroupItem, len(artGroups)) for i, artGroup := range artGroups { groups[i] = slct.AddGroup(artGroup) } for _, item := range items { item.promptItem = slct.AddChoice(item) } geom := headGeom(X) keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { showGroups := newGroups(groups, items) slct.Show(geom, prompt.TabCompletePrefix, showGroups) }).Connect(X, X.RootWin(), selectActivate, true) println("Loaded...") xevent.Main(X) }
func main() { runtime.GOMAXPROCS(64) X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } keybind.Initialize(X) font := loadFont("/usr/share/fonts/truetype/freefont/FreeMono.ttf") font.Color = xgraphics.BGRA{B: 0x00, G: 0xff, R: 0x00, A: 0xff} font.Size = 12.0 ximage := xgraphics.New(X, image.Rect(0, 0, 300, 300)) ximage.CreatePixmap() window, obscured := makeWindow(ximage) battery := batteryItem(font, 10, ximage, window) cpu := cpuItem(font, 30, ximage, window) memory := memoryItem(font, 50, ximage, window) before, after, quit := xevent.MainPing(X) loop: for { select { case <-before: <-after case <-quit: break loop case text := <-battery.Text: if *obscured { continue loop } battery.update(text) case text := <-cpu.Text: if *obscured { continue loop } cpu.update(text) case text := <-memory.Text: if *obscured { continue loop } memory.update(text) } } }
func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Anytime the keybind (mousebind) package is used, keybind.Initialize // *should* be called once. It isn't strictly necessary, but allows your // keybindings to persist even if the keyboard mapping is changed during // run-time. (Assuming you're using the xevent package's event loop.) // It also handles the case when your modifier map is changed. keybind.Initialize(X) // Create a new window. We will listen for key presses and translate them // only when this window is in focus. (Similar to how `xev` works.) win, err := xwindow.Generate(X) if err != nil { log.Fatalf("Could not generate a new window X id: %s", err) } win.Create(X.RootWin(), 0, 0, 500, 500, xproto.CwBackPixel, 0xffffffff) // Listen for Key{Press,Release} events. win.Listen(xproto.EventMaskKeyPress, xproto.EventMaskKeyRelease) // Map the window. win.Map() // Notice that we use xevent.KeyPressFun instead of keybind.KeyPressFun, // because we aren't trying to make a grab *and* because we want to listen // to *all* key press events, rather than just a particular key sequence // that has been pressed. xevent.KeyPressFun( func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { // keybind.LookupString does the magic of implementing parts of // the X Keyboard Encoding to determine an english representation // of the modifiers/keycode tuple. // N.B. It's working for me, but probably isn't 100% correct in // all environments yet. log.Println("Key:", keybind.LookupString(X, e.State, e.Detail)) }).Connect(X, win.Id) // Finally, start the main event loop. This will route any appropriate // KeyPressEvents to your callback function. log.Println("Program initialized. Start pressing keys!") xevent.Main(X) }
func main() { X, _ := xgbutil.NewConn() keybind.Initialize(X) // should output "{" fmt.Println(string(keybind.LookupString(X, 1, 34))) // should output "[" fmt.Println(string(keybind.LookupString(X, 0, 34))) fmt.Println("---------------------------------------") // should output "A" fmt.Println(string(keybind.LookupString(X, 1, 38))) // should output "a" fmt.Println(string(keybind.LookupString(X, 0, 38))) }
func BindKeys(keymap map[string]string) { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } keybind.Initialize(X) for k, v := range keymap { v := v err = keybind.KeyPressFun(func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { h.broadcast <- v }).Connect(X, X.RootWin(), k, true) if err != nil { log.Fatal(err) } } log.Println("Program initialized. Start pressing keys!") xevent.Main(X) }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } keybind.Initialize(X) currentuser, err := user.Current() if err != nil { log.Fatal(err) } configfile := currentuser.HomeDir + "/.config/hotkeys.conf.json" watcher, err := inotify.NewWatcher() if err != nil { log.Fatal(err) } err = watcher.AddWatch(configfile, inotify.IN_CLOSE_WRITE) if err != nil { log.Fatal(err) } go func() { for { select { case ev := <-watcher.Event: log.Println(ev) err := bindall(configfile, X) if err != nil { log.Println(err) continue } case err := <-watcher.Error: log.Println("error:", err) } } }() err = bindall(configfile, X) if err != nil { log.Panicln(err) } xevent.Main(X) }
func StartKeyBinding() error { var err error X, err = xgbutil.NewConn() if err != nil { return err } keybind.Initialize(X) initXRecord() initSystemIdDescList() //initMediaIdDescList() initWindowIdDescList() initWorkspaceIdDescList() grabKeyPairs(getSystemKeyPairs(), true) grabKeyPairs(getCustomKeyPairs(), true) grabMediaKeys(true) return nil }
// newWindow creates the window, initializes the keybind and mousebind packages // and sets up the window to act like a real top-level client. func newWindow(X *xgbutil.XUtil) *Window { w, err := xwindow.Generate(X) if err != nil { errLg.Fatalf("Could not create window: %s", err) } keybind.Initialize(w.X) mousebind.Initialize(w.X) err = w.CreateChecked(w.X.RootWin(), 0, 0, 600, 600, xproto.CwBackPixel, 0xffffff) if err != nil { errLg.Fatalf("Could not create window: %s", err) } // Make the window close gracefully using the WM_DELETE_WINDOW protocol. w.WMGracefulClose(func(w *xwindow.Window) { xevent.Detach(w.X, w.Id) keybind.Detach(w.X, w.Id) mousebind.Detach(w.X, w.Id) w.Destroy() xevent.Quit(w.X) }) // Set WM_STATE so it is interpreted as top-level and is mapped. err = icccm.WmStateSet(w.X, w.Id, &icccm.WmState{State: icccm.StateNormal}) if err != nil { lg("Could not set WM_STATE: %s", err) } // _NET_WM_STATE = _NET_WM_STATE_NORMAL // not needed because we we set FS later anyway? //ewmh.WmStateSet(w.X, w.Id, []string{"_NET_WM_STATE_NORMAL"}) w.Map() err = ewmh.WmStateReq(w.X, w.Id, ewmh.StateToggle, "_NET_WM_STATE_FULLSCREEN") if err != nil { lg("Failed to go FullScreen:", err) } return &Window{w} }
func main() { X, err := xgbutil.NewConn() fatal(err) keybind.Initialize(X) cycle := prompt.NewCycle(X, prompt.DefaultCycleTheme, prompt.DefaultCycleConfig) clients, err := ewmh.ClientListStackingGet(X) fatal(err) items := make([]*prompt.CycleItem, 0) for i := len(clients) - 1; i >= 0; i-- { item := cycle.AddChoice(newWindow(X, cycle.Id(), clients[i])) items = append(items, item) } keyHandlers(X, cycle, items) println("Loaded...") xevent.Main(X) }
// NewImage returns a new image canvas // that draws to the given image. The // minimum point of the given image // should probably be 0,0. func NewImage(img draw.Image, name string) (*XImgCanvas, error) { w := float64(img.Bounds().Max.X - img.Bounds().Min.X) h := float64(img.Bounds().Max.Y - img.Bounds().Min.Y) X, err := xgbutil.NewConn() if err != nil { return nil, err } keybind.Initialize(X) ximg := xgraphics.New(X, image.Rect(0, 0, int(w), int(h))) err = ximg.CreatePixmap() if err != nil { return nil, err } painter := NewXimgPainter(ximg) gc := draw2d.NewGraphicContextWithPainter(ximg, painter) gc.SetDPI(dpi) gc.Scale(1, -1) gc.Translate(0, -h) wid := ximg.XShowExtra(name, true) go func() { xevent.Main(X) }() c := &XImgCanvas{ gc: gc, w: vg.Inches(w / dpi), h: vg.Inches(h / dpi), color: []color.Color{color.Black}, x: X, ximg: ximg, wid: wid, } vg.Initialize(c) return c, nil }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatalln(err) } // The input box uses the keybind module, so we must initialize it. keybind.Initialize(X) // Creating a new input prompt is as simple as supply an X connection, // a theme and a configuration. We use built in defaults here. inpPrompt := prompt.NewInput(X, prompt.DefaultInputTheme, prompt.DefaultInputConfig) // Show maps the input prompt window and sets the focus. It returns // immediately, and the main X event loop is started. // Also, we use the root window geometry to make sure the prompt is // centered in the middle of the screen. 'response' and 'canceled' are // callback functions. See their respective commends for more details. inpPrompt.Show(xwindow.RootGeometry(X), "What is your name?", response, canceled) xevent.Main(X) }
func main() { // Signal Handling. sigChan := make(chan os.Signal) signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT) paths := basedir.Paths{ XDGSuffix: "gobar", GoImportPath: "github.com/AmandaCameron/gobar/data", } file, err := paths.ConfigFile("config.wini") utils.FailMeMaybe(err) cfg := loadConfig(file) //os.Getenv("HOME") + "/.config/gobar/config.wini") // Load Images. images.Init(paths) // Setup the X Connection X, err := xgbutil.NewConn() utils.FailMeMaybe(err) win, err := xwindow.Create(X, X.RootWin()) utils.FailMeMaybe(err) win.Resize(cfg.BarWidth, cfg.BarSize) // Setup the EWMH Stuff utils.FailMeMaybe(ewmh.RestackWindow(X, win.Id)) var strut *ewmh.WmStrutPartial if cfg.Position == "Top" { strut = &ewmh.WmStrutPartial{ Top: uint(cfg.BarSize), TopStartX: 0, TopEndX: uint(cfg.BarWidth), } win.Move(0, 0) } else if cfg.Position == "Bottom" { strut = &ewmh.WmStrutPartial{ Bottom: uint(cfg.BarSize), BottomStartX: 0, BottomEndX: uint(cfg.BarWidth), } win.Move(0, 600-cfg.BarSize) } else { println("Invalid Position:", cfg.Position) os.Exit(1) } utils.FailMeMaybe(ewmh.WmStrutPartialSet(X, win.Id, strut)) utils.FailMeMaybe(ewmh.WmWindowTypeSet(X, win.Id, []string{ "_NET_WM_WINDOW_TYPE_DOCK", })) // Put us everywhere. utils.FailMeMaybe(ewmh.WmDesktopSet(X, win.Id, 0xFFFFFFFF)) win.Map() keybind.Initialize(X) // Get the DE settings, if we can. xs, err := xsettings.New(X) if err != nil { // Maybe this should be an error, maybe not? xs = nil } // Draw the background bg := xgraphics.BGRA{ R: 64, G: 64, B: 64, A: 255, } img := xgraphics.New(X, image.Rect(0, 0, cfg.BarWidth, cfg.BarSize)) img.For(func(x, y int) xgraphics.BGRA { return bg }) utils.FailMeMaybe(img.XSurfaceSet(win.Id)) img.XDraw() img.XPaint(win.Id) // Connect to DBus sys, err := dbus.Connect(dbus.SystemBus) utils.FailMeMaybe(err) // The session bus, too. sess, err := dbus.Connect(dbus.SessionBus) utils.FailMeMaybe(err) // Blah x := xdg.New() // TODO: How should this fail? I imagine defaulting to gnome is the wrong thing to do, // but I'm not really sure what it should do. if xs != nil { theme, err := xs.GetString("Net/IconThemeName") if err == nil { x.SetTheme(theme) } } var dev *nm.Device var batt *upower.Device up := upower.New(sys) cli := nm.New(sys) if devs, err := cli.GetDevices(); err == nil { for _, d := range devs { if d.Type() == nm.Wireless { dev = d break } } } if pdevs, err := up.GetDevices(); err == nil { for _, d := range pdevs { if d.Type() == upower.Battery { batt = d break } } } // Clock clck := &Clock{ X: X, Position: cfg.Clock.Position, Width: cfg.Clock.Width, Height: cfg.BarSize, Parent: win, Format: cfg.ClockFormat, Background: xgraphics.BGRA{R: 48, G: 48, B: 48, A: 255}, Foreground: xgraphics.BGRA{R: 255, G: 255, B: 255, A: 255}, Font: utils.OpenFont(cfg.Clock.Font.Name), FontSize: cfg.Clock.Font.Size, } clck.Init() // App Launch Tracker tracker := &Tracker{ X: X, Position: cfg.Tracker.Position, Size: cfg.BarSize, Background: bg, Parent: win, } tracker.Init() // Command Tray ct := &commandtray.CommandTray{ X: X, Width: cfg.Command.Width, Height: cfg.BarSize, Position: cfg.Command.Position, Parent: win, Font: utils.OpenFont(cfg.Command.Font.Name), FontSize: cfg.Command.Font.Size, } commandtray.Register(commandtray.AppSource{ Xdg: x, X: X, AppTracker: tracker, }) if sess != nil { commandtray.Register(commandtray.GnomeSessionSource{ Obj: sess.Object("org.gnome.SessionManager", "/org/gnome/SessionManager"), Xdg: x, }) commandtray.Register(commandtray.NewShellSource(sess, x)) commandtray.Register(&commandtray.AppMenuSource{ Conn: sess, }) } // Done, maybe? ct.Init() ct.Bind(cfg.CommandAccel) ct.Draw() // Status Bar sb := &statbar.StatusBar{ X: X, Width: cfg.StatusBar.Width, Position: cfg.StatusBar.Position, Height: cfg.BarSize, Parent: win, } sb.Init() if batt != nil { sb.Add(&statbar.SbPower{batt}) } if dev != nil { sb.Add(&statbar.SbNmWifi{dev}) commandtray.Register(commandtray.NmSource{dev}) } sb.Draw() // My My this anikin guy... go func() { for { select { case <-sigChan: sb.Teardown() time.Sleep(1 * time.Second) // Anybody else? xevent.Quit(X) } } }() xevent.Main(X) }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Println(err) return } //Initialize the keybind package keybind.Initialize(X) //Create a window win, err := xwindow.Generate(X) if err != nil { log.Fatalf("Could not generate a new window X id: %s", err) } win.Create(X.RootWin(), 0, 0, 1024, 768, xproto.CwBackPixel, 0x606060ff) // Listen for Key{Press,Release} events. win.Listen(xproto.EventMaskKeyPress, xproto.EventMaskKeyRelease) // Map the window. This is what makes it on the screen win.Map() //Make a ...callback... for the events and connect xevent.KeyPressFun( func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { modStr := keybind.ModifierString(e.State) keyStr := keybind.LookupString(X, e.State, e.Detail) if len(modStr) > 0 { log.Printf("Key: %s-%s\n", modStr, keyStr) } else { log.Println("Key:", keyStr) } if keybind.KeyMatch(X, "Escape", e.State, e.Detail) { if e.State&xproto.ModMaskControl > 0 { log.Println("Control-Escape detected. Quitting...") xevent.Quit(X) } } }).Connect(X, win.Id) //So here i'm going to try to make a image..' img := xgraphics.New(X, image.Rect(0, 0, 1024, 768)) err = img.XSurfaceSet(win.Id) if err != nil { log.Printf("Error while setting window surface to image %d: %s\n", win, err) } else { log.Printf("Window %d surface set to image OK\n", win) } // I /think/ XDraw actually sends data to server? img.XDraw() // I /think/ XPaint tells the server to paint image to window img.XPaint(win.Id) //Start the routine that updates the window go updater(img, win) //This seems to start a main loop for listening to xevents xevent.Main(X) }
func main() { if flagWriteConfig { writeConfigFiles() os.Exit(0) } X, err := xgbutil.NewConn() if err != nil { logger.Error.Println(err) logger.Error.Fatalln("Error connecting to X, quitting...") } defer X.Conn().Close() // Do this first! Attempt to retrieve window manager ownership. // This includes waiting for any existing window manager to die. // 'own' also sets up handlers for quitting when a window manager tries // to replace *us*. if err := own(X, flagReplace); err != nil { logger.Error.Fatalf( "Could not establish window manager ownership: %s", err) } if len(flagConfigDir) > 0 { misc.ConfigPaths.Override = flagConfigDir } if len(flagDataDir) > 0 { misc.DataPaths.Override = flagDataDir } misc.ReadData() keybind.Initialize(X) mousebind.Initialize(X) focus.Initialize(X) stack.Initialize(X) cursors.Initialize(X) wm.Initialize(X, commands.Env, newHacks()) hook.Initialize(commands.Env, misc.ConfigFile("hooks.wini")) // Listen to Root. It is all-important. err = xwindow.New(X, X.RootWin()).Listen( xproto.EventMaskPropertyChange | xproto.EventMaskFocusChange | xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease | xproto.EventMaskStructureNotify | xproto.EventMaskSubstructureNotify | xproto.EventMaskSubstructureRedirect) if err != nil { logger.Error.Fatalf("Could not listen to Root window events: %s", err) } // Update state when the root window changes size wm.RootGeomChangeFun().Connect(X, wm.Root.Id) // Oblige map request events xevent.MapRequestFun( func(X *xgbutil.XUtil, ev xevent.MapRequestEvent) { xclient.New(ev.Window) }).Connect(X, wm.Root.Id) // Oblige configure requests from windows we don't manage. xevent.ConfigureRequestFun( func(X *xgbutil.XUtil, ev xevent.ConfigureRequestEvent) { // Make sure we aren't managing this client. if wm.FindManagedClient(ev.Window) != nil { return } xwindow.New(X, ev.Window).Configure(int(ev.ValueMask), int(ev.X), int(ev.Y), int(ev.Width), int(ev.Height), ev.Sibling, ev.StackMode) }).Connect(X, wm.Root.Id) xevent.FocusInFun( func(X *xgbutil.XUtil, ev xevent.FocusInEvent) { if ignoreRootFocus(ev.Mode, ev.Detail) { return } if len(wm.Workspace().Clients) == 0 { return } wm.FocusFallback() }).Connect(X, wm.Root.Id) // Listen to Root client message events. This is how we handle all // of the EWMH bullshit. xevent.ClientMessageFun(handleClientMessages).Connect(X, wm.Root.Id) // Tell everyone what we support. setSupported() // Start up the IPC command listener. go ipc() // Just before starting the main event loop, check to see if there are // any clients that already exist that we should manage. manageExistingClients() // Now make sure that clients are in the appropriate visible state. for _, wrk := range wm.Heads.Workspaces.Wrks { if wrk.IsVisible() { wrk.Show() } else { wrk.Hide() } } wm.Heads.ApplyStruts(wm.Clients) wm.FocusFallback() wm.Startup = false pingBefore, pingAfter, pingQuit := xevent.MainPing(X) if len(flagCpuProfile) > 0 { f, err := os.Create(flagCpuProfile) if err != nil { logger.Error.Fatalf("%s\n", err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } if flagWingoRestarted { hook.Fire(hook.Restarted, hook.Args{}) } else { hook.Fire(hook.Startup, hook.Args{}) } EVENTLOOP: for { select { case <-pingBefore: // Wait for the event to finish processing. <-pingAfter case f := <-commands.SafeExec: commands.SafeReturn <- f() case <-pingQuit: break EVENTLOOP } } if wm.Restart { // We need to tell the next invocation of Wingo that it is being // *restarted*. (So that we don't refire the startup hook.) // Thus, search os.Args for "--wingo-restarted". If it doesn't exist, // add it. found := false for _, arg := range os.Args { if strings.ToLower(strings.TrimSpace(arg)) == "--wingo-restarted" { found = true } } if !found { os.Args = append(os.Args, "--wingo-restarted") } logger.Message.Println("The user has told us to restart...\n\n\n") if err := syscall.Exec(os.Args[0], os.Args, os.Environ()); err != nil { logger.Error.Fatalf("Could not exec '%s': %s", strings.Join(os.Args, " "), err) } } }
func main() { if flagWriteConfig { writeConfigFiles() os.Exit(0) } X, err := xgbutil.NewConn() if err != nil { logger.Error.Println(err) logger.Error.Fatalln("Error connecting to X, quitting...") } defer X.Conn().Close() if flagShowSocket { showSocketPath(X) return } // Do this first! Attempt to retrieve window manager ownership. // This includes waiting for any existing window manager to die. // 'own' also sets up handlers for quitting when a window manager tries // to replace *us*. if err := own(X, flagReplace); err != nil { logger.Error.Fatalf( "Could not establish window manager ownership: %s", err) } if len(flagConfigDir) > 0 { misc.ConfigPaths.Override = flagConfigDir } if len(flagDataDir) > 0 { misc.DataPaths.Override = flagDataDir } misc.ReadData() keybind.Initialize(X) mousebind.Initialize(X) focus.Initialize(X) stack.Initialize(X) cursors.Initialize(X) wm.Initialize(X, commands.Env, newHacks()) hook.Initialize(commands.Env, misc.ConfigFile("hooks.wini")) // Initialize event handlers on the root window. rootInit(X) // Tell everyone what we support. setSupported() // Start up the IPC command listener. go ipc(X) // And start up the IPC event notifier. go event.Notifier(X, socketFilePath(X)) // Just before starting the main event loop, check to see if there are // any clients that already exist that we should manage. manageExistingClients() // Now make sure that clients are in the appropriate visible state. for _, wrk := range wm.Heads.Workspaces.Wrks { if wrk.IsVisible() { wrk.Show() } else { wrk.Hide() } } wm.Heads.ApplyStruts(wm.Clients) wm.FocusFallback() wm.Startup = false pingBefore, pingAfter, pingQuit := xevent.MainPing(X) if len(flagCpuProfile) > 0 { f, err := os.Create(flagCpuProfile) if err != nil { logger.Error.Fatalf("%s\n", err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } if flagWingoRestarted { hook.Fire(hook.Restarted, hook.Args{}) } else { hook.Fire(hook.Startup, hook.Args{}) } EVENTLOOP: for { select { case <-pingBefore: // Wait for the event to finish processing. <-pingAfter case f := <-commands.SafeExec: commands.SafeReturn <- f() case <-pingQuit: break EVENTLOOP } } if wm.Restart { event.Notify(event.Restarting{}) for _, client := range wm.Clients { c := client.(*xclient.Client) if _, ok := c.Frame().(*frame.Full); ok { c.FrameNada() } } time.Sleep(1 * time.Second) // We need to tell the next invocation of Wingo that it is being // *restarted*. (So that we don't refire the startup hook.) // Thus, search os.Args for "--wingo-restarted". If it doesn't exist, // add it. found := false for _, arg := range os.Args { if strings.ToLower(strings.TrimSpace(arg)) == "--wingo-restarted" { found = true } } if !found { os.Args = append(os.Args, "--wingo-restarted") } logger.Message.Println("The user has told us to restart...\n\n\n") if err := syscall.Exec(os.Args[0], os.Args, os.Environ()); err != nil { logger.Error.Fatalf("Could not exec '%s': %s", strings.Join(os.Args, " "), err) } } }
func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Nice names for the modifier keys (same ones used by xmodmap). // This slice corresponds to the keybind.Modifiers slice (except for // the last 'Any' modifier element). nice := []string{ "shift", "lock", "control", "mod1", "mod2", "mod3", "mod4", "mod5", } // Whenever one uses the keybind package, Initialize should always be // called first. In this case, it initializes the key and modifier maps. keybind.Initialize(X) // Get the current modifier map. // The map is actually a table, where rows correspond to modifiers, and // columns correspond to the keys that activate that modifier. modMap := keybind.ModMapGet(X) // The number of keycodes allowed per modifier (i.e., the number of // columns in the modifier map). kPerMod := int(modMap.KeycodesPerModifier) // Get the number of allowable keysyms per keycode. // This is used to search for a valid keysym for a particular keycode. symsPerKc := int(keybind.KeyMapGet(X).KeysymsPerKeycode) // Imitate everything... fmt.Printf("xmodmap: up to %d keys per modifier, "+ "(keycodes in parentheses):\n\n", kPerMod) // Iterate through all keyboard modifiers defined in xgb/xproto // except the 'Any' modifier (which is last). for mmi := range keybind.Modifiers[:len(keybind.Modifiers)-1] { niceName := nice[mmi] keys := make([]string, 0, kPerMod) // row is the row for the 'mmi' modifier in the modifier mapping table. row := mmi * kPerMod // Iterate over each keycode in the modifier map for this modifier. for _, kc := range modMap.Keycodes[row : row+kPerMod] { // If this entry doesn't have a keycode (i.e., it's zero), we // have to skip it. if kc == 0 { continue } // Look for the first valid keysym in the keyboard map corresponding // to this keycode. If one can't be found, output "BadKey." var ksym xproto.Keysym = 0 for column := 0; column < symsPerKc; column++ { ksym = keybind.KeysymGet(X, kc, byte(column)) if ksym != 0 { break } } if ksym == 0 { keys = append(keys, fmt.Sprintf("BadKey (0x%x)", kc)) } else { keys = append(keys, fmt.Sprintf("%s (0x%x)", keybind.KeysymToStr(ksym), kc)) } } fmt.Printf("%-12s%s\n", niceName, strings.Join(keys, ", ")) } fmt.Println("") }
func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Anytime the keybind (mousebind) package is used, keybind.Initialize // *should* be called once. It isn't strictly necessary, but allows your // keybindings to persist even if the keyboard mapping is changed during // run-time. (Assuming you're using the xevent package's event loop.) // It also handles the case when your modifier map is changed. keybind.Initialize(X) // Create a new window. We will listen for key presses and translate them // only when this window is in focus. (Similar to how `xev` works.) win, err := xwindow.Generate(X) if err != nil { log.Fatalf("Could not generate a new window X id: %s", err) } win.Create(X.RootWin(), 0, 0, 500, 500, xproto.CwBackPixel, 0xffffffff) // Listen for Key{Press,Release} events. win.Listen(xproto.EventMaskKeyPress, xproto.EventMaskKeyRelease) // Map the window. win.Map() // Notice that we use xevent.KeyPressFun instead of keybind.KeyPressFun, // because we aren't trying to make a grab *and* because we want to listen // to *all* key press events, rather than just a particular key sequence // that has been pressed. wid := win.Id if flagRoot { wid = X.RootWin() } xevent.KeyPressFun( func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { // keybind.LookupString does the magic of implementing parts of // the X Keyboard Encoding to determine an english representation // of the modifiers/keycode tuple. // N.B. It's working for me, but probably isn't 100% correct in // all environments yet. modStr := keybind.ModifierString(e.State) keyStr := keybind.LookupString(X, e.State, e.Detail) if len(modStr) > 0 { log.Printf("Key: %s-%s\n", modStr, keyStr) } else { log.Println("Key:", keyStr) } if keybind.KeyMatch(X, "Escape", e.State, e.Detail) { if e.State&xproto.ModMaskControl > 0 { log.Println("Control-Escape detected. Quitting...") xevent.Quit(X) } } }).Connect(X, wid) // If we want root, then we take over the entire keyboard. if flagRoot { if err := keybind.GrabKeyboard(X, X.RootWin()); err != nil { log.Fatalf("Could not grab keyboard: %s", err) } log.Println("WARNING: We are taking *complete* control of the root " + "window. The only way out is to press 'Control + Escape' or to " + "close the window with the mouse.") } // Finally, start the main event loop. This will route any appropriate // KeyPressEvents to your callback function. log.Println("Program initialized. Start pressing keys!") xevent.Main(X) }
func main() { X, err := xgbutil.NewConn() fatal(err) // Remember to always initialize the keybind package before usage. keybind.Initialize(X) // We create a benign parent window. Its only value in this example is // instructional. In particular, it shows how to have a sub-window get // focus using the ICCCM WM_TAKE_FOCUS protocol. (Since by default, // the window manager will assign focus to your top-level window.) // The real magic happens below with the WMTakeFocus method call. parentWin, err := xwindow.Create(X, X.RootWin()) fatal(err) // NewInput creates a new input window and handles all of the text drawing // for you. It can be any width, but the height will be automatically // determined by the height extents of the font size chosen. input := text.NewInput(X, parentWin.Id, width, padding, font, fontSize, fontColor, bgColor) parentWin.Resize(input.Geom.Width(), input.Geom.Height()) // Make sure X reports KeyPress events when this window is focused. input.Listen(xproto.EventMaskKeyPress) // Listen to KeyPress events. If it's a BackSpace, remove the last // character in the input box. If it's "Return" quit. If it's "Escape", // clear the input box. // Otherwise, try to add the key pressed to the input box. // (Not all key presses correspond to a single character that is added.) xevent.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { mods, kc := ev.State, ev.Detail switch { case keybind.KeyMatch(X, "BackSpace", mods, kc): input.Remove() case keybind.KeyMatch(X, "Return", mods, kc): log.Println("Return has been pressed.") log.Printf("The current text is: %s", string(input.Text)) log.Println("Quitting...") xevent.Quit(X) case keybind.KeyMatch(X, "Escape", mods, kc): input.Reset() default: input.Add(mods, kc) } }).Connect(X, input.Id) // Implement the WM_DELETE_WINDOW protocol. parentWin.WMGracefulClose(func(w *xwindow.Window) { xevent.Quit(X) }) // Implement the WM_TAKE_FOCUS protocol. The callback function provided // is executed when a valid WM_TAKE_FOCUS ClientMessage event has been // received from the window manager. // According to ICCCM Section 4.2.7, this is one of the three valid ways // of setting input focus to a sub-window. (It's also easiest since it // doesn't require us to monitor FocusChange events. EW.) // If you have multiple sub-windows that can be focused, this callback // function is where the logic would go to pick which sub-window should // be focused upon receipt of a WM_TAKE_FOCUS message. parentWin.WMTakeFocus(func(w *xwindow.Window, tstamp xproto.Timestamp) { input.FocusParent(tstamp) }) // Map the window and start the main X event loop. input.Map() parentWin.Map() xevent.Main(X) }
func main() { var err error X, err = xgbutil.NewConn() if err != nil { logger.Error.Println(err) logger.Error.Println("Error connecting to X, quitting...") return } defer X.Conn().Close() keybind.Initialize(X) mousebind.Initialize(X) focus.Initialize(X) stack.Initialize(X) wingo = newWingoState() // Create a root window abstraction and load its geometry wingo.root = xwindow.New(X, X.RootWin()) _, err = wingo.root.Geometry() if err != nil { logger.Error.Println("Could not get ROOT window geometry because: %v", err) logger.Error.Println("Cannot continue. Quitting...") return } // Load configuration wingo.conf, err = loadConfig() if err != nil { logger.Error.Println(err) logger.Error.Println("No configuration found. Quitting...") return } // Load theme wingo.theme, err = loadTheme(X) if err != nil { logger.Error.Println(err) logger.Error.Println("No theme configuration found. Quitting...") return } // Initialize prompts wingo.prompts = newPrompts() wingo.initializeHeads() // Attach all global key bindings attachAllKeys() // Attach all root mouse bindings rootMouseConfig() // Setup some cursors we use cursors.Setup(X) // Listen to Root. It is all-important. wingo.root.Listen(xproto.EventMaskPropertyChange | xproto.EventMaskStructureNotify | xproto.EventMaskSubstructureNotify | xproto.EventMaskSubstructureRedirect) // Update state when the root window changes size // xevent.ConfigureNotifyFun(rootGeometryChange).Connect(X, wingo.root.Id) // Oblige map request events xevent.MapRequestFun( func(X *xgbutil.XUtil, ev xevent.MapRequestEvent) { newClient(X, ev.Window) }).Connect(X, wingo.root.Id) // Oblige configure requests from windows we don't manage. xevent.ConfigureRequestFun( func(X *xgbutil.XUtil, ev xevent.ConfigureRequestEvent) { flags := int(ev.ValueMask) & ^int(xproto.ConfigWindowSibling) & ^int(xproto.ConfigWindowStackMode) xwindow.New(X, ev.Window).Configure(flags, int(ev.X), int(ev.Y), int(ev.Width), int(ev.Height), ev.Sibling, ev.StackMode) }).Connect(X, wingo.root.Id) // Listen to Root client message events. // We satisfy EWMH with these AND it also provides a mechanism // to issue commands using wingo-cmd. xevent.ClientMessageFun(commandHandler).Connect(X, wingo.root.Id) xevent.Main(X) }
func main() { X, err := xgbutil.NewConn() fatal(err) // Whenever the mousebind package is used, you must call Initialize. // Similarly for the keybind package. keybind.Initialize(X) mousebind.Initialize(X) // Easter egg! Use a right click to draw a gopher. gopherPng, _, err := image.Decode(bytes.NewBuffer(gopher.GopherPng())) fatal(err) // Now scale it to a reasonable size. gopher := xgraphics.Scale(gopherPng, gopherWidth, gopherHeight) // Create a new xgraphics.Image. It automatically creates an X pixmap for // you, and handles drawing to windows in the XDraw, XPaint and // XSurfaceSet functions. // N.B. An error is possible since X pixmap allocation can fail. canvas := xgraphics.New(X, image.Rect(0, 0, width, height)) // Color in the background color. canvas.For(func(x, y int) xgraphics.BGRA { return bg }) // Use the convenience function XShowExtra to create and map the // canvas window. // XShowExtra will also set the surface window of canvas for us. // We also use XShowExtra to set the name of the window and to quit the // main event loop when the window is closed. win := canvas.XShowExtra("Pointer painting", true) // Listen for pointer motion events and key press events. win.Listen(xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease | xproto.EventMaskKeyPress) // The mousebind drag function runs three callbacks: one when the drag is // first started, another at each "step" in the drag, and a final one when // the drag is done. // The button sequence (in this case '1') is pressed, the first callback // is executed. If the first return value is true, the drag continues // and a pointer grab is initiated with the cursor id specified in the // second return value (use 0 to keep the cursor unchanged). // If it's false, the drag stops. // Note that Drag will automatically compress MotionNotify events. mousebind.Drag(X, win.Id, win.Id, "1", false, func(X *xgbutil.XUtil, rx, ry, ex, ey int) (bool, xproto.Cursor) { drawPencil(canvas, win, ex, ey) return true, 0 }, func(X *xgbutil.XUtil, rx, ry, ex, ey int) { drawPencil(canvas, win, ex, ey) }, func(X *xgbutil.XUtil, rx, ry, ex, ey int) {}) mousebind.Drag(X, win.Id, win.Id, "3", false, func(X *xgbutil.XUtil, rx, ry, ex, ey int) (bool, xproto.Cursor) { drawGopher(canvas, gopher, win, ex, ey) return true, 0 }, func(X *xgbutil.XUtil, rx, ry, ex, ey int) { drawGopher(canvas, gopher, win, ex, ey) }, func(X *xgbutil.XUtil, rx, ry, ex, ey int) {}) // Bind to the clear key specified, and just redraw the bg color. keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { clearCanvas(canvas, win) }).Connect(X, win.Id, clearKey, false) // Bind a callback to each key specified in the 'pencils' color map. // The response is to simply switch the pencil color. for key, clr := range pencils { c := clr keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { log.Printf("Changing pencil color to: %#v", c) pencil = c }).Connect(X, win.Id, key, false) } // Output some basic directions. fmt.Println("Use the left or right buttons on your mouse to paint " + "squares and gophers.") fmt.Println("Pressing numbers 1, 2, 3, 4, 5 or 6 will switch your pencil " + "color.") fmt.Println("Pressing 'c' will clear the canvas.") xevent.Main(X) }