1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#![allow(dead_code, non_camel_case_types)]

use libc::{uint32_t, c_char, c_int, size_t, c_void, c_uint};

pub mod keysyms;
#[macro_use]mod dlopen;

extern {
    pub fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void;
    pub fn dlerror() -> *mut c_char;
    pub fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void;
    pub fn dlclose(handle: *mut c_void) -> c_int;
}

pub const XKB_MOD_NAME_SHIFT   : &'static str  = "Shift";
pub const XKB_MOD_NAME_CAPS    : &'static str  = "Lock";
pub const XKB_MOD_NAME_CTRL    : &'static str  = "Control";
pub const XKB_MOD_NAME_ALT     : &'static str  = "Mod1";
pub const XKB_MOD_NAME_NUM     : &'static str  = "Mod2";
pub const XKB_MOD_NAME_LOGO    : &'static str  = "Mod4";

pub const XKB_LED_NAME_CAPS    : &'static str  = "Caps Lock";
pub const XKB_LED_NAME_NUM     : &'static str  = "Num Lock";
pub const XKB_LED_NAME_SCROLL  : &'static str  = "Scroll Lock";

pub struct xkb_context;
pub struct xkb_keymap;
pub struct xkb_state;

pub type xkb_keycode_t = uint32_t;
pub type xkb_keysym_t = uint32_t;
pub type xkb_layout_index_t = uint32_t;
pub type xkb_layout_mask_t = uint32_t;
pub type xkb_level_index_t = uint32_t;
pub type xkb_mod_index_t = uint32_t;
pub type xkb_mod_mask_t = uint32_t;
pub type xkb_led_index_t = uint32_t;
pub type xkb_led_mask_t = uint32_t;

pub const XKB_KEYCODE_INVALID :u32 = 0xffffffff;
pub const XKB_LAYOUT_INVALID  :u32 = 0xffffffff;
pub const XKB_LEVEL_INVALID   :u32 = 0xffffffff;
pub const XKB_MOD_INVALID     :u32 = 0xffffffff;
pub const XKB_LED_INVALID     :u32 = 0xffffffff;
pub const XKB_KEYCODE_MAX     :u32 = 0xffffffff - 1;

#[repr(C)]
pub struct xkb_rule_names {
    rules:   *const c_char,
    model:   *const c_char ,
    layout:  *const c_char,
    variant: *const c_char,
    options: *const c_char,
}

#[repr(C)]
pub enum xkb_keysym_flags {
    /** Do not apply any flags. */
    XKB_KEYSYM_NO_FLAGS = 0,
    /** Find keysym by case-insensitive search. */
    XKB_KEYSYM_CASE_INSENSITIVE = (1 << 0)
}

#[repr(C)]
pub enum xkb_context_flags {
    /** Do not apply any context flags. */
    XKB_CONTEXT_NO_FLAGS = 0,
    /** Create this context with an empty include path. */
    XKB_CONTEXT_NO_DEFAULT_INCLUDES = (1 << 0),
    /**
     * Don't take RMLVO names from the environment.
     * @since 0.3.0
     */
    XKB_CONTEXT_NO_ENVIRONMENT_NAMES = (1 << 1)
}

#[repr(C)]
pub enum xkb_log_level {
    /** Log critical internal errors only. */
    XKB_LOG_LEVEL_CRITICAL = 10,
    /** Log all errors. */
    XKB_LOG_LEVEL_ERROR = 20,
    /** Log warnings and errors. */
    XKB_LOG_LEVEL_WARNING = 30,
    /** Log information, warnings, and errors. */
    XKB_LOG_LEVEL_INFO = 40,
    /** Log everything. */
    XKB_LOG_LEVEL_DEBUG = 50
}

#[repr(C)]
pub enum xkb_keymap_compile_flags {
    /** Do not apply any flags. */
    XKB_KEYMAP_COMPILE_NO_FLAGS = 0,
    __not_univariant = 42,
}

