1/************************************************************ 2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25********************************************************/ 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#endif 30 31#include <stdio.h> 32#include <math.h> 33#include <X11/X.h> 34#include <X11/Xproto.h> 35#include <X11/keysym.h> 36#include "misc.h" 37#include "inputstr.h" 38#include "exevents.h" 39#include "eventstr.h" 40#include <xkbsrv.h> 41#include <ctype.h> 42#include "events.h" 43 44/***====================================================================***/ 45 46void 47XkbProcessKeyboardEvent(DeviceEvent *event, DeviceIntPtr keybd) 48{ 49 KeyClassPtr keyc = keybd->key; 50 XkbSrvInfoPtr xkbi; 51 int key; 52 XkbBehavior behavior; 53 unsigned ndx; 54 55 xkbi = keyc->xkbInfo; 56 key = event->detail.key; 57 if (xkbDebugFlags & 0x8) 58 DebugF("[xkb] XkbPKE: Key %d %s\n", key, 59 (event->type == ET_KeyPress ? "down" : "up")); 60 61 if (xkbi->repeatKey == key && event->type == ET_KeyRelease && 62 !(xkbi->desc->ctrls->enabled_ctrls & XkbRepeatKeysMask)) 63 AccessXCancelRepeatKey(xkbi, key); 64 65 behavior = xkbi->desc->server->behaviors[key]; 66 /* The "permanent" flag indicates a hard-wired behavior that occurs */ 67 /* below XKB, such as a key that physically locks. XKB does not */ 68 /* do anything to implement the behavior, but it *does* report that */ 69 /* key is hardwired */ 70 71 if (!(behavior.type & XkbKB_Permanent)) { 72 switch (behavior.type) { 73 case XkbKB_Default: 74 /* Neither of these should happen in practice, but ignore them 75 anyway. */ 76 if (event->type == ET_KeyPress && !event->key_repeat && 77 key_is_down(keybd, key, KEY_PROCESSED)) 78 return; 79 else if (event->type == ET_KeyRelease && 80 !key_is_down(keybd, key, KEY_PROCESSED)) 81 return; 82 break; 83 case XkbKB_Lock: 84 if (event->type == ET_KeyRelease) 85 return; 86 else if (key_is_down(keybd, key, KEY_PROCESSED)) 87 event->type = ET_KeyRelease; 88 break; 89 case XkbKB_RadioGroup: 90 ndx = (behavior.data & (~XkbKB_RGAllowNone)); 91 if (ndx < xkbi->nRadioGroups) { 92 XkbRadioGroupPtr rg; 93 94 if (event->type == ET_KeyRelease) 95 return; 96 97 rg = &xkbi->radioGroups[ndx]; 98 if (rg->currentDown == event->detail.key) { 99 if (behavior.data & XkbKB_RGAllowNone) { 100 event->type = ET_KeyRelease; 101 XkbHandleActions(keybd, keybd, event); 102 rg->currentDown = 0; 103 } 104 return; 105 } 106 if (rg->currentDown != 0) { 107 int tmpkey = event->detail.key; 108 109 event->type = ET_KeyRelease; 110 event->detail.key = rg->currentDown; 111 XkbHandleActions(keybd, keybd, event); 112 event->type = ET_KeyPress; 113 event->detail.key = tmpkey; 114 } 115 rg->currentDown = key; 116 } 117 else 118 ErrorF("[xkb] InternalError! Illegal radio group %d\n", ndx); 119 break; 120 case XkbKB_Overlay1: 121 case XkbKB_Overlay2: 122 { 123 unsigned which; 124 unsigned overlay_active_now; 125 unsigned is_keyrelease = (event->type == ET_KeyRelease) ? 1 : 0; 126 /* Remembers whether the key was pressed while overlay was down, 127 * for when overlay is already released, but the key is not. */ 128 unsigned key_was_overlaid = 0; 129 130 if (behavior.type == XkbKB_Overlay1) 131 which = XkbOverlay1Mask; 132 else 133 which = XkbOverlay2Mask; 134 overlay_active_now = (xkbi->desc->ctrls->enabled_ctrls & which) ? 1 : 0; 135 136 if ((unsigned char)key == key) { 137 key_was_overlaid = BitIsOn(xkbi->overlay_perkey_state, key); 138 if (!is_keyrelease) { 139 if (overlay_active_now) 140 SetBit(xkbi->overlay_perkey_state, key); 141 } else { 142 if (key_was_overlaid) 143 ClearBit(xkbi->overlay_perkey_state, key); 144 } 145 } 146 147 if ((overlay_active_now || key_was_overlaid) && 148 (behavior.data >= xkbi->desc->min_key_code) && 149 (behavior.data <= xkbi->desc->max_key_code)) { 150 event->detail.key = behavior.data; 151 } 152 } 153 break; 154 default: 155 ErrorF("[xkb] unknown key behavior 0x%04x\n", behavior.type); 156 break; 157 } 158 } 159 XkbHandleActions(keybd, keybd, event); 160 return; 161} 162 163void 164ProcessKeyboardEvent(InternalEvent *ev, DeviceIntPtr keybd) 165{ 166 167 KeyClassPtr keyc = keybd->key; 168 XkbSrvInfoPtr xkbi = NULL; 169 ProcessInputProc backup_proc; 170 xkbDeviceInfoPtr xkb_priv = XKBDEVICEINFO(keybd); 171 DeviceEvent *event = &ev->device_event; 172 int is_press = (event->type == ET_KeyPress); 173 int is_release = (event->type == ET_KeyRelease); 174 175 /* We're only interested in key events. */ 176 if (!is_press && !is_release) { 177 UNWRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc); 178 keybd->public.processInputProc(ev, keybd); 179 COND_WRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc, 180 xkbUnwrapProc); 181 return; 182 } 183 184 xkbi = keyc->xkbInfo; 185 186 /* If AccessX filters are active, then pass it through to 187 * AccessXFilter{Press,Release}Event; else, punt to 188 * XkbProcessKeyboardEvent. 189 * 190 * If AXF[PK]E don't intercept anything (which they probably won't), 191 * they'll punt through XPKE anyway. */ 192 if ((xkbi->desc->ctrls->enabled_ctrls & XkbAllFilteredEventsMask)) { 193 if (is_press) 194 AccessXFilterPressEvent(event, keybd); 195 else if (is_release) 196 AccessXFilterReleaseEvent(event, keybd); 197 return; 198 } 199 else { 200 XkbProcessKeyboardEvent(event, keybd); 201 } 202 203 return; 204} 205