func (ct *CommandTray) keyPress() xevent.KeyPressFun { f := func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { // print("Cake:\n") if !ct.is_focused { // print("Boom\n") return } mods, kc := keybind.DeduceKeyInfo(ev.State, ev.Detail) // print("Key Press:", mods, kc, "\n") switch { case keybind.KeyMatch(X, "Escape", mods, kc): ct.Blur() case keybind.KeyMatch(X, "Return", mods, kc): ct.activate() case keybind.KeyMatch(X, "Up", mods, kc): ct.selected -= 1 if ct.selected < 0 { ct.selected = len(ct.cmds) } ct.Draw() case keybind.KeyMatch(X, "Down", mods, kc): if len(ct.cmds) > 0 { ct.selected += 1 ct.selected %= len(ct.cmds) ct.Draw() } case keybind.KeyMatch(X, "BackSpace", mods, kc): if len(ct.input) > 0 { ct.input = ct.input[:len(ct.input)-1] ct.getCommands() ct.Draw() } default: s := keybind.LookupString(X, mods, kc) if len(s) == 1 { ct.input = append(ct.input, rune(strings.ToLower(s)[0])) ct.selected = 0 ct.getCommands() ct.Draw() } } } return xevent.KeyPressFun(f) }
// connect is essentially 'Connect' for either KeyPress or KeyRelease events. // Namely, it parses the key string, issues a grab request if necessary, // sets up the appropriate event handlers for the main event loop, and attaches // the callback to the keybinding state. func connect(xu *xgbutil.XUtil, callback xgbutil.CallbackKey, evtype int, win xproto.Window, keyStr string, grab, reconnect bool) error { // Get the mods/key first mods, keycodes, err := ParseString(xu, keyStr) if err != nil { return err } // Only do the grab if we haven't yet on this window. for _, keycode := range keycodes { if grab && keyBindGrabs(xu, evtype, win, mods, keycode) == 0 { if err := GrabChecked(xu, win, mods, keycode); err != nil { // If a bad access, let's be nice and give a good error message. switch err.(type) { case xproto.AccessError: return fmt.Errorf("Got a bad access error when trying to "+ "bind '%s'. This usually means another client has "+ "already grabbed this keybinding.", keyStr) default: return fmt.Errorf("Could not bind '%s' because: %s", keyStr, err) } } } // If we've never grabbed anything on this window before, we need to // make sure we can respond to it in the main event loop. // Never do this if we're reconnecting. if !reconnect { var allCb xgbutil.Callback if evtype == xevent.KeyPress { allCb = xevent.KeyPressFun(runKeyPressCallbacks) } else { allCb = xevent.KeyReleaseFun(runKeyReleaseCallbacks) } // If this is the first Key{Press|Release}Event on this window, // then we need to listen to Key{Press|Release} events in the main // loop. if !connectedKeyBind(xu, evtype, win) { allCb.Connect(xu, win) } } // Finally, attach the callback. attachKeyBindCallback(xu, evtype, win, mods, keycode, callback) } // Keep track of all unique key connections. if !reconnect { addKeyString(xu, callback, evtype, win, keyStr, grab) } return nil }
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 (slct *Select) keyResponse() xevent.KeyPressFun { f := func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { if !slct.showing { return } beforeLen := len(slct.input.Text) mods, kc := keybind.DeduceKeyInfo(ev.State, ev.Detail) slct.input.Add(mods, kc) switch { case keybind.KeyMatch(X, slct.config.BackspaceKey, mods, kc): slct.input.Remove() case keybind.KeyMatch(X, slct.config.CancelKey, mods, kc): slct.Hide() return case keybind.KeyMatch(X, slct.config.ConfirmKey, mods, kc): if slct.selected >= 0 && slct.selected < len(slct.items) { slct.items[slct.selected].choose() slct.Hide() } else if len(slct.items) == 1 { slct.items[0].choose() slct.Hide() } return case keybind.KeyMatch(X, "Tab", mods, kc) || keybind.KeyMatch(X, "ISO_Left_Tab", mods, kc): if len(slct.items) == 0 { break } if mods&xproto.ModMaskShift > 0 { if slct.selected == -1 { slct.selected++ } slct.selected = misc.Mod(slct.selected-1, len(slct.items)) } else { slct.selected = misc.Mod(slct.selected+1, len(slct.items)) } slct.highlight() } // If the length of the input changed, then re-evaluate completion if beforeLen != len(slct.input.Text) { slct.FilterItems(string(slct.input.Text)) slct.selected = -1 slct.highlight() } } return xevent.KeyPressFun(f) }
func (msg *Message) keyResponse() xevent.KeyPressFun { f := func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { if !msg.showing { return } mods, kc := keybind.DeduceKeyInfo(ev.State, ev.Detail) switch { case keybind.KeyMatch(X, msg.config.ConfirmKey, mods, kc): fallthrough case keybind.KeyMatch(X, msg.config.CancelKey, mods, kc): msg.Hide() } } return xevent.KeyPressFun(f) }
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 (inp *Input) keyResponse() xevent.KeyPressFun { f := func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { if !inp.showing { return } mods, kc := keybind.DeduceKeyInfo(ev.State, ev.Detail) switch { case keybind.KeyMatch(X, "Up", mods, kc): if inp.historyIndex > 0 { inp.historyIndex-- inp.input.SetString(inp.history[inp.historyIndex]) } case keybind.KeyMatch(X, "Down", mods, kc): if inp.historyIndex < len(inp.history) { inp.historyIndex++ if inp.historyIndex < len(inp.history) { inp.input.SetString(inp.history[inp.historyIndex]) } else { inp.input.Reset() } } case keybind.KeyMatch(X, inp.config.BackspaceKey, mods, kc): inp.input.Remove() case keybind.KeyMatch(X, inp.config.ConfirmKey, mods, kc): if inp.do != nil { s := string(inp.input.Text) histLen := len(inp.history) // Don't added repeated entries. if histLen == 0 || s != inp.history[histLen-1] { inp.history = append(inp.history, s) } inp.do(inp, s) } case keybind.KeyMatch(X, inp.config.CancelKey, mods, kc): if inp.canceled != nil { inp.canceled(inp) } inp.Hide() default: inp.input.Add(mods, kc) } } return xevent.KeyPressFun(f) }
func (m *Manager) listenKeyEvents() { xevent.KeyPressFun( func(X *xgbutil.XUtil, e xevent.KeyPressEvent) { modStr := keybind.ModifierString(e.State) keyStr := keybind.LookupString(X, e.State, e.Detail) if e.Detail == 65 { keyStr = "space" } logger.Infof("KeyStr: %s, modStr: %s", keyStr, modStr) if !m.mediaKey.emitMediaSignal(modStr, keyStr, true) { modStr = deleteSpecialMod(modStr) value := "" if len(modStr) < 1 { value = keyStr } else { value = modStr + "-" + keyStr } info, ok := newKeycodeInfo(value) if !ok { return } if v, ok := getExecCommand(info); ok { // 不然按键会阻塞,直到程序推出 go doAction(v) } } }).Connect(X, X.RootWin()) xevent.KeyReleaseFun( func(X *xgbutil.XUtil, e xevent.KeyReleaseEvent) { modStr := keybind.ModifierString(e.State) keyStr := keybind.LookupString(X, e.State, e.Detail) if e.Detail == 65 { keyStr = "space" } //modStr = deleteSpecialMod(modStr) m.mediaKey.emitMediaSignal(modStr, keyStr, false) }).Connect(X, X.RootWin()) }
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() { 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() { // 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) }