func grabSignalShortcut(shortcut, action string, isGrab bool) { if len(shortcut) < 1 { logger.Error("grabSignalKey args error") return } shortcut = convertKeysym2Weird(shortcut) mod, keys, err := keybind.ParseString(X, shortcut) if err != nil { logger.Errorf("ParseString error: %v", err) return } if mod > 0 || len(keys) < 1 { return } if isGrab { if len(action) < 1 { return } tmp := C.CString(action) defer C.free(unsafe.Pointer(tmp)) C.grab_xrecord_key(C.int(keys[0]), tmp) } else { C.ungrab_xrecord_key(C.int(keys[0])) } }
func xgbUngrab(shortcut string) bool { if len(shortcut) < 1 { return false } mod, codes, err := keybind.ParseString(X, shortcut) if err != nil { fmt.Printf("Parse shortcut '%s' failed: %v\n", shortcut, err) return false } for _, code := range codes { keybind.Ungrab(X, X.RootWin(), mod, code) } return true }
func ungrabSignalShortcut(shortcut string) { if len(shortcut) < 1 { return } shortcut = convertKeysym2Weird(shortcut) mod, keys, err := keybind.ParseString(X, shortcut) if err != nil { logger.Errorf("ParseString error: %v", err) return } if mod > 0 || len(keys) < 1 { return } C.ungrab_xrecord_key(C.int(keys[0])) }
func ungrabKey(wid xproto.Window, shortcut string) bool { if len(shortcut) < 1 { logger.Warning("Ungrab args failed...") return false } shortcut = convertKeysym2Weird(shortcut) mod, keys, err := keybind.ParseString(X, shortcut) if err != nil { logger.Warning("In UngrabKey Parse shortcut failed:", err) return false } for _, k := range keys { keybind.Ungrab(X, wid, mod, k) } return true }
func keyNameToKeyCode(key string) (keycode int, err error) { if len(key) < 1 { return 0, errors.New("Invalid key") } if X == nil { if err = initXUtil(); err != nil { return 0, err } } _, codes, e := keybind.ParseString(X, key) if e != nil { return 0, e } fmt.Printf("Key: %s, keycode: %v\n", key, codes) return int(codes[0]), nil }
func newKeycodeInfo(shortcut string) (KeycodeInfo, bool) { if len(shortcut) < 1 { return KeycodeInfo{}, false } shortcut = convertKeysym2Weird(shortcut) mod, keys, err := keybind.ParseString(X, shortcut) if err != nil { logger.Warningf("newKeycodeInfo parse '%s' failed: %v", shortcut, err) return KeycodeInfo{}, false } if len(keys) < 1 { logger.Warningf("'%s' no details", shortcut) return KeycodeInfo{}, false } state, detail := keybind.DeduceKeyInfo(mod, keys[0]) return KeycodeInfo{State: state, Detail: detail}, true }
func (kcmd keyCommand) attach(run func()) { if run == nil { return } if kcmd.cmd == "PromptCyclePrev" || kcmd.cmd == "PromptCycleNext" { // We've got to parse the key string first and make sure // there are some modifiers; otherwise this utterly fails! mods, _, _ := keybind.ParseString(X, kcmd.keyStr) if mods == 0 { logger.Warning.Printf("Sorry but the key binding '%s' for the %s "+ "command is invalid. It must have a modifier "+ "to work properly. i.e., Mod1-tab where 'Mod1' "+ "is the modifier.", kcmd.keyStr, kcmd.cmd) return } keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { run() }).Connect(X, wingo.root.Id, kcmd.keyStr, true) keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { run() }).Connect(X, X.Dummy(), kcmd.keyStr, true) } else { if kcmd.down { keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { run() }).Connect(X, wingo.root.Id, kcmd.keyStr, true) } else { keybind.KeyReleaseFun( func(X *xgbutil.XUtil, ev xevent.KeyReleaseEvent) { run() }).Connect(X, wingo.root.Id, kcmd.keyStr, true) } } }
func grabKeyPress(wid xproto.Window, shortcut string) bool { if len(shortcut) < 1 { logger.Warning("grabKeyPress args error...") return false } shortcut = convertKeysym2Weird(shortcut) mod, keys, err := keybind.ParseString(X, shortcut) if err != nil { logger.Warning("In GrabKey Parse shortcut failed:", err) return false } for _, k := range keys { if err = keybind.GrabChecked(X, wid, mod, k); err != nil { logger.Warningf("Grab '%s' failed: %v", shortcut, err) ungrabKey(wid, shortcut) return false } } return true }
// Show will map and show the slice of items provided. // // 'workarea' is the rectangle to position the prompt window in. (i.e., // typically the rectangle of the monitor to place it on.) // // 'keyStr' is an optional parameter. If this prompt is shown in // response to a keybinding, then keyStr should be the keybinding used. // If there are modifiers used in the keyStr, the prompt will automatically // close if all of the modifiers are released. (This is the "alt-tab" // functionality.) // Note that if you don't want this auto-closing feature, simply leave keyStr // blank, even if the prompt is shown in response to a key binding. // // Show returns false if the prompt cannot be shown for some reason. func (cycle *Cycle) Show(workarea xrect.Rect, keyStr string, items []*CycleItem) bool { if cycle.showing { return false } // If there are no items, obviously quit. if len(items) == 0 { return false } // Note that SmartGrab is smart and avoids races. Check it out // in xgbutil/keybind.go if you're interested. // This makes it impossible to press and release alt-tab too quickly // to have it not register. if cycle.config.Grab { if err := keybind.SmartGrab(cycle.X, cycle.X.Dummy()); err != nil { logger.Warning.Printf( "Could not grab keyboard for prompt cycle: %s", err) return false } } // Save the list of cycle items (this how we know when to cycle between // them). Namely, cycle.selected is an index to this list. cycle.items = items // Save the modifiers used, if any. cycle.grabMods, _, _ = keybind.ParseString(cycle.X, keyStr) // Put the prompt window on top of the window stack. cycle.win.Stack(xproto.StackModeAbove) // Create some short aliases and start computing the geometry of the // cycle window. bs := cycle.theme.BorderSize cbs := cycle.theme.IconBorderSize is := cycle.theme.IconSize pad := cycle.theme.Padding maxWidth := int(float64(workarea.Width()) * 0.8) x, y := bs+pad, bs+pad+cbs+cycle.fontHeight width := 2 * (bs + pad) height := (2 * (bs + pad + cbs)) + is + cbs + cycle.fontHeight maxFontWidth := 0 widthStatic := false // when true, we stop increasing width for _, item := range items { maxFontWidth = misc.Max(maxFontWidth, item.text.Geom.Width()) // Check if we should move on to the next row. if x+(is+(2*cbs))+pad+bs > maxWidth { x = bs + pad y += is + (2 * cbs) height += is + (2 * cbs) widthStatic = true } // Position the icon window and map its active version or its // inactive version if it's iconified. item.show(x, y) // Only increase the width if we're still adding icons to the first row. if !widthStatic { width += is + (2 * cbs) } x += is + (2 * cbs) } // If the computed width is less than the max font width, then increase // the width of the prompt to fit the longest window title. // Forcefully cap it as the maxWidth, though. if maxFontWidth+2*(pad+bs) > width { width = misc.Min(maxWidth, maxFontWidth+2*(pad+bs)) } // position the damn window based on its width/height (i.e., center it) posx := workarea.X() + workarea.Width()/2 - width/2 posy := workarea.Y() + workarea.Height()/2 - height/2 // Issue the configure requests. We also need to adjust the borders. cycle.win.MoveResize(posx, posy, width, height) cycle.bTop.Resize(width, bs) cycle.bBot.MoveResize(0, height-bs, width, bs) cycle.bLft.Resize(bs, height) cycle.bRht.MoveResize(width-bs, 0, bs, height) cycle.showing = true cycle.selected = -1 cycle.win.Map() return true }
func (kcmd keyCommand) attach() { if kcmd.cmdName == "CycleClientPrev" || kcmd.cmdName == "CycleClientNext" { // We've got to parse the key string first and make sure // there are some modifiers; otherwise this utterly fails! mods, _, _ := keybind.ParseString(X, kcmd.keyStr) if mods == 0 { logger.Warning.Printf("Sorry but the key binding '%s' for the %s "+ "command is invalid. It must have a modifier "+ "to work properly. i.e., Mod1-tab where 'Mod1' "+ "is the modifier.", kcmd.keyStr, kcmd.cmdName) return } run, err := cmdHacks.CycleClientRunWithKeyStr(kcmd.keyStr, kcmd.cmdStr) if err != nil { logger.Warning.Printf("Could not setup %s: %s", kcmd.cmdName, err) return } err = keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { go run() }).Connect(X, Root.Id, kcmd.keyStr, true) if err != nil { logger.Warning.Printf("Could not bind '%s': %s", kcmd.keyStr, err) } err = keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { go run() }).Connect(X, X.Dummy(), kcmd.keyStr, true) if err != nil { logger.Warning.Printf("Could not bind '%s': %s", kcmd.keyStr, err) } } else { run := func() { go func() { _, err := gribbleEnv.Run(kcmd.cmdStr) if err != nil { logger.Warning.Println(err) } }() } if kcmd.down { err := keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { run() }).Connect(X, Root.Id, kcmd.keyStr, true) if err != nil { logger.Warning.Printf("Could not bind '%s': %s", kcmd.keyStr, err) } } else { err := keybind.KeyReleaseFun( func(X *xgbutil.XUtil, ev xevent.KeyReleaseEvent) { run() }).Connect(X, Root.Id, kcmd.keyStr, true) if err != nil { logger.Warning.Printf("Could not bind '%s': %s", kcmd.keyStr, err) } } } }