|
|
1.1 ! root 1: /* $Id: keyboard.c,v 1.6 2003/10/16 02:48:18 fredette Exp $ */ ! 2: ! 3: /* generic/keyboard.c - generic keyboard implementation support: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2003 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: #include <tme/common.h> ! 37: _TME_RCSID("$Id: keyboard.c,v 1.6 2003/10/16 02:48:18 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include <tme/generic/keyboard.h> ! 41: #include <tme/hash.h> ! 42: #include <tme/misc.h> ! 43: #include <stdlib.h> ! 44: ! 45: /* macros: */ ! 46: ! 47: /* the shortest possible time, in milliseconds, between two human ! 48: transitions on the same key: */ ! 49: #define TME_KEYBOARD_SHORTEST_DOUBLE_MSEC (80) ! 50: ! 51: /* input stage zero uses a slightly expanded set of event types: */ ! 52: #define TME_KEYBOARD_EVENT_IN0_RELEASE_USER (0) ! 53: #define TME_KEYBOARD_EVENT_IN0_PRESS_USER (1) ! 54: #define TME_KEYBOARD_EVENT_IN0_RELEASE_AUTO (2) ! 55: #define TME_KEYBOARD_EVENT_IN0_PRESS_AUTO (3) ! 56: #if TME_KEYBOARD_EVENT_RELEASE != TME_KEYBOARD_EVENT_IN0_RELEASE_USER ! 57: #error "TME_KEYBOARD_EVENT_RELEASE must be 0" ! 58: #endif ! 59: #if TME_KEYBOARD_EVENT_PRESS != TME_KEYBOARD_EVENT_IN0_PRESS_USER ! 60: #error "TME_KEYBOARD_EVENT_PRESS must be 1" ! 61: #endif ! 62: ! 63: /* this macro turns an input stage zero pressed value into the ! 64: corresponding release event type: */ ! 65: #define TME_KEYBOARD_IN0_RELEASE_EVENT(pressed) ((pressed) ^ 1) ! 66: ! 67: /* these macros evaluate to nonzero iff a keyval is pressed in the ! 68: different stages: */ ! 69: #define TME_KEYBOARD_PRESSED_IN0(keysym) \ ! 70: ((keysym)->tme_keysym_state_in0_pressed) ! 71: #define TME_KEYBOARD_PRESSED_IN1(keysym) \ ! 72: ((keysym)->tme_keysym_state_in1_keymode.tme_keymode_state_pressed) ! 73: #define _TME_KEYBOARD_PRESSED_IN2(keysym, prev) \ ! 74: ((keysym)->tme_keysym_state_in2_pressed \ ! 75: || (!(keysym)->tme_keysym_state_in2_released \ ! 76: && prev)) ! 77: #define TME_KEYBOARD_PRESSED_IN2(keysym) \ ! 78: _TME_KEYBOARD_PRESSED_IN2(keysym, TME_KEYBOARD_PRESSED_IN1(keysym)) ! 79: #define _TME_KEYBOARD_PRESSED_OUT0(keysym, prev)\ ! 80: ((keysym)->tme_keysym_state_out0_pressed \ ! 81: || (!(keysym)->tme_keysym_state_out0_released\ ! 82: && prev)) ! 83: #define TME_KEYBOARD_PRESSED_OUT0(keysym) \ ! 84: _TME_KEYBOARD_PRESSED_OUT0(keysym, TME_KEYBOARD_PRESSED_IN2(keysym)) ! 85: #define TME_KEYBOARD_PRESSED_OUT1(keycode) \ ! 86: ((keycode)->tme_keycode_state_keymode.tme_keymode_state_pressed) ! 87: ! 88: /* types: */ ! 89: ! 90: struct tme_keyboard_buffer_int; ! 91: struct tme_keysym_state; ! 92: ! 93: /* keymode state: */ ! 94: struct tme_keymode_state { ! 95: ! 96: /* keys that may be autorepeating are kept on a linked list: */ ! 97: struct tme_keymode_state *tme_keymode_state_next; ! 98: ! 99: /* the state for this keysym. technically, since output stage one ! 100: deals in keycodes, this really should be a void * and point to ! 101: the keysym state for input stage one, and point to the keycode ! 102: state for output stage one. ! 103: ! 104: however, avoiding the void * allows us to avoid some function ! 105: pointer casting, and in the output stage one case we don't care ! 106: which of the many keysyms that may map to the same keycode is ! 107: stored here - we just immediately grab the keycode state out of ! 108: that keysym: */ ! 109: struct tme_keysym_state *tme_keymode_state_keysym; ! 110: ! 111: /* the keymode mode: */ ! 112: int tme_keymode_state_mode; ! 113: ! 114: /* this is nonzero iff the key is pressed in the physical sense: */ ! 115: int tme_keymode_state_pressed; ! 116: ! 117: /* the last time this key was released: */ ! 118: tme_uint32_t tme_keymode_state_last_release; ! 119: ! 120: /* this is nonzero iff a genuine release should be ignored: */ ! 121: int tme_keymode_state_ignore_release; ! 122: }; ! 123: ! 124: /* a keymode stage: */ ! 125: struct tme_keymode_stage { ! 126: ! 127: /* the global keymode: */ ! 128: int tme_keymode_stage_global_mode; ! 129: ! 130: /* the list of keymode states for keys that must not autorepeat: */ ! 131: struct tme_keymode_state *tme_keymode_stage_no_autorepeats; ! 132: ! 133: /* the next stage: */ ! 134: int (*tme_keymode_stage_next) _TME_P((struct tme_keyboard_buffer_int *, ! 135: struct tme_keysym_state *, ! 136: tme_uint32_t)); ! 137: }; ! 138: ! 139: /* keycode state: */ ! 140: struct tme_keycode_state { ! 141: ! 142: /* the keycode: */ ! 143: tme_keyboard_keyval_t tme_keycode_state_keycode; ! 144: ! 145: /* the keycode keymode state: */ ! 146: struct tme_keymode_state tme_keycode_state_keymode; ! 147: }; ! 148: ! 149: /* keysym state. one of these is kept for every keysym controlled by ! 150: one or more input or output stages: */ ! 151: struct tme_keysym_state { ! 152: ! 153: /* this keysym: */ ! 154: tme_keyboard_keyval_t tme_keysym_state_keysym; ! 155: ! 156: /* input stage zero: */ ! 157: ! 158: /* if greater than TME_KEYBOARD_MODIFIER_NONE, this is the modifier ! 159: that this keysym is attached to in input stage zero: */ ! 160: int tme_keysym_state_in0_modifier; ! 161: ! 162: /* the keysym states for all keys attached to the same modifier in ! 163: input stage zero are kept on a linked list: */ ! 164: struct tme_keysym_state *tme_keysym_state_in0_modifier_next; ! 165: ! 166: /* this is nonzero iff the keysym is being pressed in input stage ! 167: zero. it's really either FALSE, or ! 168: TME_KEYBOARD_EVENT_IN0_PRESS_USER, or ! 169: TME_KEYBOARD_EVENT_IN0_PRESS_AUTO, which is why the last two are ! 170: nonzero: */ ! 171: unsigned int tme_keysym_state_in0_pressed; ! 172: ! 173: /* the last time this keysym was pressed in input stage zero. this ! 174: is a time in milliseconds: */ ! 175: tme_uint32_t tme_keysym_state_in0_press_time; ! 176: ! 177: /* input stage one: */ ! 178: ! 179: /* the input stage one keymode state: */ ! 180: struct tme_keymode_state tme_keysym_state_in1_keymode; ! 181: ! 182: /* input stage two: */ ! 183: ! 184: /* this is nonzero iff the keysym is being released in input stage ! 185: two: */ ! 186: unsigned int tme_keysym_state_in2_released; ! 187: ! 188: /* this is nonzero iff the keysym is being pressed in input stage ! 189: two: */ ! 190: unsigned int tme_keysym_state_in2_pressed; ! 191: ! 192: /* output stage zero: */ ! 193: ! 194: /* if non-NULL, this is the keycode that this keysym is mapped to in ! 195: output stage zero: */ ! 196: struct tme_keycode_state *tme_keysym_state_out0_keycode; ! 197: ! 198: /* if this keysym is not attached to any modifier on the output ! 199: stage zero, it may require that certain output side modifiers be ! 200: set or clear in order for the keycode to mean the given keysym: */ ! 201: tme_keyboard_modifiers_t tme_keysym_state_out0_modifiers_set; ! 202: tme_keyboard_modifiers_t tme_keysym_state_out0_modifiers_clear; ! 203: ! 204: /* iff greater than TME_KEYBOARD_MODIFIER_NONE, this is the modifier ! 205: that this keysym is attached to in output stage zero: */ ! 206: int tme_keysym_state_out0_modifier; ! 207: ! 208: /* the keysym states for all keys attached to the same modifier in ! 209: output stage zero are kept on a linked list: */ ! 210: struct tme_keysym_state *tme_keysym_state_out0_modifier_next; ! 211: ! 212: /* this is nonzero iff the keysym is being released in output stage ! 213: zero: */ ! 214: unsigned int tme_keysym_state_out0_released; ! 215: ! 216: /* this is nonzero iff the keysym is being pressed in output stage ! 217: zero: */ ! 218: unsigned int tme_keysym_state_out0_pressed; ! 219: ! 220: /* if this keysym is pressed in the output stage zero but required ! 221: output stage zero modifier changes to be so, this is the list of ! 222: those changes. since most keyboards generate the same keysym ! 223: using the same modifier(s), this list will usually be empty: */ ! 224: struct tme_keysym_state **tme_keysym_state_out0_keysyms; ! 225: unsigned int *tme_keysym_state_out0_press_flags; ! 226: ! 227: /* output stage one: */ ! 228: ! 229: /* this is nonzero iff the next release seen by output stage one ! 230: will not affect the output modifiers mask: */ ! 231: int tme_keysym_state_out1_ignore_release; ! 232: }; ! 233: ! 234: /* keyboard macros are necessary because it's almost certain that the ! 235: keyboard you want to emulate has keysyms that your keyboard doesn't ! 236: have. one keyboard macro takes a *sequence* of one or more pressed ! 237: keysyms to a *set* of one or more released and pressed keysyms. ! 238: ! 239: all keysym macros are kept in a single tree, where a single branch ! 240: represents the next keysym in the sequences for one or more macros. ! 241: ! 242: a node in the macros tree is active iff the keysyms on the path ! 243: from the root node have been pressed in sequence and remain ! 244: pressed. if there are any macros at all, the root node is always ! 245: active: */ ! 246: struct tme_keyboard_macro { ! 247: ! 248: /* a pointer up to our parent node, and the keysym on the branch ! 249: from our parent to us. for the root node, these are NULL and ! 250: TME_KEYBOARD_KEYVAL_UNDEF, respectively: */ ! 251: struct tme_keyboard_macro *tme_keyboard_macro_parent; ! 252: tme_keyboard_keyval_t tme_keyboard_macro_keysym; ! 253: ! 254: /* all active nodes are on a list. the root node is always active, ! 255: and it must be the last node on this list - making the is-active ! 256: test for all other nodes as simple as testing this pointer ! 257: against NULL: */ ! 258: struct tme_keyboard_macro *tme_keyboard_macro_active_next; ! 259: ! 260: /* non-leaf nodes branch out by keysym: */ ! 261: tme_hash_t tme_keyboard_macro_branches; ! 262: ! 263: /* leaf nodes contain the set of keysyms that the recognized ! 264: sequence maps to. in addition to presses of one or more new ! 265: keysyms, this will normally include releases of some or all of ! 266: the keysyms in the original sequence: */ ! 267: unsigned int tme_keyboard_macro_length; ! 268: struct tme_keysym_state **tme_keyboard_macro_keysyms; ! 269: unsigned int *tme_keyboard_macro_press_flags; ! 270: }; ! 271: ! 272: /* an internal keyboard buffer: */ ! 273: struct tme_keyboard_buffer_int { ! 274: ! 275: /* the public keyboard buffer. this must be first: */ ! 276: struct tme_keyboard_buffer tme_keyboard_buffer; ! 277: #define tme_keyboard_buffer_int_size tme_keyboard_buffer.tme_keyboard_buffer_size ! 278: #define tme_keyboard_buffer_int_head tme_keyboard_buffer.tme_keyboard_buffer_head ! 279: #define tme_keyboard_buffer_int_tail tme_keyboard_buffer.tme_keyboard_buffer_tail ! 280: #define tme_keyboard_buffer_int_events tme_keyboard_buffer.tme_keyboard_buffer_events ! 281: #define tme_keyboard_buffer_int_log_handle tme_keyboard_buffer.tme_keyboard_buffer_log_handle ! 282: ! 283: /* the keysyms state, common to all stages: */ ! 284: tme_hash_t tme_keyboard_buffer_int_keysyms_state; ! 285: ! 286: /* input stage zero: */ ! 287: ! 288: /* this is nonzero iff input stage zero has modifier information, ! 289: and it's actually the mask of modifiers that we have keysyms for: */ ! 290: unsigned int tme_keyboard_buffer_int_in0_have_modifiers; ! 291: ! 292: /* the lists of keysyms that are attached to input stage zero ! 293: modifiers: */ ! 294: struct tme_keysym_state *tme_keyboard_buffer_int_in0_modkeys[TME_KEYBOARD_MODIFIER_MAX + 1]; ! 295: ! 296: /* the current input stage zero modifiers mask: */ ! 297: tme_keyboard_modifiers_t tme_keyboard_buffer_int_in0_modifiers; ! 298: ! 299: /* the current input stage zero pressed keycodes, mapped to their ! 300: corresponding struct tme_keysym_states: */ ! 301: tme_hash_t tme_keyboard_buffer_int_in0_keycodes; ! 302: ! 303: /* input stage one: */ ! 304: ! 305: /* the input stage one keymode stage: */ ! 306: struct tme_keymode_stage tme_keyboard_buffer_int_in1_keymode_stage; ! 307: ! 308: /* input stage two: */ ! 309: ! 310: /* this is NULL iff input stage two is a passthrough, else this is ! 311: the list of active nodes in the input stage two keysym macros ! 312: tree: */ ! 313: struct tme_keyboard_macro *tme_keyboard_buffer_int_in2_macros_active; ! 314: ! 315: /* the root of the input stage two keysym macros tree: */ ! 316: struct tme_keyboard_macro tme_keyboard_buffer_int_in2_macros_root; ! 317: ! 318: /* output stage zero: */ ! 319: ! 320: /* this is nonzero iff output stage zero is just a passthrough: */ ! 321: unsigned int tme_keyboard_buffer_int_out0_passthrough; ! 322: ! 323: /* the output stage zero keycodes: */ ! 324: tme_hash_t tme_keyboard_buffer_int_out0_keycodes; ! 325: ! 326: /* this is nonzero iff the output stage zero lock modifier is to be ! 327: treated as caps lock: */ ! 328: int tme_keyboard_buffer_int_out0_lock_is_caps; ! 329: ! 330: /* any output stage zero modifier that the Num_Lock keysym is ! 331: attached to: */ ! 332: int tme_keyboard_buffer_int_out0_mod_num_lock; ! 333: ! 334: /* the lists of keysyms that are output stage zero modifiers: */ ! 335: struct tme_keysym_state *tme_keyboard_buffer_int_out0_modkeys[TME_KEYBOARD_MODIFIER_MAX + 1]; ! 336: ! 337: /* the current output stage zero modifiers mask: */ ! 338: tme_keyboard_modifiers_t tme_keyboard_buffer_int_out0_modifiers; ! 339: ! 340: /* output stage one: */ ! 341: ! 342: /* the output stage one keymode stage: */ ! 343: struct tme_keymode_stage tme_keyboard_buffer_int_out1_keymode_stage; ! 344: }; ! 345: ! 346: /* prototypes: */ ! 347: static int _tme_keyboard_buffer_in2 _TME_P((struct tme_keyboard_buffer_int *, ! 348: struct tme_keysym_state *, ! 349: tme_uint32_t)); ! 350: static int _tme_keyboard_buffer_out1_bottom _TME_P((struct tme_keyboard_buffer_int *, ! 351: struct tme_keysym_state *, ! 352: tme_uint32_t)); ! 353: ! 354: /* this is for debugging only: */ ! 355: #if 0 ! 356: static void ! 357: _tme_keyboard_debug(const struct tme_keyboard_buffer_int *buffer, ! 358: const char *stage, ! 359: tme_keyboard_keyval_t keyval, ! 360: int is_press, ! 361: tme_uint32_t event_time) ! 362: { ! 363: struct tme_log_handle *handle; ! 364: const char *string; ! 365: extern const char *_tme_gtk_keyboard_keyval_name _TME_P((tme_keyboard_keyval_t)); ! 366: ! 367: handle = buffer->tme_keyboard_buffer_int_log_handle; ! 368: if (handle == NULL) { ! 369: return; ! 370: } ! 371: ! 372: string = _tme_gtk_keyboard_keyval_name(keyval); ! 373: if (string == NULL) { ! 374: string = "???"; ! 375: } ! 376: ! 377: tme_log(handle, 100, TME_OK, ! 378: (handle, ! 379: "%s event: time %lu key %lu (%s) %s", ! 380: stage, ! 381: (unsigned long) event_time, ! 382: (unsigned long) keyval, ! 383: string, ! 384: (is_press ! 385: ? "press" ! 386: : "release"))); ! 387: } ! 388: #else ! 389: #define _tme_keyboard_debug(b, s, k, p, t) \ ! 390: do { } while(/* CONSTCOND */ 0) ! 391: #endif ! 392: ! 393: /* this creates a new keyboard buffer: */ ! 394: struct tme_keyboard_buffer * ! 395: tme_keyboard_buffer_new(unsigned int size) ! 396: { ! 397: struct tme_keyboard_buffer_int *buffer; ! 398: struct tme_keymode_stage *stage; ! 399: struct tme_keyboard_macro *root; ! 400: int modifier; ! 401: ! 402: /* round the buffer size up to a power of two: */ ! 403: if (size & (size - 1)) { ! 404: do { ! 405: size &= (size - 1); ! 406: } while (size & (size - 1)); ! 407: size <<= 1; ! 408: } ! 409: ! 410: /* allocate the buffer: */ ! 411: buffer = tme_new0(struct tme_keyboard_buffer_int, 1); ! 412: ! 413: /* set the buffer size: */ ! 414: buffer->tme_keyboard_buffer_int_size = size; ! 415: ! 416: /* set the head and tail pointers: */ ! 417: buffer->tme_keyboard_buffer_int_head = 0; ! 418: buffer->tme_keyboard_buffer_int_tail = 0; ! 419: ! 420: /* allocate the buffer events: */ ! 421: buffer->tme_keyboard_buffer_int_events ! 422: = tme_new(struct tme_keyboard_event, size); ! 423: ! 424: /* for now there is no log handle: */ ! 425: buffer->tme_keyboard_buffer_int_log_handle = NULL; ! 426: ! 427: /* create the common keysyms state: */ ! 428: buffer->tme_keyboard_buffer_int_keysyms_state ! 429: = tme_hash_new(tme_direct_hash, ! 430: tme_direct_compare, ! 431: (tme_hash_data_t) NULL); ! 432: ! 433: /* input stage zero begins with no modifiers: */ ! 434: buffer->tme_keyboard_buffer_int_in0_have_modifiers = FALSE; ! 435: ! 436: /* initialize the input stage zero modifier keys lists: */ ! 437: for (modifier = 0; ! 438: modifier <= TME_KEYBOARD_MODIFIER_MAX; ! 439: modifier++) { ! 440: buffer->tme_keyboard_buffer_int_in0_modkeys[modifier] = NULL; ! 441: } ! 442: ! 443: /* initialize the input stage zero modifiers mask: */ ! 444: buffer->tme_keyboard_buffer_int_in0_modifiers = 0; ! 445: ! 446: /* initialize the input stage one keycodes hash: */ ! 447: buffer->tme_keyboard_buffer_int_in0_keycodes ! 448: = tme_hash_new(tme_direct_hash, ! 449: tme_direct_compare, ! 450: (tme_hash_data_t) NULL); ! 451: ! 452: /* initialize the input stage one keymode stage: */ ! 453: stage = &buffer->tme_keyboard_buffer_int_in1_keymode_stage; ! 454: stage->tme_keymode_stage_global_mode = 0; ! 455: stage->tme_keymode_stage_no_autorepeats = NULL; ! 456: stage->tme_keymode_stage_next = _tme_keyboard_buffer_in2; ! 457: ! 458: /* input stage two begins with no macros, so not even the root of ! 459: the macros tree is active: */ ! 460: buffer->tme_keyboard_buffer_int_in2_macros_active = NULL; ! 461: ! 462: /* create the root of the input stage two keysym macros tree: */ ! 463: root = &buffer->tme_keyboard_buffer_int_in2_macros_root; ! 464: root->tme_keyboard_macro_parent = NULL; ! 465: root->tme_keyboard_macro_keysym = TME_KEYBOARD_KEYVAL_UNDEF; ! 466: root->tme_keyboard_macro_active_next = NULL; ! 467: root->tme_keyboard_macro_branches ! 468: = tme_hash_new(tme_direct_hash, ! 469: tme_direct_compare, ! 470: (tme_hash_data_t) NULL); ! 471: ! 472: /* output stage zero begins as a passthrough: */ ! 473: buffer->tme_keyboard_buffer_int_out0_passthrough = TRUE; ! 474: ! 475: /* initialize the output stage zero keycodes: */ ! 476: buffer->tme_keyboard_buffer_int_out0_keycodes ! 477: = tme_hash_new(tme_direct_hash, ! 478: tme_direct_compare, ! 479: (tme_hash_data_t) NULL); ! 480: ! 481: /* the output stage zero lock modifier is assumed to be a Shift lock: */ ! 482: buffer->tme_keyboard_buffer_int_out0_lock_is_caps ! 483: = FALSE; ! 484: ! 485: /* initialize the output stage zero modifier that the Num_Lock ! 486: keysym is attached to: */ ! 487: buffer->tme_keyboard_buffer_int_out0_mod_num_lock ! 488: = TME_KEYBOARD_MODIFIER_NONE; ! 489: ! 490: /* initialize the output stage zero modifier keys lists: */ ! 491: for (modifier = 0; ! 492: modifier <= TME_KEYBOARD_MODIFIER_MAX; ! 493: modifier++) { ! 494: buffer->tme_keyboard_buffer_int_out0_modkeys[modifier] = NULL; ! 495: } ! 496: ! 497: /* initialize the output stage zero modifiers mask: */ ! 498: buffer->tme_keyboard_buffer_int_out0_modifiers = 0; ! 499: ! 500: /* initialize the output stage one keymode stage: */ ! 501: stage = &buffer->tme_keyboard_buffer_int_out1_keymode_stage; ! 502: stage->tme_keymode_stage_global_mode = 0; ! 503: stage->tme_keymode_stage_no_autorepeats = NULL; ! 504: stage->tme_keymode_stage_next = _tme_keyboard_buffer_out1_bottom; ! 505: ! 506: /* done: */ ! 507: return (&buffer->tme_keyboard_buffer); ! 508: } ! 509: ! 510: /* this destroys an entry in the common keysyms state: */ ! 511: static void ! 512: _tme_keysym_state_destroy(tme_hash_data_t __keysym, ! 513: tme_hash_data_t _keysym, ! 514: void *_junk) ! 515: { ! 516: struct tme_keysym_state *keysym; ! 517: ! 518: /* recover the keysym state: */ ! 519: keysym = (struct tme_keysym_state *) _keysym; ! 520: ! 521: /* if this keysym state has output stage zero keysym changes, free ! 522: them: */ ! 523: if (keysym->tme_keysym_state_out0_keysyms != NULL) { ! 524: tme_free(keysym->tme_keysym_state_out0_keysyms); ! 525: tme_free(keysym->tme_keysym_state_out0_press_flags); ! 526: } ! 527: ! 528: /* free the state itself: */ ! 529: tme_free(keysym); ! 530: } ! 531: ! 532: /* this recursively destroys the input stage two keysym macros tree: */ ! 533: static void ! 534: _tme_keyboard_macro_destroy(tme_hash_data_t _keysym, ! 535: tme_hash_data_t _macro, ! 536: void *_junk) ! 537: { ! 538: struct tme_keyboard_macro *macro; ! 539: ! 540: /* get this macro: */ ! 541: macro = (struct tme_keyboard_macro *) _macro; ! 542: ! 543: /* if this is a leaf node: */ ! 544: if (macro->tme_keyboard_macro_branches == NULL) { ! 545: ! 546: /* free the keysyms and flags: */ ! 547: tme_free(macro->tme_keyboard_macro_keysyms); ! 548: tme_free(macro->tme_keyboard_macro_press_flags); ! 549: } ! 550: ! 551: /* otherwise, recurse: */ ! 552: else { ! 553: tme_hash_foreach(macro->tme_keyboard_macro_branches, ! 554: _tme_keyboard_macro_destroy, ! 555: NULL); ! 556: tme_hash_destroy(macro->tme_keyboard_macro_branches); ! 557: } ! 558: ! 559: /* free this tree node: */ ! 560: tme_free(macro); ! 561: } ! 562: ! 563: /* this destroys an entry in the output stage zero keycodes state: */ ! 564: static void ! 565: _tme_keycode_state_destroy(tme_hash_data_t __keycode, ! 566: tme_hash_data_t _keycode, ! 567: void *_junk) ! 568: { ! 569: struct tme_keycode_state *keycode; ! 570: ! 571: /* recover the keycode state: */ ! 572: keycode = (struct tme_keycode_state *) _keycode; ! 573: ! 574: /* free the state itself: */ ! 575: tme_free(keycode); ! 576: } ! 577: ! 578: /* this destroys a keyboard buffer: */ ! 579: void ! 580: tme_keyboard_buffer_destroy(struct tme_keyboard_buffer *_buffer) ! 581: { ! 582: struct tme_keyboard_buffer_int *buffer; ! 583: ! 584: /* recover our data structure: */ ! 585: buffer = (struct tme_keyboard_buffer_int *) _buffer; ! 586: ! 587: /* free the events: */ ! 588: tme_free(buffer->tme_keyboard_buffer_int_events); ! 589: ! 590: /* destroy the common keysyms state: */ ! 591: tme_hash_foreach(buffer->tme_keyboard_buffer_int_keysyms_state, ! 592: _tme_keysym_state_destroy, ! 593: NULL); ! 594: tme_hash_destroy(buffer->tme_keyboard_buffer_int_keysyms_state); ! 595: ! 596: /* destroy the input stage two keysym macros tree: */ ! 597: tme_hash_foreach(buffer->tme_keyboard_buffer_int_in2_macros_root.tme_keyboard_macro_branches, ! 598: _tme_keyboard_macro_destroy, ! 599: NULL); ! 600: tme_hash_destroy(buffer->tme_keyboard_buffer_int_in2_macros_root.tme_keyboard_macro_branches); ! 601: ! 602: /* destroy the output stage zero keycodes: */ ! 603: tme_hash_foreach(buffer->tme_keyboard_buffer_int_out0_keycodes, ! 604: _tme_keycode_state_destroy, ! 605: NULL); ! 606: tme_hash_destroy(buffer->tme_keyboard_buffer_int_out0_keycodes); ! 607: ! 608: /* destroy the buffer itself: */ ! 609: tme_free(buffer); ! 610: } ! 611: ! 612: /* this gets the state for a keysym, creating a new state if one ! 613: doesn't exists yet: */ ! 614: static struct tme_keysym_state * ! 615: _tme_keysym_state_get(struct tme_keyboard_buffer_int *buffer, ! 616: tme_keyboard_keyval_t _keysym) ! 617: { ! 618: struct tme_keysym_state *keysym; ! 619: ! 620: /* look up the state for this keysym: */ ! 621: keysym ! 622: = ((struct tme_keysym_state *) ! 623: tme_hash_lookup(buffer->tme_keyboard_buffer_int_keysyms_state, ! 624: (tme_hash_data_t) _keysym)); ! 625: ! 626: /* if the state doesn't exist, allocate it: */ ! 627: if (keysym == NULL) { ! 628: keysym = tme_new0(struct tme_keysym_state, 1); ! 629: ! 630: /* initialize all fields that might not be properly initialized as ! 631: all-bits-zero: */ ! 632: keysym->tme_keysym_state_keysym = _keysym; ! 633: keysym->tme_keysym_state_in0_modifier = TME_KEYBOARD_MODIFIER_NONE; ! 634: keysym->tme_keysym_state_in1_keymode.tme_keymode_state_keysym = keysym; ! 635: keysym->tme_keysym_state_out0_keycode = NULL; ! 636: keysym->tme_keysym_state_out0_modifier = TME_KEYBOARD_MODIFIER_NONE; ! 637: keysym->tme_keysym_state_out0_keysyms = NULL; ! 638: keysym->tme_keysym_state_out0_press_flags = NULL; ! 639: ! 640: /* insert this state into the hash: */ ! 641: tme_hash_insert(buffer->tme_keyboard_buffer_int_keysyms_state, ! 642: (tme_hash_data_t) _keysym, ! 643: (tme_hash_data_t) keysym); ! 644: } ! 645: ! 646: /* done: */ ! 647: return (keysym); ! 648: } ! 649: ! 650: /* this changes the set of keysyms that are attached to an input stage ! 651: zero modifier: */ ! 652: int ! 653: tme_keyboard_buffer_in_modifier(struct tme_keyboard_buffer *_buffer, ! 654: int modifier, ! 655: const tme_keyboard_keyval_t *modkeys) ! 656: { ! 657: struct tme_keyboard_buffer_int *buffer; ! 658: struct tme_keysym_state *mod_keysym, **_mod_keysym; ! 659: tme_keyboard_keyval_t keysym; ! 660: ! 661: /* recover our data structure: */ ! 662: buffer = (struct tme_keyboard_buffer_int *) _buffer; ! 663: ! 664: /* this must be a valid modifier: */ ! 665: assert (modifier > TME_KEYBOARD_MODIFIER_NONE ! 666: && modifier <= TME_KEYBOARD_MODIFIER_MAX); ! 667: ! 668: /* remove all currently attached keysyms from this modifier: */ ! 669: for (mod_keysym = buffer->tme_keyboard_buffer_int_in0_modkeys[modifier]; ! 670: mod_keysym != NULL; ! 671: mod_keysym = mod_keysym->tme_keysym_state_in0_modifier_next) { ! 672: mod_keysym->tme_keysym_state_in0_modifier ! 673: = TME_KEYBOARD_MODIFIER_NONE; ! 674: } ! 675: ! 676: /* attach all of these new keysyms to this modifier: */ ! 677: _mod_keysym = &buffer->tme_keyboard_buffer_int_in0_modkeys[modifier]; ! 678: for (; (keysym = *(modkeys++)) != TME_KEYBOARD_KEYVAL_UNDEF; ) { ! 679: mod_keysym = _tme_keysym_state_get(buffer, keysym); ! 680: mod_keysym->tme_keysym_state_in0_modifier = modifier; ! 681: *_mod_keysym = mod_keysym; ! 682: _mod_keysym = &mod_keysym->tme_keysym_state_in0_modifier_next; ! 683: } ! 684: *_mod_keysym = NULL; ! 685: ! 686: /* input stage zero now has modifier information: */ ! 687: buffer->tme_keyboard_buffer_int_in0_have_modifiers ! 688: |= (1 << modifier); ! 689: ! 690: return (TME_OK); ! 691: } ! 692: ! 693: /* this changes a keysym's input stage one keymode: */ ! 694: int ! 695: tme_keyboard_buffer_in_mode(struct tme_keyboard_buffer *_buffer, ! 696: tme_keyboard_keyval_t _keysym, int mode) ! 697: { ! 698: struct tme_keyboard_buffer_int *buffer; ! 699: struct tme_keysym_state *keysym; ! 700: ! 701: /* recover our data structure: */ ! 702: buffer = (struct tme_keyboard_buffer_int *) _buffer; ! 703: ! 704: /* there's no such thing as a global input keymode: */ ! 705: assert (_keysym != TME_KEYBOARD_KEYVAL_UNDEF); ! 706: ! 707: /* TME_KEYBOARD_MODE_UNLOCK and TME_KEYBOARD_MODE_LOCK cannot be ! 708: combined with any other bits: */ ! 709: if ((mode ! 710: & (TME_KEYBOARD_MODE_UNLOCK ! 711: | TME_KEYBOARD_MODE_LOCK)) ! 712: && (mode ! 713: & (mode - 1))) { ! 714: return (EINVAL); ! 715: } ! 716: ! 717: /* none of the TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS, ! 718: TME_KEYBOARD_MODE_FLAG_NO_RELEASES, and ! 719: TME_KEYBOARD_MODE_FLAG_LOCK_SOFT flags can be set ! 720: without TME_KEYBOARD_MODE_PASSTHROUGH: */ ! 721: if ((mode ! 722: & (TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS ! 723: | TME_KEYBOARD_MODE_FLAG_NO_RELEASES ! 724: | TME_KEYBOARD_MODE_FLAG_LOCK_SOFT)) ! 725: && !(mode ! 726: & TME_KEYBOARD_MODE_PASSTHROUGH)) { ! 727: return (EINVAL); ! 728: } ! 729: ! 730: /* you cannot specify that an input key must not release, or ! 731: that it soft locks: */ ! 732: if (mode ! 733: & (TME_KEYBOARD_MODE_FLAG_NO_RELEASES ! 734: | TME_KEYBOARD_MODE_FLAG_LOCK_SOFT)) { ! 735: return (EINVAL); ! 736: } ! 737: ! 738: /* look up this keysym and set the input stage one mode: */ ! 739: keysym = _tme_keysym_state_get(buffer, _keysym); ! 740: keysym->tme_keysym_state_in1_keymode.tme_keymode_state_mode = mode; ! 741: return (TME_OK); ! 742: } ! 743: ! 744: /* this adds an input stage two keysym macro: */ ! 745: int ! 746: tme_keyboard_buffer_in_macro(struct tme_keyboard_buffer *_buffer, ! 747: const tme_keyboard_keyval_t *keysyms_lhs, ! 748: const tme_keyboard_keyval_t *keysyms_rhs) ! 749: { ! 750: struct tme_keyboard_buffer_int *buffer; ! 751: unsigned int count_lhs, count_rhs; ! 752: unsigned int keysym_i, keysym_j, keysym_count; ! 753: tme_keyboard_keyval_t keysym; ! 754: struct tme_keysym_state **keysyms; ! 755: unsigned int *press_flags; ! 756: int rc; ! 757: struct tme_keyboard_macro *macro, *macro_next; ! 758: ! 759: /* recover our data structure: */ ! 760: buffer = (struct tme_keyboard_buffer_int *) _buffer; ! 761: ! 762: /* count the number of keysyms on both sides: */ ! 763: for (count_lhs = 0; ! 764: keysyms_lhs[count_lhs] != TME_KEYBOARD_KEYVAL_UNDEF; ! 765: count_lhs++); ! 766: for (count_rhs = 0; ! 767: keysyms_rhs[count_rhs] != TME_KEYBOARD_KEYVAL_UNDEF; ! 768: count_rhs++); ! 769: ! 770: /* there must be some left-hand side and some right-hand side: */ ! 771: if (count_lhs == 0 ! 772: || count_rhs == 0) { ! 773: return (EINVAL); ! 774: } ! 775: ! 776: /* create the final keysyms and press-flags arrays for the macro. any ! 777: keysym on the left hand side that is also on the right hand side ! 778: becomes a press, else a release, and any keysym on the right hand ! 779: side that isn't on the left hand side becomes a press: */ ! 780: keysyms = tme_new(struct tme_keysym_state *, count_lhs + count_rhs); ! 781: press_flags = tme_new(unsigned int, count_lhs + count_rhs); ! 782: keysym_count = 0; ! 783: for (keysym_i = 0; ! 784: keysym_i < count_lhs; ! 785: keysym_i++) { ! 786: keysym = keysyms_lhs[keysym_i]; ! 787: ! 788: /* see if this keysym is on the right hand side: */ ! 789: for (keysym_j = 0; ! 790: keysym_j < count_rhs; ! 791: keysym_j++) { ! 792: if (keysym == keysyms_rhs[keysym_j]) { ! 793: break; ! 794: } ! 795: } ! 796: ! 797: /* set this keysym and press-flags: */ ! 798: keysyms[keysym_count] = _tme_keysym_state_get(buffer, keysym); ! 799: press_flags[keysym_count] = (keysym_j < count_rhs); ! 800: keysym_count++; ! 801: } ! 802: for (keysym_j = 0; ! 803: keysym_j < count_rhs; ! 804: keysym_j++) { ! 805: keysym = keysyms_rhs[keysym_j]; ! 806: ! 807: /* see if this keysym is on the left hand side: */ ! 808: for (keysym_i = 0; ! 809: keysym_i < count_lhs; ! 810: keysym_i++) { ! 811: if (keysym == keysyms_lhs[keysym_i]) { ! 812: break; ! 813: } ! 814: } ! 815: ! 816: /* set this keysym and press-flags: */ ! 817: if (keysym_i == count_lhs) { ! 818: keysyms[keysym_count] = _tme_keysym_state_get(buffer, keysym); ! 819: press_flags[keysym_count] = TRUE; ! 820: keysym_count++; ! 821: } ! 822: } ! 823: ! 824: /* the last keysym in any macro's right hand side must be a press: */ ! 825: if (!press_flags[keysym_count - 1]) { ! 826: tme_free(keysyms); ! 827: tme_free(press_flags); ! 828: return (EINVAL); ! 829: } ! 830: ! 831: /* add this keysym macro to the macros tree. this macro's sequence ! 832: (i.e., its left-hand side) cannot be strictly longer, or strictly ! 833: shorter, or the same as any existing macro's sequence: */ ! 834: macro = &buffer->tme_keyboard_buffer_int_in2_macros_root; ! 835: rc = TME_OK; ! 836: for (keysym_i = 0; ! 837: ; ! 838: keysym_i++) { ! 839: ! 840: /* if we handled all left-hand side keysyms: */ ! 841: if (keysym_i == count_lhs) { ! 842: ! 843: /* if this node is already a non-leaf node, then this macro's ! 844: sequence is strictly shorter than an existing macro's ! 845: sequence: */ ! 846: if (macro->tme_keyboard_macro_branches != NULL) { ! 847: rc = EEXIST; ! 848: } ! 849: ! 850: /* otherwise, if this node is already a leaf node, then this ! 851: macro's sequence is the same as an existing macro's sequence: */ ! 852: else if (macro->tme_keyboard_macro_length > 0) { ! 853: rc = EEXIST; ! 854: } ! 855: ! 856: /* stop no matter what: */ ! 857: break; ! 858: } ! 859: ! 860: /* if this node has no branch set: */ ! 861: if (macro->tme_keyboard_macro_branches == NULL) { ! 862: ! 863: /* if this node is already a leaf node, then this macro's ! 864: sequence is strictly longer than an existing macro's ! 865: sequence: */ ! 866: if (macro->tme_keyboard_macro_length > 0) { ! 867: rc = EEXIST; ! 868: break; ! 869: } ! 870: ! 871: /* otherwise, create a branch set for this node: */ ! 872: macro->tme_keyboard_macro_branches ! 873: = tme_hash_new(tme_direct_hash, ! 874: tme_direct_compare, ! 875: (tme_hash_data_t) NULL); ! 876: } ! 877: ! 878: /* get the keysym: */ ! 879: keysym = keysyms_lhs[keysym_i]; ! 880: ! 881: /* look up this keysym in the branch set for this node: */ ! 882: macro_next ! 883: = ((struct tme_keyboard_macro *) ! 884: tme_hash_lookup(macro->tme_keyboard_macro_branches, (tme_hash_data_t) keysym)); ! 885: ! 886: /* if this keysym is a new branch, create a new macros tree node: */ ! 887: if (macro_next == NULL) { ! 888: macro_next = tme_new0(struct tme_keyboard_macro, 1); ! 889: macro_next->tme_keyboard_macro_parent = macro; ! 890: macro_next->tme_keyboard_macro_keysym = keysym; ! 891: tme_hash_insert(macro->tme_keyboard_macro_branches, ! 892: (tme_hash_data_t) keysym, ! 893: (tme_hash_data_t) macro_next); ! 894: } ! 895: ! 896: /* advance in the tree: */ ! 897: macro = macro_next; ! 898: } ! 899: ! 900: /* if this sequence couldn't be added to the sequences tree: */ ! 901: if (rc != TME_OK) { ! 902: tme_free(keysyms); ! 903: tme_free(press_flags); ! 904: return (rc); ! 905: } ! 906: ! 907: /* finish this leaf node in the macros tree: */ ! 908: macro->tme_keyboard_macro_length = keysym_count; ! 909: macro->tme_keyboard_macro_keysyms = keysyms; ! 910: macro->tme_keyboard_macro_press_flags = press_flags; ! 911: ! 912: /* if this is the first keysym macro added, set the root of the ! 913: keysym macros tree as active, making input stage two no longer a ! 914: passthrough: */ ! 915: if (buffer->tme_keyboard_buffer_int_in2_macros_active ! 916: == NULL) { ! 917: buffer->tme_keyboard_buffer_int_in2_macros_active ! 918: = &buffer->tme_keyboard_buffer_int_in2_macros_root; ! 919: } ! 920: ! 921: return (TME_OK); ! 922: } ! 923: ! 924: /* this adds a single output stage zero keysym map entry: */ ! 925: int ! 926: tme_keyboard_buffer_out_map(struct tme_keyboard_buffer *_buffer, ! 927: _tme_const struct tme_keyboard_map *map) ! 928: { ! 929: struct tme_keyboard_buffer_int *buffer; ! 930: struct tme_keysym_state *keysym; ! 931: struct tme_keycode_state *keycode; ! 932: struct tme_keymode_state *keymode; ! 933: int modifier; ! 934: tme_keyboard_modifiers_t modifiers_set, modifiers_clear; ! 935: ! 936: /* recover our data structure: */ ! 937: buffer = (struct tme_keyboard_buffer_int *) _buffer; ! 938: ! 939: /* the keysym must be defined: */ ! 940: assert (map->tme_keyboard_map_keysym ! 941: != TME_KEYBOARD_KEYVAL_UNDEF); ! 942: ! 943: /* get the state for this keysym: */ ! 944: keysym = _tme_keysym_state_get(buffer, map->tme_keyboard_map_keysym); ! 945: ! 946: /* this keysym must not already have an output side keycode: */ ! 947: if (keysym->tme_keysym_state_out0_keycode != NULL) { ! 948: return (EEXIST); ! 949: } ! 950: ! 951: /* lookup this keycode: */ ! 952: keycode ! 953: = ((struct tme_keycode_state *) ! 954: tme_hash_lookup(buffer->tme_keyboard_buffer_int_out0_keycodes, ! 955: (tme_hash_data_t) map->tme_keyboard_map_keycode)); ! 956: ! 957: /* if this keycode is new, allocate, initialize and add a structure ! 958: for it: */ ! 959: if (keycode == NULL) { ! 960: ! 961: /* allocate the keycode state: */ ! 962: keycode = tme_new0(struct tme_keycode_state, 1); ! 963: ! 964: /* initialize any parts of the keycode state that might not be ! 965: properly initialized as all-bits-zero. note that the keysym ! 966: stored in the keycode keymode state is the first keysym mapped ! 967: to the keycode: */ ! 968: keycode->tme_keycode_state_keycode = map->tme_keyboard_map_keycode; ! 969: keymode = &keycode->tme_keycode_state_keymode; ! 970: keymode->tme_keymode_state_keysym = keysym; ! 971: ! 972: /* add the keycode structure: */ ! 973: tme_hash_insert(buffer->tme_keyboard_buffer_int_out0_keycodes, ! 974: (tme_hash_data_t) map->tme_keyboard_map_keycode, ! 975: (tme_hash_data_t) keycode); ! 976: } ! 977: ! 978: /* set this keycode on this keysym: */ ! 979: keysym->tme_keysym_state_out0_keycode = keycode; ! 980: ! 981: /* if this keysym is attached to an output side modifier: */ ! 982: modifier = map->tme_keyboard_map_modifier; ! 983: if (modifier != TME_KEYBOARD_MODIFIER_NONE) { ! 984: ! 985: /* attach this keysym to the output side modifier: */ ! 986: keysym->tme_keysym_state_out0_modifier ! 987: = modifier; ! 988: keysym->tme_keysym_state_out0_modifier_next ! 989: = buffer->tme_keyboard_buffer_int_out0_modkeys[modifier]; ! 990: buffer->tme_keyboard_buffer_int_out0_modkeys[modifier] ! 991: = keysym; ! 992: ! 993: /* dispatch on any special keysym note: */ ! 994: switch (map->tme_keyboard_map_keysym_note) { ! 995: default: assert(FALSE); ! 996: case TME_KEYBOARD_KEYSYM_NOTE_UNDEF: ! 997: break; ! 998: case TME_KEYBOARD_KEYSYM_NOTE_CAPS_LOCK: ! 999: if (modifier == TME_KEYBOARD_MODIFIER_LOCK) { ! 1000: buffer->tme_keyboard_buffer_int_out0_lock_is_caps = TRUE; ! 1001: } ! 1002: break; ! 1003: case TME_KEYBOARD_KEYSYM_NOTE_SHIFT_LOCK: ! 1004: break; ! 1005: case TME_KEYBOARD_KEYSYM_NOTE_NUM_LOCK: ! 1006: buffer->tme_keyboard_buffer_int_out0_mod_num_lock = modifier; ! 1007: break; ! 1008: } ! 1009: ! 1010: /* this keysym cannot require any output side modifiers to be set ! 1011: or clear: */ ! 1012: assert (map->tme_keyboard_map_modifiers_set == 0 ! 1013: && map->tme_keyboard_map_modifiers_clear == 0); ! 1014: } ! 1015: ! 1016: /* remember the output stage zero modifiers that must be set or ! 1017: clear for this mapping to work: */ ! 1018: modifiers_set = map->tme_keyboard_map_modifiers_set; ! 1019: modifiers_clear = map->tme_keyboard_map_modifiers_clear; ! 1020: assert ((modifiers_set & modifiers_clear) == 0); ! 1021: ! 1022: /* if this keysym is lowercase, it also requires the shift modifier ! 1023: to be clear: */ ! 1024: if (modifiers_clear ! 1025: & (1 << TME_KEYBOARD_MODIFIER_LOCK)) { ! 1026: modifiers_clear ! 1027: |= (1 << TME_KEYBOARD_MODIFIER_SHIFT); ! 1028: } ! 1029: ! 1030: keysym->tme_keysym_state_out0_modifiers_set = modifiers_set; ! 1031: keysym->tme_keysym_state_out0_modifiers_clear = modifiers_clear; ! 1032: ! 1033: /* output stage zero is no longer a passthrough: */ ! 1034: buffer->tme_keyboard_buffer_int_out0_passthrough = FALSE; ! 1035: ! 1036: return (TME_OK); ! 1037: } ! 1038: ! 1039: /* this changes a keycode's output stage one mode: */ ! 1040: int ! 1041: tme_keyboard_buffer_out_mode(struct tme_keyboard_buffer *_buffer, ! 1042: tme_keyboard_keyval_t _keycode, int mode) ! 1043: { ! 1044: struct tme_keyboard_buffer_int *buffer; ! 1045: struct tme_keycode_state *keycode; ! 1046: ! 1047: /* recover our data structure: */ ! 1048: buffer = (struct tme_keyboard_buffer_int *) _buffer; ! 1049: ! 1050: /* TME_KEYBOARD_MODE_UNLOCK and TME_KEYBOARD_MODE_LOCK cannot be ! 1051: combined with any other bits: */ ! 1052: if ((mode ! 1053: & (TME_KEYBOARD_MODE_UNLOCK ! 1054: | TME_KEYBOARD_MODE_LOCK)) ! 1055: && (mode ! 1056: & (mode - 1))) { ! 1057: return (EINVAL); ! 1058: } ! 1059: ! 1060: /* none of the TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS, ! 1061: TME_KEYBOARD_MODE_FLAG_NO_RELEASES, and ! 1062: TME_KEYBOARD_MODE_FLAG_LOCK_SOFT flags can be set ! 1063: without TME_KEYBOARD_MODE_PASSTHROUGH: */ ! 1064: if ((mode ! 1065: & (TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS ! 1066: | TME_KEYBOARD_MODE_FLAG_NO_RELEASES ! 1067: | TME_KEYBOARD_MODE_FLAG_LOCK_SOFT)) ! 1068: && !(mode ! 1069: & TME_KEYBOARD_MODE_PASSTHROUGH)) { ! 1070: return (EINVAL); ! 1071: } ! 1072: ! 1073: /* you cannot specify that an output key must be unlocked: */ ! 1074: if (mode & TME_KEYBOARD_MODE_UNLOCK) { ! 1075: return (EINVAL); ! 1076: } ! 1077: ! 1078: /* if we are setting the mode on a particular keycode: */ ! 1079: if (_keycode != TME_KEYBOARD_KEYVAL_UNDEF) { ! 1080: keycode ! 1081: = ((struct tme_keycode_state *) ! 1082: tme_hash_lookup(buffer->tme_keyboard_buffer_int_out0_keycodes, ! 1083: (tme_hash_data_t) _keycode)); ! 1084: if (keycode == NULL) { ! 1085: return (ENOENT); ! 1086: } ! 1087: keycode->tme_keycode_state_keymode.tme_keymode_state_mode = mode; ! 1088: } ! 1089: ! 1090: /* otherwise, we are setting the mode on the whole keyboard: */ ! 1091: else { ! 1092: ! 1093: /* you can't set TME_KEYBOARD_MODE_GLOBAL at the global level: */ ! 1094: if (mode == TME_KEYBOARD_MODE_GLOBAL) { ! 1095: return (EINVAL); ! 1096: } ! 1097: ! 1098: /* set the output stage one global mode: */ ! 1099: buffer->tme_keyboard_buffer_int_out1_keymode_stage ! 1100: .tme_keymode_stage_global_mode = mode; ! 1101: } ! 1102: ! 1103: return (TME_OK); ! 1104: } ! 1105: ! 1106: /* this fixes the keyboard's output stage zero modifiers when they get ! 1107: out of sync with the emulated software reading the output keyboard: */ ! 1108: tme_keyboard_modifiers_t ! 1109: tme_keyboard_buffer_out_modifiers(struct tme_keyboard_buffer *_buffer, ! 1110: tme_keyboard_modifiers_t modifiers_clear, ! 1111: tme_keyboard_modifiers_t modifiers_set) ! 1112: { ! 1113: struct tme_keyboard_buffer_int *buffer; ! 1114: ! 1115: /* recover our data structure: */ ! 1116: buffer = (struct tme_keyboard_buffer_int *) _buffer; ! 1117: ! 1118: /* update the modifiers: */ ! 1119: return (buffer->tme_keyboard_buffer_int_out0_modifiers ! 1120: = ((buffer->tme_keyboard_buffer_int_out0_modifiers ! 1121: & ~modifiers_clear) ! 1122: | modifiers_set)); ! 1123: } ! 1124: ! 1125: /* this parses a single keysym macro: */ ! 1126: int ! 1127: tme_keyboard_parse_macro(const char *string, ! 1128: tme_keyboard_keysym_lookup_t keysym_lookup, ! 1129: void *keysym_lookup_private, ! 1130: tme_keyboard_keyval_t **_keysyms_lhs, ! 1131: tme_keyboard_keyval_t **_keysyms_rhs) ! 1132: { ! 1133: char **tokens; ! 1134: int tokens_count, equals_token; ! 1135: int token_i; ! 1136: tme_keyboard_keyval_t keysym, *keysyms_lhs, *keysyms_rhs; ! 1137: struct tme_keyboard_lookup lookup; ! 1138: unsigned int count_lhs, count_rhs; ! 1139: int rc; ! 1140: ! 1141: /* tokenize this line: */ ! 1142: tokens = tme_misc_tokenize(string, '#', &tokens_count); ! 1143: keysyms_lhs = tme_new(tme_keyboard_keyval_t, tokens_count); ! 1144: keysyms_rhs = tme_new(tme_keyboard_keyval_t, tokens_count); ! 1145: count_lhs = 0; ! 1146: count_rhs = 0; ! 1147: ! 1148: /* start the lookup structure: */ ! 1149: lookup.tme_keyboard_lookup_context_length = 0; ! 1150: lookup.tme_keyboard_lookup_context = NULL; ! 1151: ! 1152: /* all of the tokens must be valid keysyms, except for a single ! 1153: mandatory "=" token, which must not be the first or last token: */ ! 1154: equals_token = -1; ! 1155: rc = TME_OK; ! 1156: for (token_i = 0; ! 1157: token_i < tokens_count; ! 1158: token_i++) { ! 1159: ! 1160: /* check for an "=" token: */ ! 1161: if (!strcmp(tokens[token_i], "=")) { ! 1162: if (equals_token >= 0 ! 1163: || token_i == 0 ! 1164: || token_i + 1 == tokens_count) { ! 1165: rc = EINVAL; ! 1166: break; ! 1167: } ! 1168: equals_token = token_i; ! 1169: continue; ! 1170: } ! 1171: ! 1172: /* a token on the left hand side must be a keysym that the ! 1173: caller can generate directly: */ ! 1174: if (equals_token < 0) { ! 1175: ! 1176: /* get the keysym for this token: */ ! 1177: lookup.tme_keyboard_lookup_string = tokens[token_i]; ! 1178: lookup.tme_keyboard_lookup_flags = TME_KEYBOARD_LOOKUP_FLAG_OK_DIRECT; ! 1179: keysym = (*keysym_lookup)(keysym_lookup_private, &lookup); ! 1180: if (keysym == TME_KEYBOARD_KEYVAL_UNDEF) { ! 1181: rc = ENOENT; ! 1182: break; ! 1183: } ! 1184: keysyms_lhs[count_lhs++] = keysym; ! 1185: } ! 1186: ! 1187: /* otherwise, a token on the right hand side is either a keysym ! 1188: that the caller can generate directly, or the caller must ! 1189: be able to allocate a unique value for it: */ ! 1190: else { ! 1191: ! 1192: /* get the keysym for this token: */ ! 1193: lookup.tme_keyboard_lookup_string = tokens[token_i]; ! 1194: lookup.tme_keyboard_lookup_flags = (TME_KEYBOARD_LOOKUP_FLAG_OK_DIRECT ! 1195: | TME_KEYBOARD_LOOKUP_FLAG_OK_ALLOC ! 1196: | TME_KEYBOARD_LOOKUP_FLAG_OK_ALLOC_NOW); ! 1197: keysym = (*keysym_lookup)(keysym_lookup_private, &lookup); ! 1198: assert (keysym != TME_KEYBOARD_KEYVAL_UNDEF); ! 1199: keysyms_rhs[count_rhs++] = keysym; ! 1200: } ! 1201: } ! 1202: ! 1203: /* if this macro didn't parse correctly: */ ! 1204: if (rc != TME_OK) { ! 1205: tme_free_string_array(tokens, -1); ! 1206: tme_free(keysyms_lhs); ! 1207: tme_free(keysyms_rhs); ! 1208: return (rc); ! 1209: } ! 1210: ! 1211: /* finish the sides of the macro: */ ! 1212: keysyms_lhs[count_lhs] = TME_KEYBOARD_KEYVAL_UNDEF; ! 1213: keysyms_rhs[count_rhs] = TME_KEYBOARD_KEYVAL_UNDEF; ! 1214: ! 1215: /* done: */ ! 1216: *_keysyms_lhs = keysyms_lhs; ! 1217: *_keysyms_rhs = keysyms_rhs; ! 1218: tme_free_string_array(tokens, -1); ! 1219: return (TME_OK); ! 1220: } ! 1221: ! 1222: /* this parses a single keysym map entry: */ ! 1223: int ! 1224: tme_keyboard_parse_map(const char *string, ! 1225: tme_keyboard_keysym_lookup_t keysym_lookup, ! 1226: void *keysym_lookup_private, ! 1227: struct tme_keyboard_map *map) ! 1228: { ! 1229: char **tokens, *p1, c; ! 1230: int tokens_count; ! 1231: int token_i; ! 1232: tme_keyboard_keyval_t keycode; ! 1233: int modifier, attached_modifier; ! 1234: tme_keyboard_modifiers_t modifiers_set, modifiers_clear; ! 1235: struct tme_keyboard_lookup lookup; ! 1236: int rc; ! 1237: ! 1238: /* tokenize this line: */ ! 1239: tokens = tme_misc_tokenize(string, '#', &tokens_count); ! 1240: rc = TME_OK; ! 1241: ! 1242: /* there must be at least three tokens. the second token must be an ! 1243: equals sign, and the third token must be an integer that isn't ! 1244: TME_KEYBOARD_KEYVAL_UNDEF: */ ! 1245: if (tokens_count < 3 ! 1246: || strcmp(tokens[1], "=") ! 1247: || ((keycode = strtoul(tokens[2], &p1, 0)) ! 1248: == TME_KEYBOARD_KEYVAL_UNDEF) ! 1249: || p1 == tokens[2] ! 1250: || *p1 != '\0') { ! 1251: rc = EINVAL; ! 1252: } ! 1253: ! 1254: /* any tokens after the third must all be modifier names: */ ! 1255: else { ! 1256: attached_modifier = TME_KEYBOARD_MODIFIER_NONE; ! 1257: modifiers_set = 0; ! 1258: modifiers_clear = 0; ! 1259: for (token_i = 3; ! 1260: token_i < tokens_count; ! 1261: token_i++) { ! 1262: ! 1263: /* a token might be prefixed with '+' or '!': */ ! 1264: p1 = tokens[token_i]; ! 1265: c = *p1; ! 1266: if (c == '+' ! 1267: || c == '!') { ! 1268: p1++; ! 1269: } ! 1270: ! 1271: /* turn this token into a real modifier: */ ! 1272: if (!strcmp(p1, "shift")) { ! 1273: modifier = TME_KEYBOARD_MODIFIER_SHIFT; ! 1274: } ! 1275: else if (!strcmp(p1, "lock")) { ! 1276: modifier = TME_KEYBOARD_MODIFIER_LOCK; ! 1277: } ! 1278: else if (!strcmp(p1, "control")) { ! 1279: modifier = TME_KEYBOARD_MODIFIER_CONTROL; ! 1280: } ! 1281: else if (!strcmp(p1, "mod1")) { ! 1282: modifier = TME_KEYBOARD_MODIFIER_MOD1; ! 1283: } ! 1284: else if (!strcmp(p1, "mod2")) { ! 1285: modifier = TME_KEYBOARD_MODIFIER_MOD2; ! 1286: } ! 1287: else if (!strcmp(p1, "mod3")) { ! 1288: modifier = TME_KEYBOARD_MODIFIER_MOD3; ! 1289: } ! 1290: else if (!strcmp(p1, "mod4")) { ! 1291: modifier = TME_KEYBOARD_MODIFIER_MOD4; ! 1292: } ! 1293: else if (!strcmp(p1, "mod5")) { ! 1294: modifier = TME_KEYBOARD_MODIFIER_MOD5; ! 1295: } ! 1296: else { ! 1297: rc = EINVAL; ! 1298: break; ! 1299: } ! 1300: ! 1301: /* if a modifier is prefixed with '+', it must be the only ! 1302: modifier token in the map entry, and it indicates that the ! 1303: keycode is attached to that modifier in this map: */ ! 1304: if (c == '+') { ! 1305: ! 1306: /* if this is not the only modifier token in the map entry: */ ! 1307: if (tokens_count != 4) { ! 1308: rc = EINVAL; ! 1309: break; ! 1310: } ! 1311: ! 1312: attached_modifier = modifier; ! 1313: } ! 1314: ! 1315: /* otherwise, if a modifier name is prefixed with '!', this ! 1316: modifier must be clear for this keycode to mean this keysym: */ ! 1317: else if (c == '!') { ! 1318: modifiers_clear |= (1 << modifier); ! 1319: } ! 1320: ! 1321: /* otherwise, this modifier must be set for this keycode to mean ! 1322: this keysym: */ ! 1323: else { ! 1324: modifiers_set |= (1 << modifier); ! 1325: } ! 1326: } ! 1327: ! 1328: /* the modifiers that must be set and the modifiers that must be ! 1329: clear cannot overlap: */ ! 1330: if (modifiers_set & modifiers_clear) { ! 1331: rc = EINVAL; ! 1332: } ! 1333: ! 1334: /* if no error has been encountered yet: */ ! 1335: if (rc == TME_OK) { ! 1336: ! 1337: /* make the keyboard map entry. we very deliberately set all ! 1338: bytes not allocated to structure members to all-bits-zero, so ! 1339: that identical keysym contexts truly are identical: */ ! 1340: memset(map, 0, sizeof(*map)); ! 1341: map->tme_keyboard_map_keycode = keycode; ! 1342: map->tme_keyboard_map_modifier = attached_modifier; ! 1343: map->tme_keyboard_map_modifiers_set = modifiers_set; ! 1344: map->tme_keyboard_map_modifiers_clear = modifiers_clear; ! 1345: ! 1346: /* take note of a special keysym: */ ! 1347: if (!strcmp(tokens[0], "Caps_Lock")) { ! 1348: map->tme_keyboard_map_keysym_note ! 1349: = TME_KEYBOARD_KEYSYM_NOTE_CAPS_LOCK; ! 1350: } ! 1351: else if (!strcmp(tokens[0], "Shift_Lock")) { ! 1352: map->tme_keyboard_map_keysym_note ! 1353: = TME_KEYBOARD_KEYSYM_NOTE_SHIFT_LOCK; ! 1354: } ! 1355: else if (!strcmp(tokens[0], "Num_Lock")) { ! 1356: map->tme_keyboard_map_keysym_note ! 1357: = TME_KEYBOARD_KEYSYM_NOTE_NUM_LOCK; ! 1358: } ! 1359: else { ! 1360: map->tme_keyboard_map_keysym_note ! 1361: = TME_KEYBOARD_KEYSYM_NOTE_UNDEF; ! 1362: } ! 1363: ! 1364: /* the caller must be able to either directly generate this ! 1365: keysym or have allocated a value for it already (because a ! 1366: macro was previously added than can generate it). if neither ! 1367: is true, the lookup function must return ! 1368: TME_KEYBOARD_KEYVAL_UNDEF, but this function still does not ! 1369: fail. it is up to the caller to not add a map entry with an ! 1370: undefined keysym: */ ! 1371: lookup.tme_keyboard_lookup_string ! 1372: = tokens[0]; ! 1373: lookup.tme_keyboard_lookup_flags ! 1374: = (TME_KEYBOARD_LOOKUP_FLAG_OK_DIRECT ! 1375: | TME_KEYBOARD_LOOKUP_FLAG_OK_ALLOC); ! 1376: lookup.tme_keyboard_lookup_context_length ! 1377: = sizeof(*map); ! 1378: lookup.tme_keyboard_lookup_context ! 1379: = (tme_uint8_t *) map; ! 1380: map->tme_keyboard_map_keysym ! 1381: = (*keysym_lookup)(keysym_lookup_private, &lookup); ! 1382: } ! 1383: } ! 1384: ! 1385: /* free the tokens: */ ! 1386: tme_free_string_array(tokens, -1); ! 1387: ! 1388: /* return the parsed map: */ ! 1389: return (rc); ! 1390: } ! 1391: ! 1392: /* this adds an event to the event buffer: */ ! 1393: static int ! 1394: _tme_keyboard_buffer_copyin(struct tme_keyboard_buffer_int *buffer, ! 1395: _tme_const struct tme_keyboard_event *event) ! 1396: { ! 1397: unsigned int buffer_head, buffer_size_mask; ! 1398: ! 1399: buffer_head = buffer->tme_keyboard_buffer_int_head; ! 1400: buffer_size_mask = buffer->tme_keyboard_buffer_int_size - 1; ! 1401: ! 1402: /* if the buffer is full: */ ! 1403: if (((buffer_head + 1) & buffer_size_mask) ! 1404: == buffer->tme_keyboard_buffer_int_tail) { ! 1405: return (EAGAIN); ! 1406: } ! 1407: ! 1408: /* put this event into the buffer: */ ! 1409: buffer->tme_keyboard_buffer_int_events[buffer_head] ! 1410: = *event; ! 1411: ! 1412: /* advance the head: */ ! 1413: buffer->tme_keyboard_buffer_int_head ! 1414: = (buffer_head + 1) & buffer_size_mask; ! 1415: ! 1416: return (TME_OK); ! 1417: } ! 1418: ! 1419: /* this adds a difference to an event time, avoiding a result of ! 1420: TME_KEYBOARD_EVENT_TIME_UNDEF: */ ! 1421: static tme_uint32_t ! 1422: _tme_keyboard_event_time_diff(tme_uint32_t event_time, ! 1423: tme_int32_t diff) ! 1424: { ! 1425: event_time += (tme_uint32_t) diff; ! 1426: if (event_time == TME_KEYBOARD_EVENT_TIME_UNDEF) { ! 1427: assert (diff != 0); ! 1428: event_time += (diff < 0 ? -1 : 1); ! 1429: } ! 1430: return (event_time); ! 1431: } ! 1432: ! 1433: /* this subtracts event_time1 from event_time0, handling the wrapping ! 1434: of the tme_uint32_t milliseconds values as best as possible: */ ! 1435: static tme_int32_t ! 1436: _tme_keyboard_event_time_subtract(tme_uint32_t event_time0, ! 1437: tme_uint32_t event_time1) ! 1438: { ! 1439: tme_uint32_t event_time0_less_least; ! 1440: tme_uint32_t event_time_diff_unwrapped; ! 1441: tme_uint32_t event_time_diff_wrapped; ! 1442: ! 1443: /* if the two times are equal: */ ! 1444: if (event_time0 == event_time1) { ! 1445: return (0); ! 1446: } ! 1447: ! 1448: /* calculate the unwrapped and wrapped differences between the ! 1449: two times: */ ! 1450: if (event_time0 < event_time1) { ! 1451: event_time_diff_unwrapped = event_time1 - event_time0; ! 1452: event_time_diff_wrapped = 0 - event_time_diff_unwrapped; ! 1453: } ! 1454: else { ! 1455: event_time_diff_unwrapped = event_time0 - event_time1; ! 1456: event_time_diff_wrapped = 0 - event_time_diff_unwrapped; ! 1457: } ! 1458: ! 1459: /* calculate the event time that is the most in the past without ! 1460: being confused as being later than event_time0: */ ! 1461: event_time0_less_least ! 1462: = (event_time0 - (((tme_uint32_t) -1) >> 1)); ! 1463: ! 1464: /* if event_time0_less_least is literally greater than event_time0, ! 1465: the event time space that represents "less than event_time0" is ! 1466: not a single region in the tme_uint32_t space: */ ! 1467: if (event_time0_less_least < event_time0) { ! 1468: return ((event_time0_less_least <= event_time1 ! 1469: && event_time1 < event_time0) ! 1470: /* event_time1 is less than event_time0: */ ! 1471: ? event_time_diff_unwrapped ! 1472: /* event_time1 is greater than event_time0: */ ! 1473: : (event_time1 > event_time0 ! 1474: ? 0 - event_time_diff_unwrapped ! 1475: : 0 - event_time_diff_wrapped)); ! 1476: } ! 1477: ! 1478: /* otherwise, the event time space that represents "less than ! 1479: event_time0" is two regions in the tme_uint32_t space: */ ! 1480: else { ! 1481: return ((event_time0_less_least <= event_time1 ! 1482: || event_time1 < event_time0) ! 1483: /* event_time1 is less than event_time0: */ ! 1484: ? (event_time1 < event_time0 ! 1485: ? event_time_diff_unwrapped ! 1486: : event_time_diff_wrapped) ! 1487: /* event_time1 is greater than event_time0: */ ! 1488: : 0 - event_time_diff_unwrapped); ! 1489: } ! 1490: } ! 1491: ! 1492: /* this runs a keymode stage. this is used for input stage one, ! 1493: and output stage one. roughly, a keymode stage tries to ! 1494: guarantee that a key has a specific press/release behavior ! 1495: (or "mode") for later stages. the particular modes are described ! 1496: in the case below: */ ! 1497: static int ! 1498: _tme_keymode_stage(struct tme_keyboard_buffer_int *buffer, ! 1499: struct tme_keymode_stage *stage, ! 1500: struct tme_keymode_state *keymode, ! 1501: int is_press, ! 1502: tme_uint32_t event_time) ! 1503: { ! 1504: struct tme_keymode_state **_auto_keymode, *auto_keymode; ! 1505: int pressed_old, mode; ! 1506: int rc; ! 1507: ! 1508: /* check all keys on the no-autorepeats list: */ ! 1509: for (_auto_keymode = &stage->tme_keymode_stage_no_autorepeats; ! 1510: (auto_keymode = *_auto_keymode) != NULL; ) { ! 1511: ! 1512: /* if the time of the last release from the earlier stages is ! 1513: undefined, that means that the last event from the earlier ! 1514: stages was a press: */ ! 1515: if (auto_keymode->tme_keymode_state_last_release ! 1516: == TME_KEYBOARD_EVENT_TIME_UNDEF) { ! 1517: ! 1518: /* if the key we're checking happens to be the key that the ! 1519: earlier stages are calling us for: */ ! 1520: if (auto_keymode == keymode) { ! 1521: ! 1522: /* this must be a release on this key: */ ! 1523: assert (!is_press); ! 1524: ! 1525: /* set the release time on this key: */ ! 1526: auto_keymode->tme_keymode_state_last_release = event_time; ! 1527: ! 1528: /* we've taken care of this call: */ ! 1529: keymode = NULL; ! 1530: } ! 1531: } ! 1532: ! 1533: /* otherwise, the last event from the earlier stages was a release. ! 1534: if enough time has elapsed since then without a press from ! 1535: earlier stages: */ ! 1536: else if (_tme_keyboard_event_time_subtract(event_time, ! 1537: auto_keymode->tme_keymode_state_last_release) ! 1538: > TME_KEYBOARD_SHORTEST_DOUBLE_MSEC) { ! 1539: ! 1540: /* now we're sure that the key has genuinely released. ! 1541: remove this key from the autorepeats list: */ ! 1542: *_auto_keymode = auto_keymode->tme_keymode_state_next; ! 1543: auto_keymode->tme_keymode_state_next = NULL; ! 1544: ! 1545: /* if we're supposed to ignore the genuine release: */ ! 1546: if (auto_keymode->tme_keymode_state_ignore_release) { ! 1547: auto_keymode->tme_keymode_state_ignore_release = FALSE; ! 1548: } ! 1549: ! 1550: /* otherwise, we're not supposed to ignore the genuine release: */ ! 1551: else { ! 1552: ! 1553: /* flip the pressed state of the key: */ ! 1554: auto_keymode->tme_keymode_state_pressed ! 1555: = !auto_keymode->tme_keymode_state_pressed; ! 1556: ! 1557: /* if this key is now pressed, or if we're allowed to ! 1558: pass releases, run the next stage: */ ! 1559: mode = auto_keymode->tme_keymode_state_mode; ! 1560: if (mode == TME_KEYBOARD_MODE_GLOBAL) { ! 1561: mode = stage->tme_keymode_stage_global_mode; ! 1562: } ! 1563: if (auto_keymode->tme_keymode_state_pressed ! 1564: || !(mode ! 1565: & TME_KEYBOARD_MODE_FLAG_NO_RELEASES)) { ! 1566: rc = (*stage->tme_keymode_stage_next) ! 1567: (buffer, ! 1568: auto_keymode->tme_keymode_state_keysym, ! 1569: _tme_keyboard_event_time_diff(event_time, -1)); ! 1570: assert (rc == TME_OK); ! 1571: } ! 1572: } ! 1573: ! 1574: /* continue now - by removing this key from the autorepeats ! 1575: list we've already advanced our position in the list for ! 1576: the next iteration: */ ! 1577: continue; ! 1578: } ! 1579: ! 1580: /* otherwise, if the key we're checking happens to be the key that ! 1581: the earlier stages are calling us for: */ ! 1582: else if (auto_keymode == keymode) { ! 1583: ! 1584: /* this must be a press on this key: */ ! 1585: assert (is_press); ! 1586: ! 1587: /* now we're sure that this key is autorepeating. clear ! 1588: the last-release time: */ ! 1589: auto_keymode->tme_keymode_state_last_release ! 1590: = TME_KEYBOARD_EVENT_TIME_UNDEF; ! 1591: ! 1592: /* we've taken care of this call: */ ! 1593: keymode = NULL; ! 1594: } ! 1595: ! 1596: /* continue: */ ! 1597: _auto_keymode = &auto_keymode->tme_keymode_state_next; ! 1598: } ! 1599: ! 1600: /* return now if we already finished processing this event: */ ! 1601: if (keymode == NULL) { ! 1602: return (TME_OK); ! 1603: } ! 1604: ! 1605: /* get this key's mode: */ ! 1606: mode = keymode->tme_keymode_state_mode; ! 1607: if (mode == TME_KEYBOARD_MODE_GLOBAL) { ! 1608: mode = stage->tme_keymode_stage_global_mode; ! 1609: } ! 1610: ! 1611: /* remember if this key was pressed in this stage before: */ ! 1612: pressed_old = keymode->tme_keymode_state_pressed; ! 1613: ! 1614: /* unlock mode unlocks a key by turning every transition into a ! 1615: press transition and a release transition. think of a Caps Lock ! 1616: key on an input keyboard that *physically* locks down when you ! 1617: press it down - this is a nice property, because there's no ! 1618: mistaking that when you get a key press event, you know the key ! 1619: is both physically and *semantically* down until you get a key ! 1620: release, at which time you know just the opposite. ! 1621: ! 1622: however, this is a best case. many keyboards have Caps Lock, Num ! 1623: Lock, and other keys where their semantic pressed/release state ! 1624: doesn't match their physical pressed/release state. to make ! 1625: everything uniform, we need to bring the best-case keyboards down ! 1626: to the worst-case level: */ ! 1627: if (mode == TME_KEYBOARD_MODE_UNLOCK) { ! 1628: ! 1629: /* we must not have this key as pressed: */ ! 1630: assert (!pressed_old); ! 1631: ! 1632: /* press this key and run the next stage: */ ! 1633: keymode->tme_keymode_state_pressed = TRUE; ! 1634: rc = (*stage->tme_keymode_stage_next) ! 1635: (buffer, ! 1636: keymode->tme_keymode_state_keysym, ! 1637: _tme_keyboard_event_time_diff(event_time, -1)); ! 1638: assert (rc == TME_OK); ! 1639: ! 1640: /* release this key, and make sure the next stage ! 1641: gets run at the end of this function: */ ! 1642: keymode->tme_keymode_state_pressed = FALSE; ! 1643: pressed_old = TRUE; ! 1644: } ! 1645: ! 1646: /* lock mode makes the key lock in the physical sense, like the ! 1647: best-case Caps Lock described above. since our events from ! 1648: earlier stages are worst-case, we need to ignore autorepeats, and ! 1649: each press/release pair must toggle our notion of whether or not ! 1650: the key is physically pressed: */ ! 1651: else if (mode == TME_KEYBOARD_MODE_LOCK) { ! 1652: ! 1653: /* this must be a press: */ ! 1654: assert (is_press); ! 1655: ! 1656: /* put this key on the no-autorepeats list: */ ! 1657: keymode->tme_keymode_state_last_release ! 1658: = TME_KEYBOARD_EVENT_TIME_UNDEF; ! 1659: keymode->tme_keymode_state_next ! 1660: = stage->tme_keymode_stage_no_autorepeats; ! 1661: stage->tme_keymode_stage_no_autorepeats = keymode; ! 1662: ! 1663: /* if we have the key as pressed (locked): */ ! 1664: if (pressed_old) { ! 1665: ! 1666: /* don't ignore the genuine release, when it is determined to ! 1667: have happened. if this mode has ! 1668: TME_KEYBOARD_MODE_FLAG_NO_RELEASES set, the genuine release ! 1669: code will handle it then: */ ! 1670: keymode->tme_keymode_state_ignore_release = FALSE; ! 1671: } ! 1672: ! 1673: /* otherwise, we have the key as released (unlocked): */ ! 1674: else { ! 1675: ! 1676: /* press this key: */ ! 1677: keymode->tme_keymode_state_pressed = TRUE; ! 1678: ! 1679: /* ignore the genuine release, when it is determined ! 1680: to have happened: */ ! 1681: keymode->tme_keymode_state_ignore_release = TRUE; ! 1682: } ! 1683: } ! 1684: ! 1685: /* passthrough mode generally passes events through: */ ! 1686: else { ! 1687: ! 1688: assert (!pressed_old != !is_press); ! 1689: ! 1690: /* if this is a press: */ ! 1691: if (is_press) { ! 1692: ! 1693: /* press this key: */ ! 1694: keymode->tme_keymode_state_pressed = TRUE; ! 1695: ! 1696: /* if we must not pass through autorepeats: */ ! 1697: if (mode & TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS) { ! 1698: ! 1699: /* put this key on the no-autorepeats list: */ ! 1700: keymode->tme_keymode_state_last_release ! 1701: = TME_KEYBOARD_EVENT_TIME_UNDEF; ! 1702: keymode->tme_keymode_state_next ! 1703: = stage->tme_keymode_stage_no_autorepeats; ! 1704: stage->tme_keymode_stage_no_autorepeats = keymode; ! 1705: ! 1706: /* don't ignore the genuine release, when it is ! 1707: determined to have happened. if this mode has ! 1708: TME_KEYBOARD_MODE_FLAG_NO_RELEASES set, the ! 1709: genuine release code will handle it then: */ ! 1710: keymode->tme_keymode_state_ignore_release = FALSE; ! 1711: } ! 1712: } ! 1713: ! 1714: /* otherwise, this is a release: */ ! 1715: else { ! 1716: ! 1717: /* release this key: */ ! 1718: keymode->tme_keymode_state_pressed = FALSE; ! 1719: ! 1720: /* if this mode has TME_KEYBOARD_MODE_FLAG_NO_RELEASES set, ! 1721: we'll handle it below when we go to run the next stage: */ ! 1722: } ! 1723: } ! 1724: ! 1725: /* stop processing this event now if the key's pressed state ! 1726: in this stage has not changed, or if the key is now released ! 1727: and we're not allowed to pass releases. otherwise, run the ! 1728: next stage: */ ! 1729: return ((keymode->tme_keymode_state_pressed ! 1730: ? pressed_old ! 1731: : (!pressed_old ! 1732: || (mode ! 1733: & TME_KEYBOARD_MODE_FLAG_NO_RELEASES))) ! 1734: ? TME_OK ! 1735: : ((*stage->tme_keymode_stage_next) ! 1736: (buffer, ! 1737: keymode->tme_keymode_state_keysym, ! 1738: event_time))); ! 1739: } ! 1740: ! 1741: /* this is the bottom half of output stage one. this half does ! 1742: nothing except finally buffer an event for a keycode, and update ! 1743: the output modifiers mask: */ ! 1744: static int ! 1745: _tme_keyboard_buffer_out1_bottom(struct tme_keyboard_buffer_int *buffer, ! 1746: struct tme_keysym_state *keysym, ! 1747: tme_uint32_t event_time) ! 1748: { ! 1749: struct tme_keycode_state *keycode; ! 1750: struct tme_keyboard_event event_buffer; ! 1751: int modifier; ! 1752: int is_press; ! 1753: ! 1754: /* get the keycode: */ ! 1755: keycode = keysym->tme_keysym_state_out0_keycode; ! 1756: ! 1757: /* get whether or not this is a press: */ ! 1758: is_press = TME_KEYBOARD_PRESSED_OUT1(keycode); ! 1759: ! 1760: _tme_keyboard_debug(buffer, ! 1761: "out1-bottom", ! 1762: keysym->tme_keysym_state_keysym, ! 1763: is_press, ! 1764: event_time); ! 1765: ! 1766: /* if this keysym is attached to a modifier, update the output ! 1767: modifiers mask: */ ! 1768: /* XXX there might be a cleaner way to work the output modifier ! 1769: mask. it's suspicious that stages zero and one need to share the ! 1770: modifiers mask and the keysym to modifier mapping: */ ! 1771: modifier = keysym->tme_keysym_state_out0_modifier; ! 1772: if (modifier != TME_KEYBOARD_MODIFIER_NONE) { ! 1773: ! 1774: /* if this is a press: */ ! 1775: if (is_press) { ! 1776: ! 1777: /* if the modifier is currently clear: */ ! 1778: if (!(buffer->tme_keyboard_buffer_int_out0_modifiers ! 1779: & (1 << modifier))) { ! 1780: ! 1781: /* set the modifier: */ ! 1782: buffer->tme_keyboard_buffer_int_out0_modifiers ! 1783: |= (1 << modifier); ! 1784: ! 1785: /* iff this keysym soft-locks, the next release will not ! 1786: affect the output modifiers mask: */ ! 1787: keysym->tme_keysym_state_out1_ignore_release ! 1788: = (keycode->tme_keycode_state_keymode.tme_keymode_state_mode ! 1789: & TME_KEYBOARD_MODE_FLAG_LOCK_SOFT); ! 1790: } ! 1791: ! 1792: /* otherwise, the modifier is currently set: */ ! 1793: else { ! 1794: ! 1795: /* nothing to do. even if this keysym soft-locks, we won't ! 1796: clear the modifier until the release: */ ! 1797: } ! 1798: } ! 1799: ! 1800: /* otherwise, this is a release: */ ! 1801: else { ! 1802: ! 1803: /* if we're supposed to ignore this release: */ ! 1804: if (keysym->tme_keysym_state_out1_ignore_release) { ! 1805: keysym->tme_keysym_state_out1_ignore_release = FALSE; ! 1806: } ! 1807: ! 1808: /* otherwise, if the modifier is currently set: */ ! 1809: else if (buffer->tme_keyboard_buffer_int_out0_modifiers ! 1810: & (1 << modifier)) { ! 1811: ! 1812: /* clear the modifier: */ ! 1813: buffer->tme_keyboard_buffer_int_out0_modifiers ! 1814: &= ~(1 << modifier); ! 1815: } ! 1816: ! 1817: /* otherwise, the modifier is currently clear: */ ! 1818: else { ! 1819: ! 1820: /* nothing to do. a release would never set a modifier: */ ! 1821: } ! 1822: } ! 1823: } ! 1824: ! 1825: /* finally buffer this keycode: */ ! 1826: event_buffer.tme_keyboard_event_type ! 1827: = (is_press ! 1828: ? TME_KEYBOARD_EVENT_PRESS ! 1829: : TME_KEYBOARD_EVENT_RELEASE); ! 1830: event_buffer.tme_keyboard_event_keyval ! 1831: = keycode->tme_keycode_state_keycode; ! 1832: event_buffer.tme_keyboard_event_time ! 1833: = event_time; ! 1834: event_buffer.tme_keyboard_event_modifiers ! 1835: = buffer->tme_keyboard_buffer_int_out0_modifiers; ! 1836: return (_tme_keyboard_buffer_copyin(buffer, &event_buffer)); ! 1837: } ! 1838: ! 1839: /* this is the top half of output stage one. it is the last output ! 1840: stage, that gives each keycode the specific behavior that it must ! 1841: have on the output keyboard: */ ! 1842: static int ! 1843: _tme_keyboard_buffer_out1(struct tme_keyboard_buffer_int *buffer, ! 1844: struct tme_keysym_state *keysym, ! 1845: tme_uint32_t event_time) ! 1846: { ! 1847: struct tme_keycode_state *keycode; ! 1848: ! 1849: _tme_keyboard_debug(buffer, ! 1850: "out1-top", ! 1851: keysym->tme_keysym_state_keysym, ! 1852: TME_KEYBOARD_PRESSED_OUT0(keysym), ! 1853: event_time); ! 1854: ! 1855: /* get the keycode state: */ ! 1856: keycode = keysym->tme_keysym_state_out0_keycode; ! 1857: ! 1858: /* run the keymode stage function: */ ! 1859: return (_tme_keymode_stage(buffer, ! 1860: &buffer->tme_keyboard_buffer_int_out1_keymode_stage, ! 1861: &keycode->tme_keycode_state_keymode, ! 1862: TME_KEYBOARD_PRESSED_OUT0(keysym), ! 1863: event_time)); ! 1864: } ! 1865: ! 1866: /* this is output stage zero. at this point, we have the final ! 1867: keysyms from the input keyboard, and this stage maps those keysyms ! 1868: to keycodes on the output keyboard. ! 1869: ! 1870: sometimes, the input keyboard may generate keysyms for which the ! 1871: output keyboard requires that certain modifiers be set or clear, at ! 1872: a time when the output modifiers mask isn't suitable. for example, ! 1873: this can happen when the input keyboard can generate a certain ! 1874: keysym without shifting, when the output keyboard requires ! 1875: shifting. ! 1876: ! 1877: when this happens, this stage is responsible for simulating presses ! 1878: or releases of modifiers on the output keyboard as needed to make ! 1879: sure that the keysym is properly obtained when the mapped keycode ! 1880: is pressed, and for undoing those changes when the mapped keycode ! 1881: is released: */ ! 1882: static int ! 1883: _tme_keyboard_buffer_out0(struct tme_keyboard_buffer_int *buffer, ! 1884: struct tme_keysym_state *keysym, ! 1885: tme_uint32_t event_time) ! 1886: { ! 1887: struct tme_keyboard_event event_buffer; ! 1888: tme_keyboard_modifiers_t modifiers, modifiers_set, modifiers_clear; ! 1889: int num_lock_on; ! 1890: int is_press, mod_pressed_old, modifier; ! 1891: struct tme_keysym_state *mod_keysym, **keysyms; ! 1892: unsigned int *press_flags; ! 1893: int keysym_count; ! 1894: int modifier_stuck; ! 1895: int rc; ! 1896: ! 1897: _tme_keyboard_debug(buffer, ! 1898: "out0", ! 1899: keysym->tme_keysym_state_keysym, ! 1900: TME_KEYBOARD_PRESSED_IN2(keysym), ! 1901: event_time); ! 1902: ! 1903: /* get whether or not this is a press from earlier stages: */ ! 1904: is_press = TME_KEYBOARD_PRESSED_IN2(keysym); ! 1905: ! 1906: /* if output stage zero is a passthrough, just buffer an event for ! 1907: the keysym and we're done processing this event: */ ! 1908: if (buffer->tme_keyboard_buffer_int_out0_passthrough) { ! 1909: ! 1910: /* otherwise, simply buffer this event: */ ! 1911: event_buffer.tme_keyboard_event_type ! 1912: = (is_press ! 1913: ? TME_KEYBOARD_EVENT_PRESS ! 1914: : TME_KEYBOARD_EVENT_RELEASE); ! 1915: event_buffer.tme_keyboard_event_keyval ! 1916: = keysym->tme_keysym_state_keysym; ! 1917: event_buffer.tme_keyboard_event_time ! 1918: = event_time; ! 1919: event_buffer.tme_keyboard_event_modifiers ! 1920: = 0; ! 1921: return (_tme_keyboard_buffer_copyin(buffer, &event_buffer)); ! 1922: } ! 1923: ! 1924: /* if this keysym is not mapped to a keycode on the output keyboard, ! 1925: we don't have to process this event any more: */ ! 1926: if (keysym->tme_keysym_state_out0_keycode == NULL) { ! 1927: return (TME_OK); ! 1928: } ! 1929: ! 1930: /* if this is a press from earlier stages: */ ! 1931: if (is_press) { ! 1932: ! 1933: /* this keysym can't have any changes attached to it already: */ ! 1934: assert (keysym->tme_keysym_state_out0_keysyms == NULL); ! 1935: keysyms = NULL; ! 1936: press_flags = NULL; ! 1937: keysym_count = 0; ! 1938: ! 1939: /* get the current output stage zero modifiers: */ ! 1940: modifiers = buffer->tme_keyboard_buffer_int_out0_modifiers; ! 1941: ! 1942: /* get the sets of modifiers that must be clear and set for this ! 1943: keysym: */ ! 1944: modifiers_clear = keysym->tme_keysym_state_out0_modifiers_clear; ! 1945: modifiers_set = keysym->tme_keysym_state_out0_modifiers_set; ! 1946: assert ((modifiers_clear & modifiers_set) == 0); ! 1947: assert ((modifiers_clear | modifiers_set) == 0 ! 1948: || (keysym->tme_keysym_state_out0_modifier ! 1949: == TME_KEYBOARD_MODIFIER_NONE)); ! 1950: ! 1951: /* if this keysym is uppercase, but the current modifiers are such ! 1952: that a lowercase keysym *might* be generated: */ ! 1953: if ((modifiers_set & (1 << TME_KEYBOARD_MODIFIER_LOCK)) ! 1954: && !(modifiers & (1 << TME_KEYBOARD_MODIFIER_LOCK))) { ! 1955: ! 1956: /* if shift is down, we must be generating uppercase keysyms, so ! 1957: forget about the lock modifier in this instance: */ ! 1958: if (modifiers & (1 << TME_KEYBOARD_MODIFIER_SHIFT)) { ! 1959: modifiers_set &= ~(1 << TME_KEYBOARD_MODIFIER_LOCK); ! 1960: } ! 1961: ! 1962: /* otherwise, neither shift nor lock are down, so we are ! 1963: generating lowercase keysyms. since this keyboard might not ! 1964: have a lock modifier at all (and since it seems more ! 1965: reasonable to do it this way anyways), require the shift ! 1966: modifier to be set instead of the lock modifier in this ! 1967: instance: */ ! 1968: else { ! 1969: modifiers_set &= ~(1 << TME_KEYBOARD_MODIFIER_LOCK); ! 1970: modifiers_set |= (1 << TME_KEYBOARD_MODIFIER_SHIFT); ! 1971: } ! 1972: } ! 1973: ! 1974: /* if this output keyboard has a Num_Lock key, and this keysym is ! 1975: sensitive to the Num_Lock setting, but the appropriate Num_Lock ! 1976: setting is already in effect, forget about Num_Lock for this ! 1977: instance: */ ! 1978: modifier = buffer->tme_keyboard_buffer_int_out0_mod_num_lock; ! 1979: if (modifier != TME_KEYBOARD_MODIFIER_NONE ! 1980: && ((modifiers_clear ! 1981: | modifiers_set) ! 1982: & (1 << modifier))) { ! 1983: ! 1984: /* determine what Num_Lock setting is currently in effect. it ! 1985: is active if Num_Lock is pressed and there is no shifting ! 1986: active, or if Num_Lock is released and there is shifting ! 1987: active. NB that if the lock modifier is attached only to a ! 1988: Shift_Lock, that modifier also counts as shifting: */ ! 1989: num_lock_on ! 1990: = ( ! 1991: ! 1992: /* this term is 0 iff Num_Lock is pressed, else 1: */ ! 1993: !(modifiers ! 1994: & (1 << modifier)) ! 1995: ! 1996: != ! 1997: ! 1998: /* this term is 0 iff shifting is active, else 1: */ ! 1999: !(modifiers ! 2000: & ((1 << TME_KEYBOARD_MODIFIER_SHIFT) ! 2001: | (buffer->tme_keyboard_buffer_int_out0_lock_is_caps ! 2002: ? 0 ! 2003: : (1 << TME_KEYBOARD_MODIFIER_LOCK))))); ! 2004: ! 2005: /* if this keysym requires Num_Lock to be clear, but it is ! 2006: not in effect, forget about Num_Lock for this instance: */ ! 2007: if ((modifiers_clear & (1 << modifier)) ! 2008: && !num_lock_on) { ! 2009: modifiers_clear &= ~(1 << modifier); ! 2010: } ! 2011: ! 2012: /* if this keysym requires Num_Lock to be set, but it is ! 2013: in effect, forget about Num_Lock for this instance: */ ! 2014: if ((modifiers_set & (1 << modifier)) ! 2015: && num_lock_on) { ! 2016: modifiers_set &= ~(1 << modifier); ! 2017: } ! 2018: } ! 2019: ! 2020: /* finish the set of modifiers that must be clear and set for this ! 2021: keysym, but aren't: */ ! 2022: modifiers_clear &= modifiers; ! 2023: modifiers_set &= ~modifiers; ! 2024: ! 2025: /* try to generate release events for all keysyms attached to ! 2026: output modifiers that are set, but that need to be clear: */ ! 2027: if (modifiers_clear != 0) { ! 2028: ! 2029: /* loop over the modifiers that need clearing: */ ! 2030: for (modifier = 0; ! 2031: modifier <= TME_KEYBOARD_MODIFIER_MAX; ! 2032: modifier++) { ! 2033: if (!(modifiers_clear & (1 << modifier))) { ! 2034: continue; ! 2035: } ! 2036: ! 2037: /* try to release all of the keysyms attached to this modifier ! 2038: that are pressed: */ ! 2039: modifier_stuck = FALSE; ! 2040: for (mod_keysym = buffer->tme_keyboard_buffer_int_out0_modkeys[modifier]; ! 2041: mod_keysym != NULL; ! 2042: mod_keysym = mod_keysym->tme_keysym_state_out0_modifier_next) { ! 2043: ! 2044: /* XXX this is broken for modifiers that soft-lock. */ ! 2045: ! 2046: /* ignore this keysym if it isn't pressed: */ ! 2047: if (!TME_KEYBOARD_PRESSED_OUT0(mod_keysym)) { ! 2048: continue; ! 2049: } ! 2050: ! 2051: /* grow the keysyms and press flags arrays. the keysyms ! 2052: array always has one extra entry, which will be filled ! 2053: with NULL to terminate the array: */ ! 2054: if (keysym_count == 0) { ! 2055: keysyms = tme_new(struct tme_keysym_state *, 2); ! 2056: press_flags = tme_new(unsigned int, 1); ! 2057: } ! 2058: else { ! 2059: keysyms = tme_renew(struct tme_keysym_state *, keysyms, keysym_count + 2); ! 2060: press_flags = tme_renew(unsigned int, press_flags, keysym_count + 1); ! 2061: } ! 2062: ! 2063: /* add this keysym to those arrays: */ ! 2064: keysyms[keysym_count] = mod_keysym; ! 2065: press_flags[keysym_count] = FALSE; ! 2066: keysym_count++; ! 2067: ! 2068: /* release this modifier key. if this actually ! 2069: releases the key, run the next stage: */ ! 2070: mod_keysym->tme_keysym_state_out0_released++; ! 2071: if (!TME_KEYBOARD_PRESSED_OUT0(mod_keysym)) { ! 2072: rc = _tme_keyboard_buffer_out1(buffer, ! 2073: mod_keysym, ! 2074: _tme_keyboard_event_time_diff(event_time, -1)); ! 2075: assert (rc == TME_OK); ! 2076: } ! 2077: ! 2078: /* otherwise, this modifier is stuck on: */ ! 2079: else { ! 2080: modifier_stuck = TRUE; ! 2081: } ! 2082: } ! 2083: ! 2084: /* if we were able to release all keysyms attached to this ! 2085: modifier, clear the modifier in the output keyboard mask: */ ! 2086: if (!modifier_stuck) { ! 2087: buffer->tme_keyboard_buffer_int_out0_modifiers ! 2088: &= ~(1 << modifier); ! 2089: } ! 2090: } ! 2091: } ! 2092: ! 2093: /* try to generate press events for single keysyms attached to ! 2094: output modifiers that are clear, but that need to be set: */ ! 2095: if (modifiers_set != 0) { ! 2096: ! 2097: /* loop over the modifiers that need setting: */ ! 2098: for (modifier = 0; ! 2099: modifier <= TME_KEYBOARD_MODIFIER_MAX; ! 2100: modifier++) { ! 2101: if (!(modifiers_set & (1 << modifier))) { ! 2102: continue; ! 2103: } ! 2104: ! 2105: /* try to press a single keysym attached to this modifier: */ ! 2106: mod_keysym = buffer->tme_keyboard_buffer_int_out0_modkeys[modifier]; ! 2107: assert (mod_keysym != NULL); ! 2108: ! 2109: /* this keysym can't pressed - if it is, the modifier ! 2110: should be set: */ ! 2111: assert (!TME_KEYBOARD_PRESSED_OUT0(mod_keysym)); ! 2112: ! 2113: /* grow the keysyms and press flags arrays. the keysyms ! 2114: array always has one extra entry, which will be filled ! 2115: with NULL to terminate the array: */ ! 2116: if (keysym_count == 0) { ! 2117: keysyms = tme_new(struct tme_keysym_state *, 2); ! 2118: press_flags = tme_new(unsigned int, 1); ! 2119: } ! 2120: else { ! 2121: keysyms = tme_renew(struct tme_keysym_state *, keysyms, keysym_count + 2); ! 2122: press_flags = tme_renew(unsigned int, press_flags, keysym_count + 1); ! 2123: } ! 2124: ! 2125: /* add this keysym to those arrays: */ ! 2126: keysyms[keysym_count] = mod_keysym; ! 2127: press_flags[keysym_count] = TRUE; ! 2128: keysym_count++; ! 2129: ! 2130: /* press this modifier key. this must actually press the key, ! 2131: so run the next stage: */ ! 2132: mod_keysym->tme_keysym_state_out0_pressed++; ! 2133: assert (TME_KEYBOARD_PRESSED_OUT0(mod_keysym)); ! 2134: rc = _tme_keyboard_buffer_out1(buffer, ! 2135: mod_keysym, ! 2136: _tme_keyboard_event_time_diff(event_time, -1)); ! 2137: assert (rc == TME_OK); ! 2138: ! 2139: /* set the modifier: */ ! 2140: buffer->tme_keyboard_buffer_int_out0_modifiers ! 2141: |= (1 << modifier); ! 2142: } ! 2143: } ! 2144: ! 2145: /* remember any changes we made: */ ! 2146: if (keysyms != NULL) { ! 2147: keysyms[keysym_count] = NULL; ! 2148: } ! 2149: keysym->tme_keysym_state_out0_keysyms = keysyms; ! 2150: keysym->tme_keysym_state_out0_press_flags = press_flags; ! 2151: ! 2152: /* run the next stage: */ ! 2153: return (_tme_keyboard_buffer_out1(buffer, ! 2154: keysym, ! 2155: event_time)); ! 2156: } ! 2157: ! 2158: /* otherwise, this is a release: */ ! 2159: else { ! 2160: ! 2161: /* run the next stage: */ ! 2162: rc = _tme_keyboard_buffer_out1(buffer, ! 2163: keysym, ! 2164: event_time); ! 2165: assert (rc == TME_OK); ! 2166: ! 2167: /* if this keysym tried to make any modifier changes, undo them: */ ! 2168: keysyms = keysym->tme_keysym_state_out0_keysyms; ! 2169: press_flags = keysym->tme_keysym_state_out0_press_flags; ! 2170: if (keysyms != NULL) { ! 2171: ! 2172: /* loop over all of the modifiers we changed: */ ! 2173: for (; (mod_keysym = *(keysyms++)) != NULL; ) { ! 2174: ! 2175: /* see if this modifier is pressed now: */ ! 2176: mod_pressed_old = TME_KEYBOARD_PRESSED_OUT0(mod_keysym); ! 2177: ! 2178: /* undo the change we made to this modifier: */ ! 2179: if (*(press_flags++)) { ! 2180: mod_keysym->tme_keysym_state_out0_pressed--; ! 2181: } ! 2182: else { ! 2183: mod_keysym->tme_keysym_state_out0_released--; ! 2184: } ! 2185: ! 2186: /* if the state of this modifier has changed, run the next ! 2187: stage: */ ! 2188: if (TME_KEYBOARD_PRESSED_OUT0(mod_keysym) != mod_pressed_old) { ! 2189: rc = _tme_keyboard_buffer_out1(buffer, ! 2190: mod_keysym, ! 2191: _tme_keyboard_event_time_diff(event_time, +1)); ! 2192: assert (rc == TME_OK); ! 2193: } ! 2194: } ! 2195: ! 2196: /* forget these modifier changes: */ ! 2197: tme_free(keysym->tme_keysym_state_out0_keysyms); ! 2198: tme_free(keysym->tme_keysym_state_out0_press_flags); ! 2199: keysym->tme_keysym_state_out0_keysyms = NULL; ! 2200: keysym->tme_keysym_state_out0_press_flags = NULL; ! 2201: } ! 2202: } ! 2203: ! 2204: /* success: */ ! 2205: return (TME_OK); ! 2206: } ! 2207: ! 2208: /* this is input stage two. at this point, we have the input keyboard ! 2209: cleaned up to the point where we can have macros for generating ! 2210: keysyms that the input keyboard can't generate on its own: */ ! 2211: static int ! 2212: _tme_keyboard_buffer_in2(struct tme_keyboard_buffer_int *buffer, ! 2213: struct tme_keysym_state *keysym, ! 2214: tme_uint32_t event_time) ! 2215: { ! 2216: tme_keyboard_keyval_t _keysym; ! 2217: struct tme_keyboard_macro **_macro, *macro, *child, *parent; ! 2218: int is_press, pressed_old, sub_pressed_old; ! 2219: int update, keysym_i; ! 2220: struct tme_keysym_state *sub_keysym; ! 2221: int rc; ! 2222: ! 2223: _tme_keyboard_debug(buffer, ! 2224: "in2", ! 2225: keysym->tme_keysym_state_keysym, ! 2226: TME_KEYBOARD_PRESSED_IN1(keysym), ! 2227: event_time); ! 2228: ! 2229: /* get the keysym: */ ! 2230: _keysym = keysym->tme_keysym_state_keysym; ! 2231: ! 2232: /* get whether or not this is a press from earlier stages: */ ! 2233: is_press = TME_KEYBOARD_PRESSED_IN1(keysym); ! 2234: ! 2235: /* remember if this keysym was pressed in this stage before: */ ! 2236: pressed_old = _TME_KEYBOARD_PRESSED_IN2(keysym, !is_press); ! 2237: ! 2238: /* visit all active macros tree nodes: */ ! 2239: for (_macro = &buffer->tme_keyboard_buffer_int_in2_macros_active; ! 2240: (macro = *_macro) != NULL; ) { ! 2241: ! 2242: /* if this is a press, see if it advances this macro's sequence: */ ! 2243: if (is_press) { ! 2244: ! 2245: /* ignore this macros tree node if it's a leaf, or if this ! 2246: keysym is not a branch out of this node to some child node: */ ! 2247: if (macro->tme_keyboard_macro_branches == NULL ! 2248: || (child ! 2249: = ((struct tme_keyboard_macro *) ! 2250: tme_hash_lookup(macro->tme_keyboard_macro_branches, ! 2251: (tme_hash_data_t) _keysym))) == NULL) { ! 2252: _macro = ¯o->tme_keyboard_macro_active_next; ! 2253: continue; ! 2254: } ! 2255: ! 2256: /* the child node cannot already be active. if it is, that ! 2257: means that earlier stages didn't give us a release for this ! 2258: keysym: */ ! 2259: assert (child->tme_keyboard_macro_active_next == NULL); ! 2260: ! 2261: /* make the child node active: */ ! 2262: child->tme_keyboard_macro_active_next = macro; ! 2263: *_macro = child; ! 2264: _macro = ¯o->tme_keyboard_macro_active_next; ! 2265: macro = child; ! 2266: } ! 2267: ! 2268: /* otherwise, this is a release, so see if this release cancels ! 2269: any sequence: */ ! 2270: else { ! 2271: ! 2272: /* ignore this macros tree node if this is not a release of a ! 2273: keysym somewhere on the path from the root to this node: */ ! 2274: if (_keysym != macro->tme_keyboard_macro_keysym) { ! 2275: for (parent = macro->tme_keyboard_macro_parent; ! 2276: parent != NULL; ! 2277: parent = parent->tme_keyboard_macro_parent) { ! 2278: if (_keysym == parent->tme_keyboard_macro_keysym) { ! 2279: break; ! 2280: } ! 2281: } ! 2282: if (parent == NULL) { ! 2283: _macro = ¯o->tme_keyboard_macro_active_next; ! 2284: continue; ! 2285: } ! 2286: } ! 2287: ! 2288: /* make this macros tree node no longer active: */ ! 2289: *_macro = macro->tme_keyboard_macro_active_next; ! 2290: macro->tme_keyboard_macro_active_next = NULL; ! 2291: } ! 2292: ! 2293: /* if this macro is not a leaf node, continue: */ ! 2294: if (macro->tme_keyboard_macro_branches != NULL) { ! 2295: continue; ! 2296: } ! 2297: ! 2298: /* otherwise, this event has either activated or deactivated a ! 2299: macro. either do or undo this macro's presses and releases: */ ! 2300: update = (is_press ? 1 : -1); ! 2301: for (keysym_i = macro->tme_keyboard_macro_length; ! 2302: keysym_i-- > 0; ) { ! 2303: ! 2304: /* get this keysym's state: */ ! 2305: sub_keysym = macro->tme_keyboard_macro_keysyms[keysym_i]; ! 2306: ! 2307: /* remember if this keysym was pressed in this stage before: */ ! 2308: sub_pressed_old = TME_KEYBOARD_PRESSED_IN2(sub_keysym); ! 2309: ! 2310: /* update this keysym's state: */ ! 2311: if (macro->tme_keyboard_macro_press_flags[keysym_i]) { ! 2312: sub_keysym->tme_keysym_state_in2_pressed += update; ! 2313: } ! 2314: else { ! 2315: sub_keysym->tme_keysym_state_in2_released += update; ! 2316: } ! 2317: ! 2318: /* if this keysym's pressed state in this stage has changed, ! 2319: run the next stage, unless this is the keysym that we ! 2320: were called with, in which case we'll handle this later: */ ! 2321: if (sub_keysym != keysym ! 2322: && TME_KEYBOARD_PRESSED_IN2(sub_keysym) != sub_pressed_old) { ! 2323: rc = _tme_keyboard_buffer_out0(buffer, sub_keysym, event_time); ! 2324: assert (rc == TME_OK); ! 2325: } ! 2326: } ! 2327: } ! 2328: ! 2329: /* if this keysym's pressed state in this stage has changed, run ! 2330: the next stage, otherwise stop processing this event now: */ ! 2331: return ((TME_KEYBOARD_PRESSED_IN2(keysym) != pressed_old) ! 2332: ? _tme_keyboard_buffer_out0(buffer, keysym, event_time) ! 2333: : TME_OK); ! 2334: } ! 2335: ! 2336: /* this is input stage one. at this point, the input keyboard is ! 2337: slightly cleaned up - consecutive presses have had a release ! 2338: inserted in between, releases of unpressed keys have been dropped, ! 2339: and as many inferred lost events as possible have been generated. ! 2340: ! 2341: this stage finishes cleaning up the input keyboard to the point ! 2342: where macros are useful. usually, the only keysyms that will have ! 2343: specific behaviors enforced here will be keysyms that are used like ! 2344: modifiers in input stage two macros, but that don't behave like ! 2345: modifiers on the input keyboard (i.e., they autorepeat) and so ! 2346: aren't good for use in multiple-key macros: */ ! 2347: static int ! 2348: _tme_keyboard_buffer_in1(struct tme_keyboard_buffer_int *buffer, ! 2349: struct tme_keysym_state *keysym, ! 2350: tme_uint32_t event_time) ! 2351: { ! 2352: ! 2353: _tme_keyboard_debug(buffer, ! 2354: "in1", ! 2355: keysym->tme_keysym_state_keysym, ! 2356: TME_KEYBOARD_PRESSED_IN0(keysym), ! 2357: event_time); ! 2358: ! 2359: /* run the keymode stage function: */ ! 2360: return (_tme_keymode_stage(buffer, ! 2361: &buffer->tme_keyboard_buffer_int_in1_keymode_stage, ! 2362: &keysym->tme_keysym_state_in1_keymode, ! 2363: TME_KEYBOARD_PRESSED_IN0(keysym), ! 2364: event_time)); ! 2365: } ! 2366: ! 2367: /* this is the bottom half of input stage zero. at this point, events ! 2368: inferred by modifier changes have been generated, but otherwise the ! 2369: input keyboard hasn't been cleaned up. ! 2370: ! 2371: this half drops releases of keys that we don't think are pressed, ! 2372: generates a release in between two consecutive presses, and tracks ! 2373: the input modifier mask: */ ! 2374: static int ! 2375: _tme_keyboard_buffer_in0_bottom(struct tme_keyboard_buffer_int *buffer, ! 2376: struct tme_keysym_state *keysym, ! 2377: const struct tme_keyboard_event *event) ! 2378: { ! 2379: struct tme_keysym_state *mod_keysym; ! 2380: struct tme_keyboard_event event_pseudo; ! 2381: int modifier, pressed_old; ! 2382: int rc; ! 2383: ! 2384: _tme_keyboard_debug(buffer, ! 2385: "in0-bottom", ! 2386: keysym->tme_keysym_state_keysym, ! 2387: (event->tme_keyboard_event_type ! 2388: & TME_KEYBOARD_EVENT_IN0_PRESS_USER), ! 2389: event->tme_keyboard_event_time); ! 2390: ! 2391: /* NB: event->tme_keyboard_event_modifiers is always the modifiers ! 2392: *mask from immediately before* the event, i.e., if this event is ! 2393: *for a modifier keysym, it does not reflect any change the press ! 2394: *or release of this keysym will cause: */ ! 2395: ! 2396: /* remember if this keysym was pressed in this stage before: */ ! 2397: pressed_old = TME_KEYBOARD_PRESSED_IN0(keysym); ! 2398: ! 2399: /* see if this keysym is attached to any known modifier: */ ! 2400: modifier = (buffer->tme_keyboard_buffer_int_in0_have_modifiers ! 2401: ? keysym->tme_keysym_state_in0_modifier ! 2402: : TME_KEYBOARD_MODIFIER_NONE); ! 2403: ! 2404: /* dispatch on the event type: */ ! 2405: switch (event->tme_keyboard_event_type) { ! 2406: ! 2407: /* an automatic input stage zero press: */ ! 2408: case TME_KEYBOARD_EVENT_IN0_PRESS_AUTO: ! 2409: /* this keysym must not be pressed at all: */ ! 2410: assert (!pressed_old); ! 2411: /* FALLTHROUGH */ ! 2412: ! 2413: /* a user input stage zero press: */ ! 2414: case TME_KEYBOARD_EVENT_IN0_PRESS_USER: ! 2415: ! 2416: /* if this keysym was already pressed, inject a release first - ! 2417: you can't press a key twice without releasing it in between: */ ! 2418: if (pressed_old) { ! 2419: ! 2420: /* make the pseudoevent. assume that the release we dropped ! 2421: happened as soon as humanly possible after the press, but ! 2422: never after this new press: */ ! 2423: event_pseudo.tme_keyboard_event_type ! 2424: = TME_KEYBOARD_IN0_RELEASE_EVENT(keysym->tme_keysym_state_in0_pressed); ! 2425: event_pseudo.tme_keyboard_event_time ! 2426: = _tme_keyboard_event_time_diff(keysym->tme_keysym_state_in0_press_time, ! 2427: TME_KEYBOARD_SHORTEST_DOUBLE_MSEC); ! 2428: if (_tme_keyboard_event_time_subtract(event_pseudo.tme_keyboard_event_time, ! 2429: event->tme_keyboard_event_time) <= 0) { ! 2430: event_pseudo.tme_keyboard_event_time ! 2431: = _tme_keyboard_event_time_diff(event->tme_keyboard_event_time, -1); ! 2432: } ! 2433: event_pseudo.tme_keyboard_event_modifiers ! 2434: = buffer->tme_keyboard_buffer_int_in0_modifiers; ! 2435: ! 2436: /* recurse with this pseudoevent: */ ! 2437: rc = _tme_keyboard_buffer_in0_bottom(buffer, ! 2438: keysym, ! 2439: &event_pseudo); ! 2440: assert (rc == TME_OK); ! 2441: } ! 2442: ! 2443: /* this keysym is now pressed: */ ! 2444: keysym->tme_keysym_state_in0_pressed = event->tme_keyboard_event_type; ! 2445: keysym->tme_keysym_state_in0_press_time = event->tme_keyboard_event_time; ! 2446: ! 2447: /* set any modifier in the mask: */ ! 2448: assert (buffer->tme_keyboard_buffer_int_in0_modifiers ! 2449: == event->tme_keyboard_event_modifiers); ! 2450: if (modifier != TME_KEYBOARD_MODIFIER_NONE) { ! 2451: buffer->tme_keyboard_buffer_int_in0_modifiers |= (1 << modifier); ! 2452: } ! 2453: break; ! 2454: ! 2455: /* an automatic input stage zero release :*/ ! 2456: case TME_KEYBOARD_EVENT_IN0_RELEASE_AUTO: ! 2457: assert (pressed_old == TME_KEYBOARD_EVENT_IN0_PRESS_AUTO); ! 2458: /* FALLTHROUGH */ ! 2459: ! 2460: /* a user input stage zero release: */ ! 2461: case TME_KEYBOARD_EVENT_IN0_RELEASE_USER: ! 2462: ! 2463: /* if this keysym wasn't already pressed, stop processing this ! 2464: event: */ ! 2465: if (!pressed_old) { ! 2466: return (TME_OK); ! 2467: } ! 2468: ! 2469: /* this keysym is no longer pressed: */ ! 2470: keysym->tme_keysym_state_in0_pressed = FALSE; ! 2471: ! 2472: /* if this keysym is attached to a modifier: */ ! 2473: if (modifier != TME_KEYBOARD_MODIFIER_NONE) { ! 2474: ! 2475: /* if we can find no keysym attached to this modifier that is ! 2476: still pressed, clear the modifier in the mask: */ ! 2477: for (mod_keysym = buffer->tme_keyboard_buffer_int_in0_modkeys[modifier]; ! 2478: mod_keysym != NULL; ! 2479: mod_keysym = mod_keysym->tme_keysym_state_in0_modifier_next) { ! 2480: if (mod_keysym->tme_keysym_state_in0_pressed) { ! 2481: break; ! 2482: } ! 2483: } ! 2484: if (mod_keysym == NULL) { ! 2485: buffer->tme_keyboard_buffer_int_in0_modifiers &= ~(1 << modifier); ! 2486: } ! 2487: } ! 2488: break; ! 2489: ! 2490: default: ! 2491: abort(); ! 2492: } ! 2493: ! 2494: /* run the next stage: */ ! 2495: return (_tme_keyboard_buffer_in1(buffer, ! 2496: keysym, ! 2497: event->tme_keyboard_event_time)); ! 2498: } ! 2499: ! 2500: /* this is the top half of input stage zero. this gets raw ! 2501: events from the input keyboard. if we get a modifiers mask with ! 2502: each event, and we know which input keyboard keysyms are attached ! 2503: to which modifiers, we can often infer presses and releases of ! 2504: these keysyms when our caller has missed those events. ! 2505: ! 2506: For example, this works well under X11 when the Caps_Lock or ! 2507: Num_Lock key "locks" and its state changes while our window doesn't ! 2508: have focus. When we do regain focus, we don't get press or release ! 2509: events for those changes, but we can get the current modifiers ! 2510: mask: */ ! 2511: static int ! 2512: _tme_keyboard_buffer_in0(struct tme_keyboard_buffer_int *buffer, ! 2513: const struct tme_keyboard_event *event) ! 2514: { ! 2515: struct tme_keysym_state *keysym, *mod_keysym, *other_keysym; ! 2516: struct tme_keyboard_event event_pseudo; ! 2517: int modifier; ! 2518: tme_keyboard_modifiers_t modifiers, modifiers_set, modifiers_clear; ! 2519: int rc; ! 2520: ! 2521: _tme_keyboard_debug(buffer, ! 2522: "in0-top", ! 2523: event->tme_keyboard_event_keyval, ! 2524: (event->tme_keyboard_event_type ! 2525: == TME_KEYBOARD_EVENT_PRESS), ! 2526: event->tme_keyboard_event_time); ! 2527: ! 2528: assert (event->tme_keyboard_event_time ! 2529: != TME_KEYBOARD_EVENT_TIME_UNDEF); ! 2530: ! 2531: /* look up this keysym: */ ! 2532: keysym ! 2533: = ((struct tme_keysym_state *) ! 2534: tme_hash_lookup(buffer->tme_keyboard_buffer_int_keysyms_state, ! 2535: (tme_hash_data_t) event->tme_keyboard_event_keyval)); ! 2536: ! 2537: ! 2538: /* if input stage zero has modifier information: */ ! 2539: if (buffer->tme_keyboard_buffer_int_in0_have_modifiers) { ! 2540: ! 2541: /* NB: event->tme_keyboard_event_modifiers is always the modifiers ! 2542: mask from immediately *before* the event, i.e., if this event ! 2543: is for a modifier keysym, it does not reflect any change this ! 2544: press or release of this keysym will cause to that mask: */ ! 2545: modifiers = event->tme_keyboard_event_modifiers; ! 2546: ! 2547: /* get the mask of modifiers that been cleared and set unbeknownst ! 2548: to us before this event: */ ! 2549: modifiers_clear = ! 2550: (buffer->tme_keyboard_buffer_int_in0_modifiers ! 2551: & ~modifiers ! 2552: & buffer->tme_keyboard_buffer_int_in0_have_modifiers); ! 2553: modifiers_set = ! 2554: (modifiers ! 2555: & ~buffer->tme_keyboard_buffer_int_in0_modifiers ! 2556: & buffer->tme_keyboard_buffer_int_in0_have_modifiers); ! 2557: ! 2558: /* generate the appropriate release events for all keysyms ! 2559: attached to modifiers that have been cleared: */ ! 2560: if (modifiers_clear != 0) { ! 2561: ! 2562: /* loop over the modifiers that need clearing: */ ! 2563: for (modifier = 0; ! 2564: modifier <= TME_KEYBOARD_MODIFIER_MAX; ! 2565: modifier++) { ! 2566: if (!(modifiers_clear & (1 << modifier))) { ! 2567: continue; ! 2568: } ! 2569: ! 2570: /* release all of the keysyms: */ ! 2571: for (mod_keysym = buffer->tme_keyboard_buffer_int_in0_modkeys[modifier]; ! 2572: mod_keysym != NULL; ! 2573: mod_keysym = mod_keysym->tme_keysym_state_in0_modifier_next) { ! 2574: ! 2575: /* ignore this keysym if it isn't pressed: */ ! 2576: if (!mod_keysym->tme_keysym_state_in0_pressed) { ! 2577: continue; ! 2578: } ! 2579: ! 2580: /* make the pseudoevent: */ ! 2581: event_pseudo.tme_keyboard_event_type ! 2582: = TME_KEYBOARD_IN0_RELEASE_EVENT(mod_keysym->tme_keysym_state_in0_pressed); ! 2583: event_pseudo.tme_keyboard_event_time ! 2584: = _tme_keyboard_event_time_diff(event->tme_keyboard_event_time, -1); ! 2585: event_pseudo.tme_keyboard_event_modifiers ! 2586: = buffer->tme_keyboard_buffer_int_in0_modifiers; ! 2587: ! 2588: /* call the bottom half with this pseudoevent: */ ! 2589: rc = _tme_keyboard_buffer_in0_bottom(buffer, ! 2590: mod_keysym, ! 2591: &event_pseudo); ! 2592: assert (rc == TME_OK); ! 2593: } ! 2594: } ! 2595: ! 2596: /* all of the modifiers that needed clearing must now be clear: */ ! 2597: assert ((buffer->tme_keyboard_buffer_int_in0_modifiers ! 2598: & modifiers_clear) == 0); ! 2599: } ! 2600: ! 2601: /* generate a press event for a single keysym attached to each ! 2602: modifier that has been set: */ ! 2603: if (modifiers_set != 0) { ! 2604: ! 2605: /* loop over the modifiers that need setting: */ ! 2606: for (modifier = 0; ! 2607: modifier <= TME_KEYBOARD_MODIFIER_MAX; ! 2608: modifier++) { ! 2609: if (!(modifiers_set & (1 << modifier))) { ! 2610: continue; ! 2611: } ! 2612: ! 2613: /* press the first keysym attached to this modifier: */ ! 2614: mod_keysym = buffer->tme_keyboard_buffer_int_in0_modkeys[modifier]; ! 2615: assert (mod_keysym != NULL); ! 2616: ! 2617: /* make the pseudoevent: */ ! 2618: event_pseudo.tme_keyboard_event_type ! 2619: = TME_KEYBOARD_EVENT_IN0_PRESS_AUTO; ! 2620: event_pseudo.tme_keyboard_event_time ! 2621: = _tme_keyboard_event_time_diff(event->tme_keyboard_event_time, -1); ! 2622: event_pseudo.tme_keyboard_event_modifiers ! 2623: = buffer->tme_keyboard_buffer_int_in0_modifiers; ! 2624: ! 2625: /* call the bottom half with this pseudoevent: */ ! 2626: rc = _tme_keyboard_buffer_in0_bottom(buffer, ! 2627: mod_keysym, ! 2628: &event_pseudo); ! 2629: assert (rc == TME_OK); ! 2630: } ! 2631: ! 2632: /* all of the modifiers that needed setting must now be set: */ ! 2633: assert ((buffer->tme_keyboard_buffer_int_in0_modifiers ! 2634: & modifiers_set) == modifiers_set); ! 2635: } ! 2636: ! 2637: /* if the keysym in the event is undefined, we don't need to ! 2638: process this event any more. events with an undefined keysym ! 2639: can be used whenever the caller thinks that it has dropped ! 2640: keyboard events, and wants to do what it can to update the ! 2641: keyboard, and it can at least get the true current modifiers ! 2642: mask. this is common under X11: */ ! 2643: if (event->tme_keyboard_event_keyval ! 2644: == TME_KEYBOARD_KEYVAL_UNDEF) { ! 2645: return (TME_OK); ! 2646: } ! 2647: } ! 2648: ! 2649: /* we must have a defined keysym: */ ! 2650: assert (event->tme_keyboard_event_keyval ! 2651: != TME_KEYBOARD_KEYVAL_UNDEF); ! 2652: ! 2653: /* if we have no state for the keysym in this event, this keysym ! 2654: isn't controlled by any of the input stages: */ ! 2655: if (keysym == NULL) { ! 2656: ! 2657: /* if there are output stages, having no state for this keysym ! 2658: means that this keysym doesn't exist on the output keyboard. ! 2659: we can stop processing this event now: */ ! 2660: if (!buffer->tme_keyboard_buffer_int_out0_passthrough) { ! 2661: return (TME_OK); ! 2662: } ! 2663: ! 2664: /* otherwise, simply buffer this event: */ ! 2665: event_pseudo = *event; ! 2666: switch (event->tme_keyboard_event_type) { ! 2667: case TME_KEYBOARD_EVENT_IN0_PRESS_USER: ! 2668: case TME_KEYBOARD_EVENT_IN0_PRESS_AUTO: ! 2669: event_pseudo.tme_keyboard_event_type = TME_KEYBOARD_EVENT_PRESS; ! 2670: break; ! 2671: case TME_KEYBOARD_EVENT_IN0_RELEASE_USER: ! 2672: case TME_KEYBOARD_EVENT_IN0_RELEASE_AUTO: ! 2673: event_pseudo.tme_keyboard_event_type = TME_KEYBOARD_EVENT_RELEASE; ! 2674: break; ! 2675: default: abort(); ! 2676: } ! 2677: event_pseudo.tme_keyboard_event_modifiers = 0; ! 2678: return (_tme_keyboard_buffer_copyin(buffer, &event_pseudo)); ! 2679: } ! 2680: ! 2681: /* if this event has a keycode: */ ! 2682: if (event->tme_keyboard_event_keycode ! 2683: != TME_KEYBOARD_KEYVAL_UNDEF) { ! 2684: ! 2685: /* see if this keycode is already pressed in this stage: */ ! 2686: other_keysym ! 2687: = ((struct tme_keysym_state *) ! 2688: tme_hash_lookup(buffer->tme_keyboard_buffer_int_in0_keycodes, ! 2689: (tme_hash_data_t) event->tme_keyboard_event_keycode)); ! 2690: ! 2691: /* if this keycode is already pressed by another keysym in this ! 2692: stage, release the other keysym first: */ ! 2693: if (other_keysym != NULL ! 2694: && other_keysym != keysym ! 2695: && TME_KEYBOARD_PRESSED_IN0(other_keysym)) { ! 2696: ! 2697: /* make the pseudoevent: */ ! 2698: event_pseudo.tme_keyboard_event_type ! 2699: = TME_KEYBOARD_IN0_RELEASE_EVENT(other_keysym->tme_keysym_state_in0_pressed); ! 2700: event_pseudo.tme_keyboard_event_time ! 2701: = _tme_keyboard_event_time_diff(event->tme_keyboard_event_time, -1); ! 2702: event_pseudo.tme_keyboard_event_modifiers ! 2703: = buffer->tme_keyboard_buffer_int_in0_modifiers; ! 2704: ! 2705: /* call the bottom half with this pseudoevent: */ ! 2706: rc = _tme_keyboard_buffer_in0_bottom(buffer, ! 2707: other_keysym, ! 2708: &event_pseudo); ! 2709: assert (rc == TME_OK); ! 2710: } ! 2711: ! 2712: /* if this is a press, remember that this keycode is pressed, ! 2713: else forget that this keycode is pressed: */ ! 2714: if (event->tme_keyboard_event_type == TME_KEYBOARD_EVENT_PRESS) { ! 2715: tme_hash_insert(buffer->tme_keyboard_buffer_int_in0_keycodes, ! 2716: (tme_hash_data_t) event->tme_keyboard_event_keycode, ! 2717: (tme_hash_data_t) keysym); ! 2718: } ! 2719: else { ! 2720: tme_hash_remove(buffer->tme_keyboard_buffer_int_in0_keycodes, ! 2721: (tme_hash_data_t) event->tme_keyboard_event_keycode); ! 2722: } ! 2723: } ! 2724: ! 2725: /* call the bottom half with this event: */ ! 2726: return (_tme_keyboard_buffer_in0_bottom(buffer, ! 2727: keysym, ! 2728: event)); ! 2729: } ! 2730: ! 2731: /* this copies a keyboard event into the buffer: */ ! 2732: int ! 2733: tme_keyboard_buffer_copyin(struct tme_keyboard_buffer *_buffer, ! 2734: const struct tme_keyboard_event *event) ! 2735: { ! 2736: struct tme_keyboard_buffer_int *buffer; ! 2737: ! 2738: /* recover our data structure: */ ! 2739: buffer = (struct tme_keyboard_buffer_int *) _buffer; ! 2740: ! 2741: /* run input stage zero: */ ! 2742: return (_tme_keyboard_buffer_in0(buffer, event)); ! 2743: } ! 2744: ! 2745: /* this copies a keyval out of a keyboard buffer: */ ! 2746: int ! 2747: tme_keyboard_buffer_copyout(struct tme_keyboard_buffer *buffer, ! 2748: struct tme_keyboard_event *event) ! 2749: { ! 2750: unsigned int buffer_tail, buffer_size_mask; ! 2751: ! 2752: buffer_tail = buffer->tme_keyboard_buffer_tail; ! 2753: buffer_size_mask = buffer->tme_keyboard_buffer_size - 1; ! 2754: ! 2755: /* if the buffer is empty: */ ! 2756: if (buffer_tail == buffer->tme_keyboard_buffer_head) { ! 2757: return (EAGAIN); ! 2758: } ! 2759: ! 2760: /* get an event out of the buffer: */ ! 2761: *event = buffer->tme_keyboard_buffer_events[buffer_tail]; ! 2762: ! 2763: /* advance the tail: */ ! 2764: buffer->tme_keyboard_buffer_tail = (buffer_tail + 1) & buffer_size_mask; ! 2765: return (TME_OK); ! 2766: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.