label_printer/epson/faxmachine/xkbcommon/xkbcommon.go

618 lines
21 KiB
Go
Raw Normal View History

// xkbcommon contains Go bindings for the libxkbcommon C library. All the doc
// comments here are 1-to-1 copies of the C doc comments, and may refer to
// C-specific behavior that is abstracted away by the bindings.
package xkbcommon
import (
"errors"
"unsafe"
)
/*
#cgo pkg-config: xkbcommon
#include <stdlib.h>
#include <xkbcommon/xkbcommon.h>
*/
import "C"
// @struct xkb_context
// Opaque top level library context object.
//
// The context contains various general library data and state, like
// logging level and include paths.
//
// Objects are created in a specific context, and multiple contexts may
// coexist simultaneously. Objects from different contexts are completely
// separated and do not share any memory or state.
type Context C.struct_xkb_context
func (c *Context) value() *C.struct_xkb_context {
return (*C.struct_xkb_context)(c)
}
// Opaque compiled keymap object.
//
// The keymap object holds all of the static keyboard information obtained
// from compiling XKB files.
//
// A keymap is immutable after it is created (besides reference counts, etc.);
// if you need to change it, you must create a new one.
type Keymap C.struct_xkb_keymap
func (k *Keymap) value() *C.struct_xkb_keymap {
return (*C.struct_xkb_keymap)(k)
}
// @struct xkb_state
// Opaque keyboard state object.
//
// State objects contain the active state of a keyboard (or keyboards), such
// as the currently effective layout and the active modifiers. It acts as a
// simple state machine, wherein key presses and releases are the input, and
// key symbols (keysyms) are the output.
type State C.struct_xkb_state
func (s *State) value() *C.struct_xkb_state {
return (*C.struct_xkb_state)(s)
}
// A number used to represent a physical key on a keyboard.
//
// A standard PC-compatible keyboard might have 102 keys. An appropriate
// keymap would assign each of them a keycode, by which the user should
// refer to the key throughout the library.
//
// Historically, the X11 protocol, and consequentially the XKB protocol,
// assign only 8 bits for keycodes. This limits the number of different
// keys that can be used simultaneously in a single keymap to 256
// (disregarding other limitations). This library does not share this limit;
// keycodes beyond 255 ('extended keycodes') are not treated specially.
// Keymaps and applications which are compatible with X11 should not use
// these keycodes.
//
// The values of specific keycodes are determined by the keymap and the
// underlying input system. For example, with an X11-compatible keymap
// and Linux evdev scan codes (see linux/input.h), a fixed offset is used:
//
// The keymap defines a canonical name for each key, plus possible aliases.
// Historically, the XKB protocol restricts these names to at most 4 (ASCII)
// characters, but this library does not share this limit.
//
// @code
// xkb_keycode_t keycode_A = KEY_A + 8;
// @endcode
//
// @sa xkb_keycode_is_legal_ext() xkb_keycode_is_legal_x11()
type Keycode C.xkb_keycode_t
// A number used to represent the symbols generated from a key on a keyboard.
//
// A key, represented by a keycode, may generate different symbols according
// to keyboard state. For example, on a QWERTY keyboard, pressing the key
// labled \<A\> generates the symbol a. If the Shift key is held, it
// generates the symbol A. If a different layout is used, say Greek,
// it generates the symbol α. And so on.
//
// Each such symbol is represented by a *keysym* (short for “key symbol”).
// Note that keysyms are somewhat more general, in that they can also represent
// some “function”, such as “Left” or “Right” for the arrow keys. For more
// information, see: Appendix A [“KEYSYM Encoding”][encoding] of the X Window
// System Protocol.
//
// Specifically named keysyms can be found in the
// xkbcommon/xkbcommon-keysyms.h header file. Their name does not include
// the `XKB_KEY_` prefix.
//
// Besides those, any Unicode/ISO&nbsp;10646 character in the range U+0100 to
// U+10FFFF can be represented by a keysym value in the range 0x01000100 to
// 0x0110FFFF. The name of Unicode keysyms is `U<codepoint>`, e.g. `UA1B2`.
//
// The name of other unnamed keysyms is the hexadecimal representation of
// their value, e.g. `0xabcd1234`.
//
// Keysym names are case-sensitive.
//
// @note **Encoding:** Keysyms are 32-bit integers with the 3 most significant
// bits always set to zero. See: Appendix A [“KEYSYM Encoding”][encoding] of
// the X Window System Protocol.
//
// @ingroup keysyms
// @sa XKB_KEYSYM_MAX
//
// [encoding]: https://www.x.org/releases/current/doc/xproto/x11protocol.html#keysym_encoding
type Keysym C.xkb_keysym_t
// Index of a modifier.
//
// A @e modifier is a state component which changes the way keys are
// interpreted. A keymap defines a set of modifiers, such as Alt, Shift,
// Num Lock or Meta, and specifies which keys may @e activate which
// modifiers (in a many-to-many relationship, i.e. a key can activate
// several modifiers, and a modifier may be activated by several keys.
// Different keymaps do this differently).
//
// When retrieving the keysyms for a key, the active modifier set is
// consulted; this detemines the correct shift level to use within the
// currently active layout (see xkb_level_index_t).
//
// Modifier indices are consecutive. The first modifier has index 0.
//
// Each modifier must have a name, and the names are unique. Therefore, it
// is safe to use the name as a unique identifier for a modifier. The names
// of some common modifiers are provided in the xkbcommon/xkbcommon-names.h
// header file. Modifier names are case-sensitive.
//
// @sa xkb_keymap_num_mods()
type ModIndex C.xkb_mod_index_t
// A mask of modifier indices.
type ModMask C.xkb_mod_mask_t
var ModInvalid ModIndex = C.XKB_MOD_INVALID
// Names to compile a keymap with, also known as RMLVO.
//
// The names are the common configuration values by which a user picks
// a keymap.
//
// If the entire struct is NULL, then each field is taken to be NULL.
// You should prefer passing NULL instead of choosing your own defaults.
type RuleNames struct {
// The rules file to use. The rules file describes how to interpret
// the values of the model, layout, variant and options fields.
//
// If NULL or the empty string "", a default value is used.
// If the XKB_DEFAULT_RULES environment variable is set, it is used
// as the default. Otherwise the system default is used.
Rules string
// The keyboard model by which to interpret keycodes and LEDs.
//
// If NULL or the empty string "", a default value is used.
// If the XKB_DEFAULT_MODEL environment variable is set, it is used
// as the default. Otherwise the system default is used.
Model string
// A comma separated list of layouts (languages) to include in the
// keymap.
//
// If NULL or the empty string "", a default value is used.
// If the XKB_DEFAULT_LAYOUT environment variable is set, it is used
// as the default. Otherwise the system default is used.
Layout string
// A comma separated list of variants, one per layout, which may
// modify or augment the respective layout in various ways.
//
// Generally, should either be empty or have the same number of values
// as the number of layouts. You may use empty values as in "intl,,neo".
//
// If NULL or the empty string "", and a default value is also used
// for the layout, a default value is used. Otherwise no variant is
// used.
// If the XKB_DEFAULT_VARIANT environment variable is set, it is used
// as the default. Otherwise the system default is used.
Variant string
// A comma separated list of options, through which the user specifies
// non-layout related preferences, like which key combinations are used
// for switching layouts, or which key is the Compose key.
//
// If NULL, a default value is used. If the empty string "", no
// options are used.
// If the XKB_DEFAULT_OPTIONS environment variable is set, it is used
// as the default. Otherwise the system default is used.
Options string
}
func (rn *RuleNames) value() *C.struct_xkb_rule_names {
if rn == nil {
return nil
}
var cStruct C.struct_xkb_rule_names
if rn.Rules != "" {
cStruct.rules = C.CString(rn.Rules)
}
if rn.Model != "" {
cStruct.model = C.CString(rn.Model)
}
if rn.Layout != "" {
cStruct.layout = C.CString(rn.Layout)
}
if rn.Variant != "" {
cStruct.variant = C.CString(rn.Variant)
}
if rn.Options != "" {
cStruct.options = C.CString(rn.Options)
}
return &cStruct
}
func (rn *RuleNames) free(cStruct *C.struct_xkb_rule_names) {
if cStruct != nil {
C.free(unsafe.Pointer(cStruct.rules))
C.free(unsafe.Pointer(cStruct.model))
C.free(unsafe.Pointer(cStruct.layout))
C.free(unsafe.Pointer(cStruct.variant))
C.free(unsafe.Pointer(cStruct.options))
}
}
// Get the name of a keysym.
//
// For a description of how keysyms are named, see @ref xkb_keysym_t.
//
// @param[in] keysym The keysym.
// @param[out] buffer A string buffer to write the name into.
// @param[in] size Size of the buffer.
//
// @warning If the buffer passed is too small, the string is truncated
// (though still NUL-terminated); a size of at least 64 bytes is recommended.
//
// @returns The number of bytes in the name, excluding the NUL byte. If
// the keysym is invalid, returns -1.
//
// You may check if truncation has occurred by comparing the return value
// with the length of buffer, similarly to the snprintf(3) function.
//
// @sa xkb_keysym_t
func (k Keysym) Name() (string, bool) {
size := C.xkb_keysym_get_name(C.xkb_keysym_t(k), nil, 0)
if size < 0 {
return "", false
}
buffer := (*C.char)(C.malloc(C.size_t(size + 1)))
defer C.free((unsafe.Pointer)(buffer))
C.xkb_keysym_get_name(C.xkb_keysym_t(k), buffer, C.size_t(size+1))
return C.GoString(buffer), true
}
// Flags for context creation.
type ContextFlags C.enum_xkb_context_flags
var (
// Do not apply any context flags.
ContextNoFlags ContextFlags = C.XKB_CONTEXT_NO_FLAGS
// Create this context with an empty include path.
ContextNoDefaultIncludes ContextFlags = C.XKB_CONTEXT_NO_DEFAULT_INCLUDES
// Don't take RMLVO names from the environment
//
// @since 0.3.0
ContextNoEnvironmentNames ContextFlags = C.XKB_CONTEXT_NO_ENVIRONMENT_NAMES
// Disable the use of secure_getenv for this context, so that privileged
// processes can use environment variables. Client uses at their own risk.
//
// @since 1.5.0
ContextNoSecureGetenv ContextFlags = C.XKB_CONTEXT_NO_SECURE_GETENV
)
// Create a new context.
//
// @param flags Optional flags for the context, or 0.
//
// @returns A new context, or NULL on failure.
//
// @memberof xkb_context
func NewContext(flags ContextFlags) (*Context, error) {
ctx := C.xkb_context_new(C.enum_xkb_context_flags(flags))
if ctx == nil {
return nil, errors.New("failed to create context")
}
return (*Context)(ctx), nil
}
// Release a reference on a context, and possibly free it.
//
// @param context The context. If it is NULL, this function does nothing.
//
// @memberof xkb_context
func (c *Context) Unref() {
C.xkb_context_unref(c.value())
}
// Flags for keymap compilation.
type KeymapCompileFlags C.enum_xkb_keymap_compile_flags
var (
// Do not apply any flags.
KeymapCompileFlagsNoFlags KeymapCompileFlags = C.XKB_KEYMAP_COMPILE_NO_FLAGS
)
// Create a keymap from RMLVO names.
//
// The primary keymap entry point: creates a new XKB keymap from a set of
// RMLVO (Rules + Model + Layouts + Variants + Options) names.
//
// @param context The context in which to create the keymap.
// @param names The RMLVO names to use. See xkb_rule_names.
// @param flags Optional flags for the keymap, or 0.
//
// @returns A keymap compiled according to the RMLVO names, or NULL if
// the compilation failed.
//
// @sa xkb_rule_names
// @memberof xkb_keymap
func NewKeymapFromNames(ctx *Context, names *RuleNames,
flags KeymapCompileFlags) (*Keymap, error) {
cNames := names.value()
defer names.free(cNames)
keymap := C.xkb_keymap_new_from_names(ctx.value(), cNames,
C.enum_xkb_keymap_compile_flags(flags))
if keymap == nil {
return nil, errors.New("failed to create keymap")
}
return (*Keymap)(keymap), nil
}
// Release a reference on a keymap, and possibly free it.
//
// @param keymap The keymap. If it is NULL, this function does nothing.
//
// @memberof xkb_keymap
func (k *Keymap) Unref() {
C.xkb_keymap_unref(k.value())
}
// Get the index of a modifier by name.
//
// @returns The index. If no modifier with this name exists, returns
// XKB_MOD_INVALID.
//
// @sa xkb_mod_index_t
// @memberof xkb_keymap
func (k *Keymap) ModGetIndex(name string) ModIndex {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
return ModIndex(C.xkb_keymap_mod_get_index(k.value(), cName))
}
// Create a new keyboard state object.
//
// @param keymap The keymap which the state will use.
//
// @returns A new keyboard state object, or NULL on failure.
//
// @memberof xkb_state
func NewState(keymap *Keymap) (*State, error) {
state := C.xkb_state_new(keymap.value())
if state == nil {
return nil, errors.New("failed to create state")
}
return (*State)(state), nil
}
func (s *State) Unref() {
C.xkb_state_unref(s.value())
}
// Specifies the direction of the key (press / release).
type KeyDirection C.enum_xkb_key_direction
var (
// The key was released.
KeyUp KeyDirection = C.XKB_KEY_UP
// The key was pressed.
KeyDown KeyDirection = C.XKB_KEY_DOWN
)
// Modifier and layout types for state objects. This enum is bitmaskable,
// e.g. (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED) is valid to
// exclude locked modifiers.
//
// In XKB, the DEPRESSED components are also known as 'base'.
type StateComponent C.enum_xkb_state_component
var (
// Depressed modifiers, i.e. a key is physically holding them.
StateModsDepressed StateComponent = C.XKB_STATE_MODS_DEPRESSED
// Latched modifiers, i.e. will be unset after the next non-modifier
// key press.
StateModsLatched StateComponent = C.XKB_STATE_MODS_LATCHED
// Locked modifiers, i.e. will be unset after the key provoking the
// lock has been pressed again.
StateModsLocked StateComponent = C.XKB_STATE_MODS_LOCKED
// Effective modifiers, i.e. currently active and affect key
// processing (derived from the other state components).
// Use this unless you explicitly care how the state came about.
StateModsEffective StateComponent = C.XKB_STATE_MODS_EFFECTIVE
// Depressed layout, i.e. a key is physically holding it.
StateLayoutDepressed StateComponent = C.XKB_STATE_LAYOUT_DEPRESSED
// Latched layout, i.e. will be unset after the next non-modifier
// key press.
StateLayoutLatched StateComponent = C.XKB_STATE_LAYOUT_LATCHED
// Locked layout, i.e. will be unset after the key provoking the lock
// has been pressed again.
StateLayoutLocked StateComponent = C.XKB_STATE_LAYOUT_LOCKED
// Effective layout, i.e. currently active and affects key processing
// (derived from the other state components).
// Use this unless you explicitly care how the state came about.
StateLayoutEffective StateComponent = C.XKB_STATE_LAYOUT_EFFECTIVE
// LEDs (derived from the other state components).
STATE_LEDS StateComponent = C.XKB_STATE_LEDS
)
// Update the keyboard state to reflect a given key being pressed or
// released.
//
// This entry point is intended for *server* applications and should not be used
// by *client* applications; see @ref server-client-state for details.
//
// A series of calls to this function should be consistent; that is, a call
// with XKB_KEY_DOWN for a key should be matched by an XKB_KEY_UP; if a key
// is pressed twice, it should be released twice; etc. Otherwise (e.g. due
// to missed input events), situations like "stuck modifiers" may occur.
//
// This function is often used in conjunction with the function
// xkb_state_key_get_syms() (or xkb_state_key_get_one_sym()), for example,
// when handling a key event. In this case, you should prefer to get the
// keysyms *before* updating the key, such that the keysyms reported for
// the key event are not affected by the event itself. This is the
// conventional behavior.
//
// @returns A mask of state components that have changed as a result of
// the update. If nothing in the state has changed, returns 0.
//
// @memberof xkb_state
//
// @sa xkb_state_update_mask()
func (s *State) UpdateKey(key Keycode, direction KeyDirection) StateComponent {
stateComponent := C.xkb_state_update_key(s.value(), C.xkb_keycode_t(key),
C.enum_xkb_key_direction(direction))
return StateComponent(stateComponent)
}
// Get the Unicode/UTF-8 string obtained from pressing a particular key
// in a given keyboard state.
//
// @param[in] state The keyboard state object.
// @param[in] key The keycode of the key.
// @param[out] buffer A buffer to write the string into.
// @param[in] size Size of the buffer.
//
// @warning If the buffer passed is too small, the string is truncated
// (though still NUL-terminated).
//
// @returns The number of bytes required for the string, excluding the
// NUL byte. If there is nothing to write, returns 0.
//
// You may check if truncation has occurred by comparing the return value
// with the size of @p buffer, similarly to the snprintf(3) function.
// You may safely pass NULL and 0 to @p buffer and @p size to find the
// required size (without the NUL-byte).
//
// This function performs Capitalization and Control @ref
// keysym-transformations.
//
// @memberof xkb_state
// @since 0.4.1
func (s *State) KeyGetUtf8(key Keycode) string {
size := C.xkb_state_key_get_utf8(s.value(), C.xkb_keycode_t(key), nil, 0)
if size == 0 {
return ""
}
buffer := (*C.char)(C.malloc(C.size_t(size + 1)))
defer C.free((unsafe.Pointer)(buffer))
C.xkb_state_key_get_utf8(s.value(), C.xkb_keycode_t(key), buffer, C.size_t(size+1))
return C.GoString(buffer)
}
// Get the single keysym obtained from pressing a particular key in a
// given keyboard state.
//
// This function is similar to xkb_state_key_get_syms(), but intended
// for users which cannot or do not want to handle the case where
// multiple keysyms are returned (in which case this function is
// preferred).
//
// @returns The keysym. If the key does not have exactly one keysym,
// returns XKB_KEY_NoSymbol
//
// This function performs Capitalization @ref keysym-transformations.
//
// @sa xkb_state_key_get_syms()
// @memberof xkb_state
func (s *State) GetOneSym(keycode Keycode) Keysym {
keysym := C.xkb_state_key_get_one_sym(s.value(), C.xkb_keycode_t(keycode))
return Keysym(keysym)
}
// The counterpart to xkb_state_update_mask for modifiers, to be used on
// the server side of serialization.
//
// This entry point is intended for *server* applications; see @ref
// server-client-state for details. *Client* applications should use the
// xkb_state_mod_*_is_active API.
//
// @param state The keyboard state.
// @param components A mask of the modifier state components to serialize.
// State components other than XKB_STATE_MODS_* are ignored.
// If XKB_STATE_MODS_EFFECTIVE is included, all other state components are
// ignored.
//
// @returns A xkb_mod_mask_t representing the given components of the
// modifier state.
//
// @memberof xkb_state
func (s *State) SerializeMods(components StateComponent) ModMask {
return ModMask(C.xkb_state_serialize_mods(s.value(), C.enum_xkb_state_component(components)))
}
// Consumed modifiers mode.
//
// There are several possible methods for deciding which modifiers are
// consumed and which are not, each applicable for different systems or
// situations. The mode selects the method to use.
//
// Keep in mind that in all methods, the keymap may decide to "preserve"
// a modifier, meaning it is not reported as consumed even if it would
// have otherwise.
type ConsumedMode C.enum_xkb_consumed_mode
var (
// This is the mode defined in the XKB specification and used by libX11.
//
// A modifier is consumed if and only if it *may affect* key translation.
//
// For example, if `Control+Alt+<Backspace>` produces some assigned keysym,
// then when pressing just `<Backspace>`, `Control` and `Alt` are consumed,
// even though they are not active, since if they *were* active they would
// have affected key translation.
ConsumedModeXKB ConsumedMode = C.XKB_CONSUMED_MODE_XKB
// This is the mode used by the GTK+ toolkit.
//
// The mode consists of the following two independent heuristics:
//
// - The currently active set of modifiers, excluding modifiers which do
// not affect the key (as described for @ref XKB_CONSUMED_MODE_XKB), are
// considered consumed, if the keysyms produced when all of them are
// active are different from the keysyms produced when no modifiers are
// active.
//
// - A single modifier is considered consumed if the keysyms produced for
// the key when it is the only active modifier are different from the
// keysyms produced when no modifiers are active.
ConsumedModeGTK ConsumedMode = C.XKB_CONSUMED_MODE_GTK
)
// Get the mask of modifiers consumed by translating a given key.
//
// @param state The keyboard state.
// @param key The keycode of the key.
// @param mode The consumed modifiers mode to use; see enum description.
//
// @returns a mask of the consumed modifiers.
//
// @memberof xkb_state
// @since 0.7.0
func (s *State) KeyGetConsumedMods2(key Keycode, mode ConsumedMode) ModMask {
return ModMask(C.xkb_state_key_get_consumed_mods2(s.value(),
C.xkb_keycode_t(key), C.enum_xkb_consumed_mode(mode)))
}
// Same as xkb_state_key_get_consumed_mods2() with mode XKB_CONSUMED_MODE_XKB.
//
// @memberof xkb_state
// @since 0.4.1
func (s *State) KeyGetConsumedMods(key Keycode) ModMask {
return ModMask(C.xkb_state_key_get_consumed_mods(s.value(), C.xkb_keycode_t(key)))
}