1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE 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
46 void
XkbProcessKeyboardEvent(DeviceEvent * event,DeviceIntPtr keybd)47 XkbProcessKeyboardEvent(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
163 void
ProcessKeyboardEvent(InternalEvent * ev,DeviceIntPtr keybd)164 ProcessKeyboardEvent(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