#[repr(C)]
pub enum xkb_keymap_format {
    /** Cannot be used for creation */
    XKB_KEYMAP_USE_ORIGINAL_FORMAT = 0,
    /** The current/classic XKB text format, as generated by xkbcomp -xkb. */
    XKB_KEYMAP_FORMAT_TEXT_V1 = 1,
}

#[repr(C)]
pub enum xkb_key_direction {
    /** The key was released. */
    XKB_KEY_UP,
    /** The key was pressed. */
    XKB_KEY_DOWN
}

bitflags!(
    flags xkb_state_component: uint32_t {
        /** Depressed modifiers, i.e. a key is physically holding them. */
        const XKB_STATE_MODS_DEPRESSED = (1 << 0),
        /** Latched modifiers, i.e. will be unset after the next non-modifier
         *  key press. */
        const XKB_STATE_MODS_LATCHED = (1 << 1),
        /** Locked modifiers, i.e. will be unset after the key provoking the
         *  lock has been pressed again. */
        const XKB_STATE_MODS_LOCKED = (1 << 2),
        /** Effective modifiers, i.e. currently active and affect key
         *  processing (derived from the other state components).
         *  Use this unless you explictly care how the state came about. */
        const XKB_STATE_MODS_EFFECTIVE = (1 << 3),
        /** Depressed layout, i.e. a key is physically holding it. */
        const XKB_STATE_LAYOUT_DEPRESSED = (1 << 4),
        /** Latched layout, i.e. will be unset after the next non-modifier
         *  key press. */
        const XKB_STATE_LAYOUT_LATCHED = (1 << 5),
        /** Locked layout, i.e. will be unset after the key provoking the lock
         *  has been pressed again. */
        const XKB_STATE_LAYOUT_LOCKED = (1 << 6),
        /** Effective layout, i.e. currently active and affects key processing
         *  (derived from the other state components).
         *  Use this unless you explictly care how the state came about. */
        const XKB_STATE_LAYOUT_EFFECTIVE = (1 << 7),
        /** LEDs (derived from the other state components). */
        const XKB_STATE_LEDS = (1 << 8)
    }
);

