THE DRAGON HAS BEEN SLAIN

Numlock is fully supported, as well as shift lock. Of course, I
cannot properly test shift lock or caps lock because I have neither
of those things, but I assume they work as well as num lock does.
This commit is contained in:
Sasha Koshka 2022-11-24 22:02:32 -05:00
parent 33ed2af075
commit 941a78eaf1
3 changed files with 112 additions and 14 deletions

View File

@ -74,7 +74,13 @@ func factory (
if err != nil { return }
backend.window, err = xwindow.Generate(backend.connection)
if err != nil { return }
// get keyboard mapping information
keybind.Initialize(backend.connection)
backend.modifierMasks.capsLock = backend.keysymToMask(0xFFE5)
backend.modifierMasks.shiftLock = backend.keysymToMask(0xFFE6)
backend.modifierMasks.numLock = backend.keysymToMask(0xFF7F)
backend.modifierMasks.modeSwitch = backend.keysymToMask(0xFF7E)
// create the window
backend.window.Create (
@ -158,6 +164,38 @@ func findAndLoadFont (name string, size float64) (face font.Face) {
return
}
func (backend *Backend) keysymToKeycode (
symbol xproto.Keysym,
) (
code xproto.Keycode,
) {
mapping := keybind.KeyMapGet(backend.connection)
for index, testSymbol := range mapping.Keysyms {
if testSymbol == symbol {
code = xproto.Keycode (
index /
int(mapping.KeysymsPerKeycode) +
int(backend.connection.Setup().MinKeycode))
break
}
}
return
}
func (backend *Backend) keysymToMask (
symbol xproto.Keysym,
) (
mask uint16,
) {
mask = keybind.ModGet (
backend.connection,
backend.keysymToKeycode(symbol))
return
}
// init registers this backend when the program starts.
func init () {
stone.RegisterBackend(factory)

View File

@ -1,5 +1,7 @@
package x
// TODO: rename this file? lol
// import "fmt"
import "unicode"
import "github.com/jezek/xgb/xproto"
@ -117,13 +119,11 @@ func (backend *Backend) keycodeToButton (
button stone.Button,
numberPad bool,
) {
// FIXME: also set shift to true if the lock modifier is on and the lock
// modifier is interpreted as shiftLock
shift := state & xproto.ModMaskShift > 0
// FIXME: only set this to true if the lock modifier is on and the lock
// modifier is interpreted as capsLock
capsLock := state & xproto.ModMaskLock > 0
shift :=
state & xproto.ModMaskShift > 0 ||
state & backend.modifierMasks.shiftLock > 0
capsLock := state & backend.modifierMasks.capsLock > 0
numLock := state & backend.modifierMasks.numLock > 0
symbol1 := keybind.KeysymGet(backend.connection, keycode, 0)
symbol2 := keybind.KeysymGet(backend.connection, keycode, 1)
@ -132,7 +132,19 @@ func (backend *Backend) keycodeToButton (
cased := false
// third paragraph
// PARAGRAPH 3
//
// A list of KeySyms is associated with each KeyCode. The list is
// intended to convey the set of symbols on the corresponding key. If
// the list (ignoring trailing NoSymbol entries) is a single KeySym
// ``K'', then the list is treated as if it were the list ``K NoSymbol
// K NoSymbol''. If the list (ignoring trailing NoSymbol entries) is a
// pair of KeySyms ``K1 K2'', then the list is treated as if it were the
// list ``K1 K2 K1 K2''. If the list (ignoring trailing NoSymbol
// entries) is a triple of KeySyms ``K1 K2 K3'', then the list is
// treated as if it were the list ``K1 K2 K3 NoSymbol''. When an
// explicit ``void'' element is desired in the list, the value
// VoidSymbol can be used.
switch {
case symbol2 == 0 && symbol3 == 0 && symbol4 == 0:
symbol3 = symbol1
@ -151,7 +163,18 @@ func (backend *Backend) keycodeToButton (
// FIXME: we ignore mode switch stuff
_ = symbol4Rune
// fourth paragraph
// PARAGRAPH 4
//
// The first four elements of the list are split into two groups of
// KeySyms. Group 1 contains the first and second KeySyms; Group 2
// contains the third and fourth KeySyms. Within each group, if the
// second element of the group is NoSymbol , then the group should be
// treated as if the second element were the same as the first element,
// except when the first element is an alphabetic KeySym ``K'' for which
// both lowercase and uppercase forms are defined. In that case, the
// group should be treated as if the first element were the lowercase
// form of ``K'' and the second element were the uppercase form of
// ``K.''
if symbol2 == 0 {
upper := unicode.IsUpper(symbol1Rune)
lower := unicode.IsLower(symbol1Rune)
@ -180,30 +203,60 @@ func (backend *Backend) keycodeToButton (
var selectedKeysym xproto.Keysym
var selectedRune rune
// big ol list in the middle
_, symbol2IsNumPad := keypadCodeTable[symbol2]
// "PARAGRAPH" 5
//
// Within a group, the choice of KeySym is determined by applying the
// first rule that is satisfied from the following list:
switch {
// FIXME: take into account numlock
case numLock && symbol2IsNumPad:
// The numlock modifier is on and the second KeySym is a keypad
// KeySym. In this case, if the Shift modifier is on, or if the
// Lock modifier is on and is interpreted as ShiftLock, then the
// first KeySym is used, otherwise the second KeySym is used.
if shift {
selectedKeysym = symbol1
selectedRune = symbol1Rune
} else {
selectedKeysym = symbol2
selectedRune = symbol2Rune
}
case !shift && !capsLock:
// The Shift and Lock modifiers are both off. In this case, the
// first KeySym is used.
selectedKeysym = symbol1
selectedRune = symbol1Rune
case !shift && capsLock:
// The Shift modifier is off, and the Lock modifier is on and is
// interpreted as CapsLock. In this case, the first KeySym is
// used, but if that KeySym is lowercase alphabetic, then the
// corresponding uppercase KeySym is used instead.
if cased && unicode.IsLower(symbol1Rune) {
selectedRune = symbol2Rune
} else {
selectedKeysym = symbol1
selectedRune = symbol1Rune
}
case shift && capsLock:
// The Shift modifier is on, and the Lock modifier is on and is
// interpreted as CapsLock. In this case, the second KeySym is
// used, but if that KeySym is lowercase alphabetic, then the
// corresponding uppercase KeySym is used instead.
if cased && unicode.IsLower(symbol2Rune) {
selectedRune = unicode.ToUpper(symbol2Rune)
} else {
selectedKeysym = symbol2
selectedRune = symbol2Rune
}
case shift:
// The Shift modifier is on, or the Lock modifier is on and is
// interpreted as ShiftLock, or both. In this case, the second
// KeySym is used.
selectedKeysym = symbol2
selectedRune = symbol2Rune
}

View File

@ -43,6 +43,13 @@ type Backend struct {
descent int
}
modifierMasks struct {
capsLock uint16
shiftLock uint16
numLock uint16
modeSwitch uint16
}
windowBoundsClean bool
}