1706f2543Smrg/************************************************************ 2706f2543SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3706f2543Smrg 4706f2543SmrgPermission to use, copy, modify, and distribute this 5706f2543Smrgsoftware and its documentation for any purpose and without 6706f2543Smrgfee is hereby granted, provided that the above copyright 7706f2543Smrgnotice appear in all copies and that both that copyright 8706f2543Smrgnotice and this permission notice appear in supporting 9706f2543Smrgdocumentation, and that the name of Silicon Graphics not be 10706f2543Smrgused in advertising or publicity pertaining to distribution 11706f2543Smrgof the software without specific prior written permission. 12706f2543SmrgSilicon Graphics makes no representation about the suitability 13706f2543Smrgof this software for any purpose. It is provided "as is" 14706f2543Smrgwithout any express or implied warranty. 15706f2543Smrg 16706f2543SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18706f2543SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19706f2543SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20706f2543SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21706f2543SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22706f2543SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23706f2543SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 24706f2543Smrg 25706f2543Smrg********************************************************/ 26706f2543Smrg 27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 28706f2543Smrg#include <dix-config.h> 29706f2543Smrg#endif 30706f2543Smrg 31706f2543Smrg#include <stdio.h> 32706f2543Smrg#include <X11/X.h> 33706f2543Smrg#include <X11/Xproto.h> 34706f2543Smrg#include <X11/keysym.h> 35706f2543Smrg#include "inputstr.h" 36706f2543Smrg#include "scrnintstr.h" 37706f2543Smrg#include "windowstr.h" 38706f2543Smrg#include <xkbsrv.h> 39706f2543Smrg#include <X11/extensions/XI.h> 40706f2543Smrg 41706f2543Smrg/*#define FALLING_TONE 1*/ 42706f2543Smrg/*#define RISING_TONE 1*/ 43706f2543Smrg#define FALLING_TONE 10 44706f2543Smrg#define RISING_TONE 10 45706f2543Smrg#define SHORT_TONE 50 46706f2543Smrg#define SHORT_DELAY 60 47706f2543Smrg#define LONG_TONE 75 48706f2543Smrg#define VERY_LONG_TONE 100 49706f2543Smrg#define LONG_DELAY 85 50706f2543Smrg#define CLICK_DURATION 1 51706f2543Smrg 52706f2543Smrg#define DEEP_PITCH 250 53706f2543Smrg#define LOW_PITCH 500 54706f2543Smrg#define MID_PITCH 1000 55706f2543Smrg#define HIGH_PITCH 2000 56706f2543Smrg#define CLICK_PITCH 1500 57706f2543Smrg 58706f2543Smrgstatic unsigned long atomGeneration= 0; 59706f2543Smrgstatic Atom featureOn; 60706f2543Smrgstatic Atom featureOff; 61706f2543Smrgstatic Atom featureChange; 62706f2543Smrgstatic Atom ledOn; 63706f2543Smrgstatic Atom ledOff; 64706f2543Smrgstatic Atom ledChange; 65706f2543Smrgstatic Atom slowWarn; 66706f2543Smrgstatic Atom slowPress; 67706f2543Smrgstatic Atom slowReject; 68706f2543Smrgstatic Atom slowAccept; 69706f2543Smrgstatic Atom slowRelease; 70706f2543Smrgstatic Atom stickyLatch; 71706f2543Smrgstatic Atom stickyLock; 72706f2543Smrgstatic Atom stickyUnlock; 73706f2543Smrgstatic Atom bounceReject; 74706f2543Smrgstatic char doesPitch = 1; 75706f2543Smrg 76706f2543Smrg#define FEATURE_ON "AX_FeatureOn" 77706f2543Smrg#define FEATURE_OFF "AX_FeatureOff" 78706f2543Smrg#define FEATURE_CHANGE "AX_FeatureChange" 79706f2543Smrg#define LED_ON "AX_IndicatorOn" 80706f2543Smrg#define LED_OFF "AX_IndicatorOff" 81706f2543Smrg#define LED_CHANGE "AX_IndicatorChange" 82706f2543Smrg#define SLOW_WARN "AX_SlowKeysWarning" 83706f2543Smrg#define SLOW_PRESS "AX_SlowKeyPress" 84706f2543Smrg#define SLOW_REJECT "AX_SlowKeyReject" 85706f2543Smrg#define SLOW_ACCEPT "AX_SlowKeyAccept" 86706f2543Smrg#define SLOW_RELEASE "AX_SlowKeyRelease" 87706f2543Smrg#define STICKY_LATCH "AX_StickyLatch" 88706f2543Smrg#define STICKY_LOCK "AX_StickyLock" 89706f2543Smrg#define STICKY_UNLOCK "AX_StickyUnlock" 90706f2543Smrg#define BOUNCE_REJECT "AX_BounceKeyReject" 91706f2543Smrg 92706f2543Smrg#define MAKE_ATOM(a) MakeAtom(a,sizeof(a)-1,TRUE) 93706f2543Smrg 94706f2543Smrgstatic void 95706f2543Smrg_XkbDDXBeepInitAtoms(void) 96706f2543Smrg{ 97706f2543Smrg featureOn= MAKE_ATOM(FEATURE_ON); 98706f2543Smrg featureOff= MAKE_ATOM(FEATURE_OFF); 99706f2543Smrg featureChange= MAKE_ATOM(FEATURE_CHANGE); 100706f2543Smrg ledOn= MAKE_ATOM(LED_ON); 101706f2543Smrg ledOff= MAKE_ATOM(LED_OFF); 102706f2543Smrg ledChange= MAKE_ATOM(LED_CHANGE); 103706f2543Smrg slowWarn= MAKE_ATOM(SLOW_WARN); 104706f2543Smrg slowPress= MAKE_ATOM(SLOW_PRESS); 105706f2543Smrg slowReject= MAKE_ATOM(SLOW_REJECT); 106706f2543Smrg slowAccept= MAKE_ATOM(SLOW_ACCEPT); 107706f2543Smrg slowRelease= MAKE_ATOM(SLOW_RELEASE); 108706f2543Smrg stickyLatch= MAKE_ATOM(STICKY_LATCH); 109706f2543Smrg stickyLock= MAKE_ATOM(STICKY_LOCK); 110706f2543Smrg stickyUnlock= MAKE_ATOM(STICKY_UNLOCK); 111706f2543Smrg bounceReject= MAKE_ATOM(BOUNCE_REJECT); 112706f2543Smrg return; 113706f2543Smrg} 114706f2543Smrg 115706f2543Smrgstatic CARD32 116706f2543Smrg_XkbDDXBeepExpire(OsTimerPtr timer,CARD32 now,pointer arg) 117706f2543Smrg{ 118706f2543SmrgDeviceIntPtr dev= (DeviceIntPtr)arg; 119706f2543SmrgKbdFeedbackPtr feed; 120706f2543SmrgKeybdCtrl * ctrl; 121706f2543SmrgXkbSrvInfoPtr xkbInfo; 122706f2543SmrgCARD32 next; 123706f2543Smrgint pitch,duration; 124706f2543Smrgint oldPitch,oldDuration; 125706f2543SmrgAtom name; 126706f2543Smrg 127706f2543Smrg if ((dev==NULL)||(dev->key==NULL)||(dev->key->xkbInfo==NULL)|| 128706f2543Smrg (dev->kbdfeed==NULL)) 129706f2543Smrg return 0; 130706f2543Smrg if (atomGeneration!=serverGeneration) { 131706f2543Smrg _XkbDDXBeepInitAtoms(); 132706f2543Smrg atomGeneration= serverGeneration; 133706f2543Smrg } 134706f2543Smrg 135706f2543Smrg feed= dev->kbdfeed; 136706f2543Smrg ctrl= &feed->ctrl; 137706f2543Smrg xkbInfo= dev->key->xkbInfo; 138706f2543Smrg next= 0; 139706f2543Smrg pitch= oldPitch= ctrl->bell_pitch; 140706f2543Smrg duration= oldDuration= ctrl->bell_duration; 141706f2543Smrg name= None; 142706f2543Smrg switch (xkbInfo->beepType) { 143706f2543Smrg default: 144706f2543Smrg ErrorF("[xkb] Unknown beep type %d\n",xkbInfo->beepType); 145706f2543Smrg case _BEEP_NONE: 146706f2543Smrg duration= 0; 147706f2543Smrg break; 148706f2543Smrg 149706f2543Smrg /* When an LED is turned on, we want a high-pitched beep. 150706f2543Smrg * When the LED it turned off, we want a low-pitched beep. 151706f2543Smrg * If we cannot do pitch, we want a single beep for on and two 152706f2543Smrg * beeps for off. 153706f2543Smrg */ 154706f2543Smrg case _BEEP_LED_ON: 155706f2543Smrg if (name==None) name= ledOn; 156706f2543Smrg duration= SHORT_TONE; 157706f2543Smrg pitch= HIGH_PITCH; 158706f2543Smrg break; 159706f2543Smrg case _BEEP_LED_OFF: 160706f2543Smrg if (name==None) name= ledOff; 161706f2543Smrg duration= SHORT_TONE; 162706f2543Smrg pitch= LOW_PITCH; 163706f2543Smrg if (!doesPitch && xkbInfo->beepCount<1) 164706f2543Smrg next = SHORT_DELAY; 165706f2543Smrg break; 166706f2543Smrg 167706f2543Smrg /* When a Feature is turned on, we want an up-siren. 168706f2543Smrg * When a Feature is turned off, we want a down-siren. 169706f2543Smrg * If we cannot do pitch, we want a single beep for on and two 170706f2543Smrg * beeps for off. 171706f2543Smrg */ 172706f2543Smrg case _BEEP_FEATURE_ON: 173706f2543Smrg if (name==None) name= featureOn; 174706f2543Smrg if (xkbInfo->beepCount<1) { 175706f2543Smrg pitch= LOW_PITCH; 176706f2543Smrg duration= VERY_LONG_TONE; 177706f2543Smrg if (doesPitch) 178706f2543Smrg next= SHORT_DELAY; 179706f2543Smrg } 180706f2543Smrg else { 181706f2543Smrg pitch= MID_PITCH; 182706f2543Smrg duration= SHORT_TONE; 183706f2543Smrg } 184706f2543Smrg break; 185706f2543Smrg 186706f2543Smrg case _BEEP_FEATURE_OFF: 187706f2543Smrg if (name==None) name= featureOff; 188706f2543Smrg if (xkbInfo->beepCount<1) { 189706f2543Smrg pitch= MID_PITCH; 190706f2543Smrg if (doesPitch) 191706f2543Smrg duration= VERY_LONG_TONE; 192706f2543Smrg else duration= SHORT_TONE; 193706f2543Smrg next= SHORT_DELAY; 194706f2543Smrg } 195706f2543Smrg else { 196706f2543Smrg pitch= LOW_PITCH; 197706f2543Smrg duration= SHORT_TONE; 198706f2543Smrg } 199706f2543Smrg break; 200706f2543Smrg 201706f2543Smrg /* Two high beeps indicate an LED or Feature changed 202706f2543Smrg * state, but that another LED or Feature is also on. 203706f2543Smrg * [[[WDW - This is not in AccessDOS ]]] 204706f2543Smrg */ 205706f2543Smrg case _BEEP_LED_CHANGE: 206706f2543Smrg if (name==None) name= ledChange; 207706f2543Smrg case _BEEP_FEATURE_CHANGE: 208706f2543Smrg if (name==None) name= featureChange; 209706f2543Smrg duration= SHORT_TONE; 210706f2543Smrg pitch= HIGH_PITCH; 211706f2543Smrg if (xkbInfo->beepCount<1) { 212706f2543Smrg next= SHORT_DELAY; 213706f2543Smrg } 214706f2543Smrg break; 215706f2543Smrg 216706f2543Smrg /* Three high-pitched beeps are the warning that SlowKeys 217706f2543Smrg * is going to be turned on or off. 218706f2543Smrg */ 219706f2543Smrg case _BEEP_SLOW_WARN: 220706f2543Smrg if (name==None) name= slowWarn; 221706f2543Smrg duration= SHORT_TONE; 222706f2543Smrg pitch= HIGH_PITCH; 223706f2543Smrg if (xkbInfo->beepCount<2) 224706f2543Smrg next= SHORT_DELAY; 225706f2543Smrg break; 226706f2543Smrg 227706f2543Smrg /* Click on SlowKeys press and accept. 228706f2543Smrg * Deep pitch when a SlowKey or BounceKey is rejected. 229706f2543Smrg * [[[WDW - Rejects are not in AccessDOS ]]] 230706f2543Smrg * If we cannot do pitch, we want single beeps. 231706f2543Smrg */ 232706f2543Smrg case _BEEP_SLOW_PRESS: 233706f2543Smrg if (name==None) name= slowPress; 234706f2543Smrg case _BEEP_SLOW_ACCEPT: 235706f2543Smrg if (name==None) name= slowAccept; 236706f2543Smrg case _BEEP_SLOW_RELEASE: 237706f2543Smrg if (name==None) name= slowRelease; 238706f2543Smrg duration= CLICK_DURATION; 239706f2543Smrg pitch= CLICK_PITCH; 240706f2543Smrg break; 241706f2543Smrg case _BEEP_BOUNCE_REJECT: 242706f2543Smrg if (name==None) name= bounceReject; 243706f2543Smrg case _BEEP_SLOW_REJECT: 244706f2543Smrg if (name==None) name= slowReject; 245706f2543Smrg duration= SHORT_TONE; 246706f2543Smrg pitch= DEEP_PITCH; 247706f2543Smrg break; 248706f2543Smrg 249706f2543Smrg /* Low followed by high pitch when a StickyKey is latched. 250706f2543Smrg * High pitch when a StickyKey is locked. 251706f2543Smrg * Low pitch when unlocked. 252706f2543Smrg * If we cannot do pitch, two beeps for latch, nothing for 253706f2543Smrg * lock, and two for unlock. 254706f2543Smrg */ 255706f2543Smrg case _BEEP_STICKY_LATCH: 256706f2543Smrg if (name==None) name= stickyLatch; 257706f2543Smrg duration= SHORT_TONE; 258706f2543Smrg if (xkbInfo->beepCount<1) { 259706f2543Smrg next= SHORT_DELAY; 260706f2543Smrg pitch= LOW_PITCH; 261706f2543Smrg } 262706f2543Smrg else pitch= HIGH_PITCH; 263706f2543Smrg break; 264706f2543Smrg case _BEEP_STICKY_LOCK: 265706f2543Smrg if (name==None) name= stickyLock; 266706f2543Smrg if (doesPitch) { 267706f2543Smrg duration= SHORT_TONE; 268706f2543Smrg pitch= HIGH_PITCH; 269706f2543Smrg } 270706f2543Smrg break; 271706f2543Smrg case _BEEP_STICKY_UNLOCK: 272706f2543Smrg if (name==None) name= stickyUnlock; 273706f2543Smrg duration= SHORT_TONE; 274706f2543Smrg pitch= LOW_PITCH; 275706f2543Smrg if (!doesPitch && xkbInfo->beepCount<1) 276706f2543Smrg next = SHORT_DELAY; 277706f2543Smrg break; 278706f2543Smrg } 279706f2543Smrg if (timer == NULL && duration>0) { 280706f2543Smrg CARD32 starttime = GetTimeInMillis(); 281706f2543Smrg CARD32 elapsedtime; 282706f2543Smrg 283706f2543Smrg ctrl->bell_duration= duration; 284706f2543Smrg ctrl->bell_pitch= pitch; 285706f2543Smrg if (xkbInfo->beepCount==0) { 286706f2543Smrg XkbHandleBell(0,0,dev,ctrl->bell,(pointer)ctrl,KbdFeedbackClass,name,None, 287706f2543Smrg NULL); 288706f2543Smrg } 289706f2543Smrg else if (xkbInfo->desc->ctrls->enabled_ctrls&XkbAudibleBellMask) { 290706f2543Smrg (*dev->kbdfeed->BellProc)(ctrl->bell,dev,(pointer)ctrl,KbdFeedbackClass); 291706f2543Smrg } 292706f2543Smrg ctrl->bell_duration= oldDuration; 293706f2543Smrg ctrl->bell_pitch= oldPitch; 294706f2543Smrg xkbInfo->beepCount++; 295706f2543Smrg 296706f2543Smrg /* Some DDX schedule the beep and return immediately, others don't 297706f2543Smrg return until the beep is completed. We measure the time and if 298706f2543Smrg it's less than the beep duration, make sure not to schedule the 299706f2543Smrg next beep until after the current one finishes. */ 300706f2543Smrg 301706f2543Smrg elapsedtime = GetTimeInMillis(); 302706f2543Smrg if (elapsedtime > starttime) { /* watch out for millisecond counter 303706f2543Smrg overflow! */ 304706f2543Smrg elapsedtime -= starttime; 305706f2543Smrg } else { 306706f2543Smrg elapsedtime = 0; 307706f2543Smrg } 308706f2543Smrg if (elapsedtime < duration) { 309706f2543Smrg next += duration - elapsedtime; 310706f2543Smrg } 311706f2543Smrg 312706f2543Smrg } 313706f2543Smrg return next; 314706f2543Smrg} 315706f2543Smrg 316706f2543Smrgint 317706f2543SmrgXkbDDXAccessXBeep(DeviceIntPtr dev,unsigned what,unsigned which) 318706f2543Smrg{ 319706f2543SmrgXkbSrvInfoRec *xkbInfo= dev->key->xkbInfo; 320706f2543SmrgCARD32 next; 321706f2543Smrg 322706f2543Smrg xkbInfo->beepType= what; 323706f2543Smrg xkbInfo->beepCount= 0; 324706f2543Smrg next= _XkbDDXBeepExpire(NULL,0,(pointer)dev); 325706f2543Smrg if (next>0) { 326706f2543Smrg xkbInfo->beepTimer= TimerSet(xkbInfo->beepTimer, 327706f2543Smrg 0, next, 328706f2543Smrg _XkbDDXBeepExpire, (pointer)dev); 329706f2543Smrg } 330706f2543Smrg return 1; 331706f2543Smrg} 332