xref: /OK3568_Linux_fs/external/xserver/xkb/ddxBeep.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 <X11/X.h>
33 #include <X11/Xproto.h>
34 #include <X11/keysym.h>
35 #include "inputstr.h"
36 #include "scrnintstr.h"
37 #include "windowstr.h"
38 #include <xkbsrv.h>
39 #include <X11/extensions/XI.h>
40 
41 /*#define FALLING_TONE	1*/
42 /*#define RISING_TONE	1*/
43 #define FALLING_TONE	10
44 #define RISING_TONE	10
45 #define	SHORT_TONE	50
46 #define	SHORT_DELAY	60
47 #define	LONG_TONE	75
48 #define	VERY_LONG_TONE	100
49 #define	LONG_DELAY	85
50 #define CLICK_DURATION	1
51 
52 #define	DEEP_PITCH	250
53 #define	LOW_PITCH	500
54 #define	MID_PITCH	1000
55 #define	HIGH_PITCH	2000
56 #define CLICK_PITCH	1500
57 
58 static unsigned long atomGeneration = 0;
59 static Atom featureOn;
60 static Atom featureOff;
61 static Atom featureChange;
62 static Atom ledOn;
63 static Atom ledOff;
64 static Atom ledChange;
65 static Atom slowWarn;
66 static Atom slowPress;
67 static Atom slowReject;
68 static Atom slowAccept;
69 static Atom slowRelease;
70 static Atom stickyLatch;
71 static Atom stickyLock;
72 static Atom stickyUnlock;
73 static Atom bounceReject;
74 static char doesPitch = 1;
75 
76 #define	FEATURE_ON	"AX_FeatureOn"
77 #define	FEATURE_OFF	"AX_FeatureOff"
78 #define	FEATURE_CHANGE	"AX_FeatureChange"
79 #define	LED_ON		"AX_IndicatorOn"
80 #define	LED_OFF		"AX_IndicatorOff"
81 #define	LED_CHANGE	"AX_IndicatorChange"
82 #define	SLOW_WARN	"AX_SlowKeysWarning"
83 #define	SLOW_PRESS	"AX_SlowKeyPress"
84 #define	SLOW_REJECT	"AX_SlowKeyReject"
85 #define	SLOW_ACCEPT	"AX_SlowKeyAccept"
86 #define	SLOW_RELEASE	"AX_SlowKeyRelease"
87 #define	STICKY_LATCH	"AX_StickyLatch"
88 #define	STICKY_LOCK	"AX_StickyLock"
89 #define	STICKY_UNLOCK	"AX_StickyUnlock"
90 #define	BOUNCE_REJECT	"AX_BounceKeyReject"
91 
92 #define	MAKE_ATOM(a)	MakeAtom(a,sizeof(a)-1,TRUE)
93 
94 static void
_XkbDDXBeepInitAtoms(void)95 _XkbDDXBeepInitAtoms(void)
96 {
97     featureOn = MAKE_ATOM(FEATURE_ON);
98     featureOff = MAKE_ATOM(FEATURE_OFF);
99     featureChange = MAKE_ATOM(FEATURE_CHANGE);
100     ledOn = MAKE_ATOM(LED_ON);
101     ledOff = MAKE_ATOM(LED_OFF);
102     ledChange = MAKE_ATOM(LED_CHANGE);
103     slowWarn = MAKE_ATOM(SLOW_WARN);
104     slowPress = MAKE_ATOM(SLOW_PRESS);
105     slowReject = MAKE_ATOM(SLOW_REJECT);
106     slowAccept = MAKE_ATOM(SLOW_ACCEPT);
107     slowRelease = MAKE_ATOM(SLOW_RELEASE);
108     stickyLatch = MAKE_ATOM(STICKY_LATCH);
109     stickyLock = MAKE_ATOM(STICKY_LOCK);
110     stickyUnlock = MAKE_ATOM(STICKY_UNLOCK);
111     bounceReject = MAKE_ATOM(BOUNCE_REJECT);
112     return;
113 }
114 
115 static CARD32
_XkbDDXBeepExpire(OsTimerPtr timer,CARD32 now,void * arg)116 _XkbDDXBeepExpire(OsTimerPtr timer, CARD32 now, void *arg)
117 {
118     DeviceIntPtr dev = (DeviceIntPtr) arg;
119     KbdFeedbackPtr feed;
120     KeybdCtrl *ctrl;
121     XkbSrvInfoPtr xkbInfo;
122     CARD32 next;
123     int pitch, duration;
124     int oldPitch, oldDuration;
125     Atom name;
126 
127     if ((dev == NULL) || (dev->key == NULL) || (dev->key->xkbInfo == NULL) ||
128         (dev->kbdfeed == NULL))
129         return 0;
130     if (atomGeneration != serverGeneration) {
131         _XkbDDXBeepInitAtoms();
132         atomGeneration = serverGeneration;
133     }
134 
135     feed = dev->kbdfeed;
136     ctrl = &feed->ctrl;
137     xkbInfo = dev->key->xkbInfo;
138     next = 0;
139     pitch = oldPitch = ctrl->bell_pitch;
140     duration = oldDuration = ctrl->bell_duration;
141     name = None;
142     switch (xkbInfo->beepType) {
143     default:
144         ErrorF("[xkb] Unknown beep type %d\n", xkbInfo->beepType);
145     case _BEEP_NONE:
146         duration = 0;
147         break;
148 
149         /* When an LED is turned on, we want a high-pitched beep.
150          * When the LED it turned off, we want a low-pitched beep.
151          * If we cannot do pitch, we want a single beep for on and two
152          * beeps for off.
153          */
154     case _BEEP_LED_ON:
155         if (name == None)
156             name = ledOn;
157         duration = SHORT_TONE;
158         pitch = HIGH_PITCH;
159         break;
160     case _BEEP_LED_OFF:
161         if (name == None)
162             name = ledOff;
163         duration = SHORT_TONE;
164         pitch = LOW_PITCH;
165         if (!doesPitch && xkbInfo->beepCount < 1)
166             next = SHORT_DELAY;
167         break;
168 
169         /* When a Feature is turned on, we want an up-siren.
170          * When a Feature is turned off, we want a down-siren.
171          * If we cannot do pitch, we want a single beep for on and two
172          * beeps for off.
173          */
174     case _BEEP_FEATURE_ON:
175         if (name == None)
176             name = featureOn;
177         if (xkbInfo->beepCount < 1) {
178             pitch = LOW_PITCH;
179             duration = VERY_LONG_TONE;
180             if (doesPitch)
181                 next = SHORT_DELAY;
182         }
183         else {
184             pitch = MID_PITCH;
185             duration = SHORT_TONE;
186         }
187         break;
188 
189     case _BEEP_FEATURE_OFF:
190         if (name == None)
191             name = featureOff;
192         if (xkbInfo->beepCount < 1) {
193             pitch = MID_PITCH;
194             if (doesPitch)
195                 duration = VERY_LONG_TONE;
196             else
197                 duration = SHORT_TONE;
198             next = SHORT_DELAY;
199         }
200         else {
201             pitch = LOW_PITCH;
202             duration = SHORT_TONE;
203         }
204         break;
205 
206         /* Two high beeps indicate an LED or Feature changed
207          * state, but that another LED or Feature is also on.
208          * [[[WDW - This is not in AccessDOS ]]]
209          */
210     case _BEEP_LED_CHANGE:
211         if (name == None)
212             name = ledChange;
213     case _BEEP_FEATURE_CHANGE:
214         if (name == None)
215             name = featureChange;
216         duration = SHORT_TONE;
217         pitch = HIGH_PITCH;
218         if (xkbInfo->beepCount < 1) {
219             next = SHORT_DELAY;
220         }
221         break;
222 
223         /* Three high-pitched beeps are the warning that SlowKeys
224          * is going to be turned on or off.
225          */
226     case _BEEP_SLOW_WARN:
227         if (name == None)
228             name = slowWarn;
229         duration = SHORT_TONE;
230         pitch = HIGH_PITCH;
231         if (xkbInfo->beepCount < 2)
232             next = SHORT_DELAY;
233         break;
234 
235         /* Click on SlowKeys press and accept.
236          * Deep pitch when a SlowKey or BounceKey is rejected.
237          * [[[WDW - Rejects are not in AccessDOS ]]]
238          * If we cannot do pitch, we want single beeps.
239          */
240     case _BEEP_SLOW_PRESS:
241         if (name == None)
242             name = slowPress;
243     case _BEEP_SLOW_ACCEPT:
244         if (name == None)
245             name = slowAccept;
246     case _BEEP_SLOW_RELEASE:
247         if (name == None)
248             name = slowRelease;
249         duration = CLICK_DURATION;
250         pitch = CLICK_PITCH;
251         break;
252     case _BEEP_BOUNCE_REJECT:
253         if (name == None)
254             name = bounceReject;
255     case _BEEP_SLOW_REJECT:
256         if (name == None)
257             name = slowReject;
258         duration = SHORT_TONE;
259         pitch = DEEP_PITCH;
260         break;
261 
262         /* Low followed by high pitch when a StickyKey is latched.
263          * High pitch when a StickyKey is locked.
264          * Low pitch when unlocked.
265          * If we cannot do pitch, two beeps for latch, nothing for
266          * lock, and two for unlock.
267          */
268     case _BEEP_STICKY_LATCH:
269         if (name == None)
270             name = stickyLatch;
271         duration = SHORT_TONE;
272         if (xkbInfo->beepCount < 1) {
273             next = SHORT_DELAY;
274             pitch = LOW_PITCH;
275         }
276         else
277             pitch = HIGH_PITCH;
278         break;
279     case _BEEP_STICKY_LOCK:
280         if (name == None)
281             name = stickyLock;
282         if (doesPitch) {
283             duration = SHORT_TONE;
284             pitch = HIGH_PITCH;
285         }
286         break;
287     case _BEEP_STICKY_UNLOCK:
288         if (name == None)
289             name = stickyUnlock;
290         duration = SHORT_TONE;
291         pitch = LOW_PITCH;
292         if (!doesPitch && xkbInfo->beepCount < 1)
293             next = SHORT_DELAY;
294         break;
295     }
296     if (timer == NULL && duration > 0) {
297         CARD32 starttime = GetTimeInMillis();
298         CARD32 elapsedtime;
299 
300         ctrl->bell_duration = duration;
301         ctrl->bell_pitch = pitch;
302         if (xkbInfo->beepCount == 0) {
303             XkbHandleBell(0, 0, dev, ctrl->bell, (void *) ctrl,
304                           KbdFeedbackClass, name, None, NULL);
305         }
306         else if (xkbInfo->desc->ctrls->enabled_ctrls & XkbAudibleBellMask) {
307             (*dev->kbdfeed->BellProc) (ctrl->bell, dev, (void *) ctrl,
308                                        KbdFeedbackClass);
309         }
310         ctrl->bell_duration = oldDuration;
311         ctrl->bell_pitch = oldPitch;
312         xkbInfo->beepCount++;
313 
314         /* Some DDX schedule the beep and return immediately, others don't
315            return until the beep is completed.  We measure the time and if
316            it's less than the beep duration, make sure not to schedule the
317            next beep until after the current one finishes. */
318 
319         elapsedtime = GetTimeInMillis();
320         if (elapsedtime > starttime) {  /* watch out for millisecond counter
321                                            overflow! */
322             elapsedtime -= starttime;
323         }
324         else {
325             elapsedtime = 0;
326         }
327         if (elapsedtime < duration) {
328             next += duration - elapsedtime;
329         }
330 
331     }
332     return next;
333 }
334 
335 int
XkbDDXAccessXBeep(DeviceIntPtr dev,unsigned what,unsigned which)336 XkbDDXAccessXBeep(DeviceIntPtr dev, unsigned what, unsigned which)
337 {
338     XkbSrvInfoRec *xkbInfo = dev->key->xkbInfo;
339     CARD32 next;
340 
341     xkbInfo->beepType = what;
342     xkbInfo->beepCount = 0;
343     next = _XkbDDXBeepExpire(NULL, 0, (void *) dev);
344     if (next > 0) {
345         xkbInfo->beepTimer = TimerSet(xkbInfo->beepTimer,
346                                       0, next,
347                                       _XkbDDXBeepExpire, (void *) dev);
348     }
349     return 1;
350 }
351