1*2b949d04SAndroid Build Coastguard Worker# Quick Guide 2*2b949d04SAndroid Build Coastguard Worker 3*2b949d04SAndroid Build Coastguard Worker## Introduction 4*2b949d04SAndroid Build Coastguard Worker 5*2b949d04SAndroid Build Coastguard WorkerThis document contains a quick walk-through of the often-used parts of 6*2b949d04SAndroid Build Coastguard Workerthe library. We will employ a few use-cases to lead the examples: 7*2b949d04SAndroid Build Coastguard Worker 8*2b949d04SAndroid Build Coastguard Worker1. An evdev client. "evdev" is the Linux kernel's input subsystem; it 9*2b949d04SAndroid Build Coastguard Worker only reports to the client which keys are pressed and released. 10*2b949d04SAndroid Build Coastguard Worker 11*2b949d04SAndroid Build Coastguard Worker2. An X11 client, using the XCB library to communicate with the X 12*2b949d04SAndroid Build Coastguard Worker server and the xcb-xkb library for using the XKB protocol. 13*2b949d04SAndroid Build Coastguard Worker 14*2b949d04SAndroid Build Coastguard Worker3. A Wayland client, using the standard protocol. 15*2b949d04SAndroid Build Coastguard Worker 16*2b949d04SAndroid Build Coastguard WorkerThe snippets are not complete, and some support code is omitted. You 17*2b949d04SAndroid Build Coastguard Workercan find complete and more complex examples in the source directory: 18*2b949d04SAndroid Build Coastguard Worker 19*2b949d04SAndroid Build Coastguard Worker1. tools/interactive-evdev.c contains an interactive evdev client. 20*2b949d04SAndroid Build Coastguard Worker 21*2b949d04SAndroid Build Coastguard Worker2. tools/interactive-x11.c contains an interactive X11 client. 22*2b949d04SAndroid Build Coastguard Worker 23*2b949d04SAndroid Build Coastguard Worker3. tools/interactive-wayland.c contains an interactive Wayland client. 24*2b949d04SAndroid Build Coastguard Worker 25*2b949d04SAndroid Build Coastguard WorkerAlso, the library contains many more functions for examining and using 26*2b949d04SAndroid Build Coastguard Workerthe library context, the keymap and the keyboard state. See the 27*2b949d04SAndroid Build Coastguard Workerhyper-linked reference documentation or go through the header files in 28*2b949d04SAndroid Build Coastguard Workerxkbcommon/ for more details. 29*2b949d04SAndroid Build Coastguard Worker 30*2b949d04SAndroid Build Coastguard Worker## Code 31*2b949d04SAndroid Build Coastguard Worker 32*2b949d04SAndroid Build Coastguard WorkerBefore we can do anything interesting, we need a library context: 33*2b949d04SAndroid Build Coastguard Worker 34*2b949d04SAndroid Build Coastguard Worker~~~{.c} 35*2b949d04SAndroid Build Coastguard Worker #include <xkbcommon/xkbcommon.h> 36*2b949d04SAndroid Build Coastguard Worker 37*2b949d04SAndroid Build Coastguard Worker struct xkb_context *ctx; 38*2b949d04SAndroid Build Coastguard Worker 39*2b949d04SAndroid Build Coastguard Worker ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); 40*2b949d04SAndroid Build Coastguard Worker if (!ctx) <error> 41*2b949d04SAndroid Build Coastguard Worker~~~ 42*2b949d04SAndroid Build Coastguard Worker 43*2b949d04SAndroid Build Coastguard WorkerThe `xkb_context` contains the keymap include paths, the log level and 44*2b949d04SAndroid Build Coastguard Workerfunctions, and other general customizable administrativia. 45*2b949d04SAndroid Build Coastguard Worker 46*2b949d04SAndroid Build Coastguard WorkerNext we need to create a keymap, `xkb_keymap`. This is an immutable object 47*2b949d04SAndroid Build Coastguard Workerwhich contains all of the information about the keys, layouts, etc. There 48*2b949d04SAndroid Build Coastguard Workerare different ways to do this. 49*2b949d04SAndroid Build Coastguard Worker 50*2b949d04SAndroid Build Coastguard WorkerIf we are an evdev client, we have nothing to go by, so we need to ask 51*2b949d04SAndroid Build Coastguard Workerthe user for his/her keymap preferences (for example, an Icelandic 52*2b949d04SAndroid Build Coastguard Workerkeyboard with a Dvorak layout). The configuration format is commonly 53*2b949d04SAndroid Build Coastguard Workercalled RMLVO (Rules+Model+Layout+Variant+Options), the same format used 54*2b949d04SAndroid Build Coastguard Workerby the X server. With it, we can fill a struct called `xkb_rule_names`; 55*2b949d04SAndroid Build Coastguard Workerpassing `NULL` chooses the system's default. 56*2b949d04SAndroid Build Coastguard Worker 57*2b949d04SAndroid Build Coastguard Worker~~~{.c} 58*2b949d04SAndroid Build Coastguard Worker struct xkb_keymap *keymap; 59*2b949d04SAndroid Build Coastguard Worker /* Example RMLVO for Icelandic Dvorak. */ 60*2b949d04SAndroid Build Coastguard Worker struct xkb_rule_names names = { 61*2b949d04SAndroid Build Coastguard Worker .rules = NULL, 62*2b949d04SAndroid Build Coastguard Worker .model = "pc105", 63*2b949d04SAndroid Build Coastguard Worker .layout = "is", 64*2b949d04SAndroid Build Coastguard Worker .variant = "dvorak", 65*2b949d04SAndroid Build Coastguard Worker .options = "terminate:ctrl_alt_bksp" 66*2b949d04SAndroid Build Coastguard Worker }; 67*2b949d04SAndroid Build Coastguard Worker 68*2b949d04SAndroid Build Coastguard Worker keymap = xkb_keymap_new_from_names(ctx, &names, 69*2b949d04SAndroid Build Coastguard Worker XKB_KEYMAP_COMPILE_NO_FLAGS); 70*2b949d04SAndroid Build Coastguard Worker if (!keymap) <error> 71*2b949d04SAndroid Build Coastguard Worker~~~ 72*2b949d04SAndroid Build Coastguard Worker 73*2b949d04SAndroid Build Coastguard WorkerIf we are a Wayland client, the compositor gives us a string complete 74*2b949d04SAndroid Build Coastguard Workerwith a keymap. In this case, we can create the keymap object like this: 75*2b949d04SAndroid Build Coastguard Worker 76*2b949d04SAndroid Build Coastguard Worker~~~{.c} 77*2b949d04SAndroid Build Coastguard Worker /* From the wl_keyboard::keymap event. */ 78*2b949d04SAndroid Build Coastguard Worker const char *keymap_string = <...>; 79*2b949d04SAndroid Build Coastguard Worker struct xkb_keymap *keymap; 80*2b949d04SAndroid Build Coastguard Worker 81*2b949d04SAndroid Build Coastguard Worker keymap = xkb_keymap_new_from_string(ctx, keymap_string, 82*2b949d04SAndroid Build Coastguard Worker XKB_KEYMAP_FORMAT_TEXT_V1, 83*2b949d04SAndroid Build Coastguard Worker XKB_KEYMAP_COMPILE_NO_FLAGS); 84*2b949d04SAndroid Build Coastguard Worker if (!keymap) <error> 85*2b949d04SAndroid Build Coastguard Worker~~~ 86*2b949d04SAndroid Build Coastguard Worker 87*2b949d04SAndroid Build Coastguard WorkerIf we are an X11 client, we are better off getting the keymap from the 88*2b949d04SAndroid Build Coastguard WorkerX server directly. For this we need to choose the XInput device; here 89*2b949d04SAndroid Build Coastguard Workerwe will use the core keyboard device: 90*2b949d04SAndroid Build Coastguard Worker 91*2b949d04SAndroid Build Coastguard Worker~~~{.c} 92*2b949d04SAndroid Build Coastguard Worker #include <xkbcommon/xkbcommon-x11.h> 93*2b949d04SAndroid Build Coastguard Worker 94*2b949d04SAndroid Build Coastguard Worker xcb_connection_t *conn = <...>; 95*2b949d04SAndroid Build Coastguard Worker int32_t device_id; 96*2b949d04SAndroid Build Coastguard Worker 97*2b949d04SAndroid Build Coastguard Worker device_id = xkb_x11_get_core_keyboard_device_id(conn); 98*2b949d04SAndroid Build Coastguard Worker if (device_id == -1) <error> 99*2b949d04SAndroid Build Coastguard Worker 100*2b949d04SAndroid Build Coastguard Worker keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id, 101*2b949d04SAndroid Build Coastguard Worker XKB_KEYMAP_COMPILE_NO_FLAGS); 102*2b949d04SAndroid Build Coastguard Worker if (!keymap) <error> 103*2b949d04SAndroid Build Coastguard Worker~~~ 104*2b949d04SAndroid Build Coastguard Worker 105*2b949d04SAndroid Build Coastguard WorkerNow that we have the keymap, we are ready to handle the keyboard devices. 106*2b949d04SAndroid Build Coastguard WorkerFor each device, we create an `xkb_state`, which remembers things like which 107*2b949d04SAndroid Build Coastguard Workerkeyboard modifiers and LEDs are active: 108*2b949d04SAndroid Build Coastguard Worker 109*2b949d04SAndroid Build Coastguard Worker~~~{.c} 110*2b949d04SAndroid Build Coastguard Worker struct xkb_state *state; 111*2b949d04SAndroid Build Coastguard Worker 112*2b949d04SAndroid Build Coastguard Worker state = xkb_state_new(keymap); 113*2b949d04SAndroid Build Coastguard Worker if (!state) <error> 114*2b949d04SAndroid Build Coastguard Worker~~~ 115*2b949d04SAndroid Build Coastguard Worker 116*2b949d04SAndroid Build Coastguard WorkerFor X11/XCB clients, this is better: 117*2b949d04SAndroid Build Coastguard Worker 118*2b949d04SAndroid Build Coastguard Worker~~~{.c} 119*2b949d04SAndroid Build Coastguard Worker state = xkb_x11_state_new_from_device(keymap, conn, device_id); 120*2b949d04SAndroid Build Coastguard Worker if (!state) <error> 121*2b949d04SAndroid Build Coastguard Worker~~~ 122*2b949d04SAndroid Build Coastguard Worker 123*2b949d04SAndroid Build Coastguard WorkerWhen we have an `xkb_state` for a device, we can start handling key events 124*2b949d04SAndroid Build Coastguard Workerfrom it. Given a keycode for a key, we can get its keysym: 125*2b949d04SAndroid Build Coastguard Worker 126*2b949d04SAndroid Build Coastguard Worker~~~{.c} 127*2b949d04SAndroid Build Coastguard Worker <key event structure> event; 128*2b949d04SAndroid Build Coastguard Worker xkb_keycode_t keycode; 129*2b949d04SAndroid Build Coastguard Worker xkb_keysym_t keysym; 130*2b949d04SAndroid Build Coastguard Worker 131*2b949d04SAndroid Build Coastguard Worker keycode = event->keycode; 132*2b949d04SAndroid Build Coastguard Worker keysym = xkb_state_key_get_one_sym(state, keycode); 133*2b949d04SAndroid Build Coastguard Worker~~~ 134*2b949d04SAndroid Build Coastguard Worker 135*2b949d04SAndroid Build Coastguard WorkerWe can see which keysym we got, and get its name: 136*2b949d04SAndroid Build Coastguard Worker 137*2b949d04SAndroid Build Coastguard Worker~~~{.c} 138*2b949d04SAndroid Build Coastguard Worker char keysym_name[64]; 139*2b949d04SAndroid Build Coastguard Worker 140*2b949d04SAndroid Build Coastguard Worker if (keysym == XKB_KEY_Space) 141*2b949d04SAndroid Build Coastguard Worker <got a space> 142*2b949d04SAndroid Build Coastguard Worker 143*2b949d04SAndroid Build Coastguard Worker xkb_keysym_get_name(keysym, keysym_name, sizeof(keysym_name)); 144*2b949d04SAndroid Build Coastguard Worker~~~ 145*2b949d04SAndroid Build Coastguard Worker 146*2b949d04SAndroid Build Coastguard Workerlibxkbcommon also supports an extension to the classic XKB, whereby a 147*2b949d04SAndroid Build Coastguard Workersingle event can result in multiple keysyms. Here's how to use it: 148*2b949d04SAndroid Build Coastguard Worker 149*2b949d04SAndroid Build Coastguard Worker~~~{.c} 150*2b949d04SAndroid Build Coastguard Worker const xkb_keysym_t *keysyms; 151*2b949d04SAndroid Build Coastguard Worker int num_keysyms; 152*2b949d04SAndroid Build Coastguard Worker 153*2b949d04SAndroid Build Coastguard Worker num_keysyms = xkb_state_key_get_syms(state, keycode, &keysyms); 154*2b949d04SAndroid Build Coastguard Worker~~~ 155*2b949d04SAndroid Build Coastguard Worker 156*2b949d04SAndroid Build Coastguard WorkerWe can also get a UTF-8 string representation for this key: 157*2b949d04SAndroid Build Coastguard Worker 158*2b949d04SAndroid Build Coastguard Worker~~~{.c} 159*2b949d04SAndroid Build Coastguard Worker char *buffer; 160*2b949d04SAndroid Build Coastguard Worker int size; 161*2b949d04SAndroid Build Coastguard Worker 162*2b949d04SAndroid Build Coastguard Worker // First find the needed size; return value is the same as snprintf(3). 163*2b949d04SAndroid Build Coastguard Worker size = xkb_state_key_get_utf8(state, keycode, NULL, 0) + 1; 164*2b949d04SAndroid Build Coastguard Worker if (size <= 1) <nothing to do> 165*2b949d04SAndroid Build Coastguard Worker buffer = <allocate size bytes> 166*2b949d04SAndroid Build Coastguard Worker 167*2b949d04SAndroid Build Coastguard Worker xkb_state_key_get_utf8(state, keycode, buffer, size); 168*2b949d04SAndroid Build Coastguard Worker~~~ 169*2b949d04SAndroid Build Coastguard Worker 170*2b949d04SAndroid Build Coastguard WorkerOf course, we also need to keep the `xkb_state` up-to-date with the 171*2b949d04SAndroid Build Coastguard Workerkeyboard device, if we want to get the correct keysyms in the future. 172*2b949d04SAndroid Build Coastguard Worker 173*2b949d04SAndroid Build Coastguard WorkerIf we are an evdev client, we must let the library know whether a key 174*2b949d04SAndroid Build Coastguard Workeris pressed or released at any given time: 175*2b949d04SAndroid Build Coastguard Worker 176*2b949d04SAndroid Build Coastguard Worker~~~{.c} 177*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component changed; 178*2b949d04SAndroid Build Coastguard Worker 179*2b949d04SAndroid Build Coastguard Worker if (<key press>) 180*2b949d04SAndroid Build Coastguard Worker changed = xkb_state_update_key(state, keycode, XKB_KEY_DOWN); 181*2b949d04SAndroid Build Coastguard Worker else if (<key release>) 182*2b949d04SAndroid Build Coastguard Worker changed = xkb_state_update_key(state, keycode, XKB_KEY_UP); 183*2b949d04SAndroid Build Coastguard Worker~~~ 184*2b949d04SAndroid Build Coastguard Worker 185*2b949d04SAndroid Build Coastguard WorkerThe `changed` return value tells us exactly which parts of the state 186*2b949d04SAndroid Build Coastguard Workerhave changed. 187*2b949d04SAndroid Build Coastguard Worker 188*2b949d04SAndroid Build Coastguard WorkerIf it is a key-repeat event, we can ask the keymap what to do with it: 189*2b949d04SAndroid Build Coastguard Worker 190*2b949d04SAndroid Build Coastguard Worker~~~{.c} 191*2b949d04SAndroid Build Coastguard Worker if (<key repeat> && !xkb_keymap_key_repeats(keymap, keycode)) 192*2b949d04SAndroid Build Coastguard Worker <discard event> 193*2b949d04SAndroid Build Coastguard Worker~~~ 194*2b949d04SAndroid Build Coastguard Worker 195*2b949d04SAndroid Build Coastguard WorkerOn the other hand, if we are an X or Wayland client, the server already 196*2b949d04SAndroid Build Coastguard Workerdoes the hard work for us. It notifies us when the device's state 197*2b949d04SAndroid Build Coastguard Workerchanges, and we can simply use what it tells us (the necessary 198*2b949d04SAndroid Build Coastguard Workerinformation usually comes in a form of some "state changed" event): 199*2b949d04SAndroid Build Coastguard Worker 200*2b949d04SAndroid Build Coastguard Worker~~~{.c} 201*2b949d04SAndroid Build Coastguard Worker changed = xkb_state_update_mask(state, 202*2b949d04SAndroid Build Coastguard Worker event->depressed_mods, 203*2b949d04SAndroid Build Coastguard Worker event->latched_mods, 204*2b949d04SAndroid Build Coastguard Worker event->locked_mods, 205*2b949d04SAndroid Build Coastguard Worker event->depressed_layout, 206*2b949d04SAndroid Build Coastguard Worker event->latched_layout, 207*2b949d04SAndroid Build Coastguard Worker event->locked_layout); 208*2b949d04SAndroid Build Coastguard Worker~~~ 209*2b949d04SAndroid Build Coastguard Worker 210*2b949d04SAndroid Build Coastguard WorkerNow that we have an always-up-to-date `xkb_state`, we can examine it. 211*2b949d04SAndroid Build Coastguard WorkerFor example, we can check whether the Control modifier is active, or 212*2b949d04SAndroid Build Coastguard Workerwhether the Num Lock LED is active: 213*2b949d04SAndroid Build Coastguard Worker 214*2b949d04SAndroid Build Coastguard Worker~~~{.c} 215*2b949d04SAndroid Build Coastguard Worker if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, 216*2b949d04SAndroid Build Coastguard Worker XKB_STATE_MODS_EFFECTIVE) > 0) 217*2b949d04SAndroid Build Coastguard Worker <The Control modifier is active> 218*2b949d04SAndroid Build Coastguard Worker 219*2b949d04SAndroid Build Coastguard Worker if (xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) > 0) 220*2b949d04SAndroid Build Coastguard Worker <The Num Lock LED is active> 221*2b949d04SAndroid Build Coastguard Worker~~~ 222*2b949d04SAndroid Build Coastguard Worker 223*2b949d04SAndroid Build Coastguard WorkerAnd that's it! Eventually, we should free the objects we've created: 224*2b949d04SAndroid Build Coastguard Worker 225*2b949d04SAndroid Build Coastguard Worker~~~{.c} 226*2b949d04SAndroid Build Coastguard Worker xkb_state_unref(state); 227*2b949d04SAndroid Build Coastguard Worker xkb_keymap_unref(keymap); 228*2b949d04SAndroid Build Coastguard Worker xkb_context_unref(ctx); 229*2b949d04SAndroid Build Coastguard Worker~~~ 230