Imported Upstream version 1.15.1
[deb_xorg-server.git] / xkb / ddxBeep.c
CommitLineData
a09e091a
JB
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 <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
58static unsigned long atomGeneration = 0;
59static Atom featureOn;
60static Atom featureOff;
61static Atom featureChange;
62static Atom ledOn;
63static Atom ledOff;
64static Atom ledChange;
65static Atom slowWarn;
66static Atom slowPress;
67static Atom slowReject;
68static Atom slowAccept;
69static Atom slowRelease;
70static Atom stickyLatch;
71static Atom stickyLock;
72static Atom stickyUnlock;
73static Atom bounceReject;
74static 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
94static 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
115static CARD32
116_XkbDDXBeepExpire(OsTimerPtr timer, CARD32 now, pointer 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, (pointer) ctrl,
304 KbdFeedbackClass, name, None, NULL);
305 }
306 else if (xkbInfo->desc->ctrls->enabled_ctrls & XkbAudibleBellMask) {
307 (*dev->kbdfeed->BellProc) (ctrl->bell, dev, (pointer) 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
335int
336XkbDDXAccessXBeep(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, (pointer) dev);
344 if (next > 0) {
345 xkbInfo->beepTimer = TimerSet(xkbInfo->beepTimer,
346 0, next,
347 _XkbDDXBeepExpire, (pointer) dev);
348 }
349 return 1;
350}