external_library!(XkbCommon,
    xkb_keysym_get_name: unsafe extern fn(keysym: xkb_keysym_t,
                                          bufer: *mut c_char,
                                          size: size_t
                                         ) -> c_int,
    xkb_keysym_from_name: unsafe extern fn(name: *const c_char,
                                           flags: xkb_keysym_flags
                                          ) -> xkb_keysym_t,
    xkb_keysym_to_utf8: unsafe extern fn(keysym: xkb_keysym_t,
                                         buffer: *mut c_char,
                                         size: size_t
                                        ) -> c_int,
    xkb_keysym_to_utf32: unsafe extern fn(keysym: xkb_keysym_t) -> uint32_t,
    xkb_context_new: unsafe extern fn(flags: xkb_context_flags) -> *mut xkb_context,
    xkb_context_ref: unsafe extern fn(constex: *mut xkb_context) -> *mut xkb_context,
    xkb_context_unref: unsafe extern fn(context: *mut xkb_context),
    xkb_context_set_user_data: unsafe extern fn(context: *mut xkb_context,
                                                user_data: *mut c_void
                                               ),
    xkb_context_get_user_data: unsafe extern fn(context: *mut xkb_context) -> *mut c_void,
    xkb_context_include_path_append: unsafe extern fn(context: *mut xkb_context,
                                                      path: *const c_char
                                                     ) -> c_int,
    xkb_context_include_path_append_default: unsafe extern fn(context: *mut xkb_context) -> c_int,
    xkb_context_include_path_reset_defaults: unsafe extern fn(context: *mut xkb_context) -> c_int,
    xkb_context_include_path_clear: unsafe extern fn(context: *mut xkb_context),
    xkb_context_num_include_paths: unsafe extern fn(context: *mut xkb_context) -> c_uint,
    xkb_context_include_path_get: unsafe extern fn(context: *mut xkb_context,
                                                   index: c_uint
                                                  ) -> *const c_char,
    xkb_context_set_log_level: unsafe extern fn(context: *mut xkb_context,
                                                level: xkb_log_level
                                               ),
    xkb_context_get_log_level: unsafe extern fn(context: *mut xkb_context) -> xkb_log_level,
    xkb_context_set_log_verbosity: unsafe extern fn(context: *mut xkb_context, verbosity: c_int),
    xkb_context_get_log_verbosity: unsafe extern fn(context: *mut xkb_context) -> c_int,
    xkb_keymap_new_from_names: unsafe extern fn(context: *mut xkb_context,
                                                names: *const xkb_rule_names,
                                                flags: xkb_keymap_compile_flags
                                               ) -> *mut xkb_keymap,
    xkb_keymap_new_from_string: unsafe extern fn(context: *mut xkb_context,
                                                 string: *const c_char,
                                                 format: xkb_keymap_format,
                                                 flags: xkb_keymap_compile_flags
                                                ) -> *mut xkb_keymap,
    xkb_keymap_new_from_buffer: unsafe extern fn(context: *mut xkb_context,
                                                 buffer: *const c_char,
                                                 length: size_t,
                                                 format: xkb_keymap_format,
                                                 flags: xkb_keymap_compile_flags
                                                ) -> *mut xkb_keymap,
    xkb_keymap_ref: unsafe extern fn(keymap: *mut xkb_keymap) -> *mut xkb_keymap,
    xkb_keymap_unref: unsafe extern fn(keymap: *mut xkb_keymap),
    xkb_keymap_get_as_string: unsafe extern fn(keymap: *mut xkb_keymap,
                                               format: xkb_keymap_format
                                              ) -> *const c_char,

    xkb_state_new: unsafe extern fn(keymap: *mut xkb_keymap) -> *mut xkb_state,
    xkb_state_ref: unsafe extern fn(state: *mut xkb_state) -> *mut xkb_state,
    xkb_state_unref: unsafe extern fn(state: *mut xkb_state),
    xkb_state_update_mask: unsafe extern fn(state: *mut xkb_state,
                                            depressed_mods: xkb_mod_mask_t,
                                            latched_mods: xkb_mod_mask_t,
                                            locked_mods: xkb_mod_mask_t,
                                            depressed_layout: xkb_layout_index_t,
                                            latched_layout: xkb_layout_index_t,
                                            locked_layout: xkb_layout_index_t
                                           ) -> xkb_state_component,
    xkb_state_update_key: unsafe extern fn(state: *mut xkb_state,
                                           key: xkb_keycode_t,
                                           direction: xkb_key_direction
                                          ) -> xkb_state_component,
    xkb_state_key_get_syms: unsafe extern fn(state: *mut xkb_state,
                                             key: xkb_keycode_t,
                                             syms_out: *const *mut xkb_keysym_t
                                            ) -> c_int,
    xkb_state_key_get_utf8: unsafe extern fn(state: *mut xkb_state,
                                             key: xkb_keycode_t,
                                             buffer: *mut c_char,
                                             size: size_t
                                            ) -> c_int,
    xkb_state_key_get_utf32: unsafe extern fn(state: *mut xkb_state,
                                              key: xkb_keycode_t
                                             ) -> uint32_t,
    xkb_state_key_get_one_sym: unsafe extern fn(state: *mut xkb_state,
                                                key: xkb_keycode_t
                                               ) -> xkb_keysym_t
);

lazy_static!(
    pub static ref XKBCOMMON_OPTION: Option<XkbCommon> = {
        XkbCommon::open("libxkbcommon.so")
    };
    pub static ref XKBCOMMON_HANDLE: &'static XkbCommon = {
        XKBCOMMON_OPTION.as_ref().expect("Library libxkbcommon.so could not be loaded.")
    };
);