ddxBeep.c revision 706f2543
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{ 118DeviceIntPtr dev= (DeviceIntPtr)arg; 119KbdFeedbackPtr feed; 120KeybdCtrl * ctrl; 121XkbSrvInfoPtr xkbInfo; 122CARD32 next; 123int pitch,duration; 124int oldPitch,oldDuration; 125Atom 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) name= ledOn; 156 duration= SHORT_TONE; 157 pitch= HIGH_PITCH; 158 break; 159 case _BEEP_LED_OFF: 160 if (name==None) name= ledOff; 161 duration= SHORT_TONE; 162 pitch= LOW_PITCH; 163 if (!doesPitch && xkbInfo->beepCount<1) 164 next = SHORT_DELAY; 165 break; 166 167 /* When a Feature is turned on, we want an up-siren. 168 * When a Feature is turned off, we want a down-siren. 169 * If we cannot do pitch, we want a single beep for on and two 170 * beeps for off. 171 */ 172 case _BEEP_FEATURE_ON: 173 if (name==None) name= featureOn; 174 if (xkbInfo->beepCount<1) { 175 pitch= LOW_PITCH; 176 duration= VERY_LONG_TONE; 177 if (doesPitch) 178 next= SHORT_DELAY; 179 } 180 else { 181 pitch= MID_PITCH; 182 duration= SHORT_TONE; 183 } 184 break; 185 186 case _BEEP_FEATURE_OFF: 187 if (name==None) name= featureOff; 188 if (xkbInfo->beepCount<1) { 189 pitch= MID_PITCH; 190 if (doesPitch) 191 duration= VERY_LONG_TONE; 192 else duration= SHORT_TONE; 193 next= SHORT_DELAY; 194 } 195 else { 196 pitch= LOW_PITCH; 197 duration= SHORT_TONE; 198 } 199 break; 200 201 /* Two high beeps indicate an LED or Feature changed 202 * state, but that another LED or Feature is also on. 203 * [[[WDW - This is not in AccessDOS ]]] 204 */ 205 case _BEEP_LED_CHANGE: 206 if (name==None) name= ledChange; 207 case _BEEP_FEATURE_CHANGE: 208 if (name==None) name= featureChange; 209 duration= SHORT_TONE; 210 pitch= HIGH_PITCH; 211 if (xkbInfo->beepCount<1) { 212 next= SHORT_DELAY; 213 } 214 break; 215 216 /* Three high-pitched beeps are the warning that SlowKeys 217 * is going to be turned on or off. 218 */ 219 case _BEEP_SLOW_WARN: 220 if (name==None) name= slowWarn; 221 duration= SHORT_TONE; 222 pitch= HIGH_PITCH; 223 if (xkbInfo->beepCount<2) 224 next= SHORT_DELAY; 225 break; 226 227 /* Click on SlowKeys press and accept. 228 * Deep pitch when a SlowKey or BounceKey is rejected. 229 * [[[WDW - Rejects are not in AccessDOS ]]] 230 * If we cannot do pitch, we want single beeps. 231 */ 232 case _BEEP_SLOW_PRESS: 233 if (name==None) name= slowPress; 234 case _BEEP_SLOW_ACCEPT: 235 if (name==None) name= slowAccept; 236 case _BEEP_SLOW_RELEASE: 237 if (name==None) name= slowRelease; 238 duration= CLICK_DURATION; 239 pitch= CLICK_PITCH; 240 break; 241 case _BEEP_BOUNCE_REJECT: 242 if (name==None) name= bounceReject; 243 case _BEEP_SLOW_REJECT: 244 if (name==None) name= slowReject; 245 duration= SHORT_TONE; 246 pitch= DEEP_PITCH; 247 break; 248 249 /* Low followed by high pitch when a StickyKey is latched. 250 * High pitch when a StickyKey is locked. 251 * Low pitch when unlocked. 252 * If we cannot do pitch, two beeps for latch, nothing for 253 * lock, and two for unlock. 254 */ 255 case _BEEP_STICKY_LATCH: 256 if (name==None) name= stickyLatch; 257 duration= SHORT_TONE; 258 if (xkbInfo->beepCount<1) { 259 next= SHORT_DELAY; 260 pitch= LOW_PITCH; 261 } 262 else pitch= HIGH_PITCH; 263 break; 264 case _BEEP_STICKY_LOCK: 265 if (name==None) name= stickyLock; 266 if (doesPitch) { 267 duration= SHORT_TONE; 268 pitch= HIGH_PITCH; 269 } 270 break; 271 case _BEEP_STICKY_UNLOCK: 272 if (name==None) name= stickyUnlock; 273 duration= SHORT_TONE; 274 pitch= LOW_PITCH; 275 if (!doesPitch && xkbInfo->beepCount<1) 276 next = SHORT_DELAY; 277 break; 278 } 279 if (timer == NULL && duration>0) { 280 CARD32 starttime = GetTimeInMillis(); 281 CARD32 elapsedtime; 282 283 ctrl->bell_duration= duration; 284 ctrl->bell_pitch= pitch; 285 if (xkbInfo->beepCount==0) { 286 XkbHandleBell(0,0,dev,ctrl->bell,(pointer)ctrl,KbdFeedbackClass,name,None, 287 NULL); 288 } 289 else if (xkbInfo->desc->ctrls->enabled_ctrls&XkbAudibleBellMask) { 290 (*dev->kbdfeed->BellProc)(ctrl->bell,dev,(pointer)ctrl,KbdFeedbackClass); 291 } 292 ctrl->bell_duration= oldDuration; 293 ctrl->bell_pitch= oldPitch; 294 xkbInfo->beepCount++; 295 296 /* Some DDX schedule the beep and return immediately, others don't 297 return until the beep is completed. We measure the time and if 298 it's less than the beep duration, make sure not to schedule the 299 next beep until after the current one finishes. */ 300 301 elapsedtime = GetTimeInMillis(); 302 if (elapsedtime > starttime) { /* watch out for millisecond counter 303 overflow! */ 304 elapsedtime -= starttime; 305 } else { 306 elapsedtime = 0; 307 } 308 if (elapsedtime < duration) { 309 next += duration - elapsedtime; 310 } 311 312 } 313 return next; 314} 315 316int 317XkbDDXAccessXBeep(DeviceIntPtr dev,unsigned what,unsigned which) 318{ 319XkbSrvInfoRec *xkbInfo= dev->key->xkbInfo; 320CARD32 next; 321 322 xkbInfo->beepType= what; 323 xkbInfo->beepCount= 0; 324 next= _XkbDDXBeepExpire(NULL,0,(pointer)dev); 325 if (next>0) { 326 xkbInfo->beepTimer= TimerSet(xkbInfo->beepTimer, 327 0, next, 328 _XkbDDXBeepExpire, (pointer)dev); 329 } 330 return 1; 331} 332