xref: /OK3568_Linux_fs/external/xserver/xkb/xkbPrKeyEv.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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