351 lines
10 KiB
C
351 lines
10 KiB
C
/************************************************************
|
|
Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
|
|
|
|
Permission to use, copy, modify, and distribute this
|
|
software and its documentation for any purpose and without
|
|
fee is hereby granted, provided that the above copyright
|
|
notice appear in all copies and that both that copyright
|
|
notice and this permission notice appear in supporting
|
|
documentation, and that the name of Silicon Graphics not be
|
|
used in advertising or publicity pertaining to distribution
|
|
of the software without specific prior written permission.
|
|
Silicon Graphics makes no representation about the suitability
|
|
of this software for any purpose. It is provided "as is"
|
|
without any express or implied warranty.
|
|
|
|
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
|
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
|
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
|
|
THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
********************************************************/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <X11/X.h>
|
|
#include <X11/Xproto.h>
|
|
#include <X11/keysym.h>
|
|
#include "inputstr.h"
|
|
#include "scrnintstr.h"
|
|
#include "windowstr.h"
|
|
#include <xkbsrv.h>
|
|
#include <X11/extensions/XI.h>
|
|
|
|
/*#define FALLING_TONE 1*/
|
|
/*#define RISING_TONE 1*/
|
|
#define FALLING_TONE 10
|
|
#define RISING_TONE 10
|
|
#define SHORT_TONE 50
|
|
#define SHORT_DELAY 60
|
|
#define LONG_TONE 75
|
|
#define VERY_LONG_TONE 100
|
|
#define LONG_DELAY 85
|
|
#define CLICK_DURATION 1
|
|
|
|
#define DEEP_PITCH 250
|
|
#define LOW_PITCH 500
|
|
#define MID_PITCH 1000
|
|
#define HIGH_PITCH 2000
|
|
#define CLICK_PITCH 1500
|
|
|
|
static unsigned long atomGeneration = 0;
|
|
static Atom featureOn;
|
|
static Atom featureOff;
|
|
static Atom featureChange;
|
|
static Atom ledOn;
|
|
static Atom ledOff;
|
|
static Atom ledChange;
|
|
static Atom slowWarn;
|
|
static Atom slowPress;
|
|
static Atom slowReject;
|
|
static Atom slowAccept;
|
|
static Atom slowRelease;
|
|
static Atom stickyLatch;
|
|
static Atom stickyLock;
|
|
static Atom stickyUnlock;
|
|
static Atom bounceReject;
|
|
static char doesPitch = 1;
|
|
|
|
#define FEATURE_ON "AX_FeatureOn"
|
|
#define FEATURE_OFF "AX_FeatureOff"
|
|
#define FEATURE_CHANGE "AX_FeatureChange"
|
|
#define LED_ON "AX_IndicatorOn"
|
|
#define LED_OFF "AX_IndicatorOff"
|
|
#define LED_CHANGE "AX_IndicatorChange"
|
|
#define SLOW_WARN "AX_SlowKeysWarning"
|
|
#define SLOW_PRESS "AX_SlowKeyPress"
|
|
#define SLOW_REJECT "AX_SlowKeyReject"
|
|
#define SLOW_ACCEPT "AX_SlowKeyAccept"
|
|
#define SLOW_RELEASE "AX_SlowKeyRelease"
|
|
#define STICKY_LATCH "AX_StickyLatch"
|
|
#define STICKY_LOCK "AX_StickyLock"
|
|
#define STICKY_UNLOCK "AX_StickyUnlock"
|
|
#define BOUNCE_REJECT "AX_BounceKeyReject"
|
|
|
|
#define MAKE_ATOM(a) MakeAtom(a,sizeof(a)-1,TRUE)
|
|
|
|
static void
|
|
_XkbDDXBeepInitAtoms(void)
|
|
{
|
|
featureOn = MAKE_ATOM(FEATURE_ON);
|
|
featureOff = MAKE_ATOM(FEATURE_OFF);
|
|
featureChange = MAKE_ATOM(FEATURE_CHANGE);
|
|
ledOn = MAKE_ATOM(LED_ON);
|
|
ledOff = MAKE_ATOM(LED_OFF);
|
|
ledChange = MAKE_ATOM(LED_CHANGE);
|
|
slowWarn = MAKE_ATOM(SLOW_WARN);
|
|
slowPress = MAKE_ATOM(SLOW_PRESS);
|
|
slowReject = MAKE_ATOM(SLOW_REJECT);
|
|
slowAccept = MAKE_ATOM(SLOW_ACCEPT);
|
|
slowRelease = MAKE_ATOM(SLOW_RELEASE);
|
|
stickyLatch = MAKE_ATOM(STICKY_LATCH);
|
|
stickyLock = MAKE_ATOM(STICKY_LOCK);
|
|
stickyUnlock = MAKE_ATOM(STICKY_UNLOCK);
|
|
bounceReject = MAKE_ATOM(BOUNCE_REJECT);
|
|
return;
|
|
}
|
|
|
|
static CARD32
|
|
_XkbDDXBeepExpire(OsTimerPtr timer, CARD32 now, void *arg)
|
|
{
|
|
DeviceIntPtr dev = (DeviceIntPtr) arg;
|
|
KbdFeedbackPtr feed;
|
|
KeybdCtrl *ctrl;
|
|
XkbSrvInfoPtr xkbInfo;
|
|
CARD32 next;
|
|
int pitch, duration;
|
|
int oldPitch, oldDuration;
|
|
Atom name;
|
|
|
|
if ((dev == NULL) || (dev->key == NULL) || (dev->key->xkbInfo == NULL) ||
|
|
(dev->kbdfeed == NULL))
|
|
return 0;
|
|
if (atomGeneration != serverGeneration) {
|
|
_XkbDDXBeepInitAtoms();
|
|
atomGeneration = serverGeneration;
|
|
}
|
|
|
|
feed = dev->kbdfeed;
|
|
ctrl = &feed->ctrl;
|
|
xkbInfo = dev->key->xkbInfo;
|
|
next = 0;
|
|
pitch = oldPitch = ctrl->bell_pitch;
|
|
duration = oldDuration = ctrl->bell_duration;
|
|
name = None;
|
|
switch (xkbInfo->beepType) {
|
|
default:
|
|
ErrorF("[xkb] Unknown beep type %d\n", xkbInfo->beepType);
|
|
case _BEEP_NONE:
|
|
duration = 0;
|
|
break;
|
|
|
|
/* When an LED is turned on, we want a high-pitched beep.
|
|
* When the LED it turned off, we want a low-pitched beep.
|
|
* If we cannot do pitch, we want a single beep for on and two
|
|
* beeps for off.
|
|
*/
|
|
case _BEEP_LED_ON:
|
|
if (name == None)
|
|
name = ledOn;
|
|
duration = SHORT_TONE;
|
|
pitch = HIGH_PITCH;
|
|
break;
|
|
case _BEEP_LED_OFF:
|
|
if (name == None)
|
|
name = ledOff;
|
|
duration = SHORT_TONE;
|
|
pitch = LOW_PITCH;
|
|
if (!doesPitch && xkbInfo->beepCount < 1)
|
|
next = SHORT_DELAY;
|
|
break;
|
|
|
|
/* When a Feature is turned on, we want an up-siren.
|
|
* When a Feature is turned off, we want a down-siren.
|
|
* If we cannot do pitch, we want a single beep for on and two
|
|
* beeps for off.
|
|
*/
|
|
case _BEEP_FEATURE_ON:
|
|
if (name == None)
|
|
name = featureOn;
|
|
if (xkbInfo->beepCount < 1) {
|
|
pitch = LOW_PITCH;
|
|
duration = VERY_LONG_TONE;
|
|
if (doesPitch)
|
|
next = SHORT_DELAY;
|
|
}
|
|
else {
|
|
pitch = MID_PITCH;
|
|
duration = SHORT_TONE;
|
|
}
|
|
break;
|
|
|
|
case _BEEP_FEATURE_OFF:
|
|
if (name == None)
|
|
name = featureOff;
|
|
if (xkbInfo->beepCount < 1) {
|
|
pitch = MID_PITCH;
|
|
if (doesPitch)
|
|
duration = VERY_LONG_TONE;
|
|
else
|
|
duration = SHORT_TONE;
|
|
next = SHORT_DELAY;
|
|
}
|
|
else {
|
|
pitch = LOW_PITCH;
|
|
duration = SHORT_TONE;
|
|
}
|
|
break;
|
|
|
|
/* Two high beeps indicate an LED or Feature changed
|
|
* state, but that another LED or Feature is also on.
|
|
* [[[WDW - This is not in AccessDOS ]]]
|
|
*/
|
|
case _BEEP_LED_CHANGE:
|
|
if (name == None)
|
|
name = ledChange;
|
|
case _BEEP_FEATURE_CHANGE:
|
|
if (name == None)
|
|
name = featureChange;
|
|
duration = SHORT_TONE;
|
|
pitch = HIGH_PITCH;
|
|
if (xkbInfo->beepCount < 1) {
|
|
next = SHORT_DELAY;
|
|
}
|
|
break;
|
|
|
|
/* Three high-pitched beeps are the warning that SlowKeys
|
|
* is going to be turned on or off.
|
|
*/
|
|
case _BEEP_SLOW_WARN:
|
|
if (name == None)
|
|
name = slowWarn;
|
|
duration = SHORT_TONE;
|
|
pitch = HIGH_PITCH;
|
|
if (xkbInfo->beepCount < 2)
|
|
next = SHORT_DELAY;
|
|
break;
|
|
|
|
/* Click on SlowKeys press and accept.
|
|
* Deep pitch when a SlowKey or BounceKey is rejected.
|
|
* [[[WDW - Rejects are not in AccessDOS ]]]
|
|
* If we cannot do pitch, we want single beeps.
|
|
*/
|
|
case _BEEP_SLOW_PRESS:
|
|
if (name == None)
|
|
name = slowPress;
|
|
case _BEEP_SLOW_ACCEPT:
|
|
if (name == None)
|
|
name = slowAccept;
|
|
case _BEEP_SLOW_RELEASE:
|
|
if (name == None)
|
|
name = slowRelease;
|
|
duration = CLICK_DURATION;
|
|
pitch = CLICK_PITCH;
|
|
break;
|
|
case _BEEP_BOUNCE_REJECT:
|
|
if (name == None)
|
|
name = bounceReject;
|
|
case _BEEP_SLOW_REJECT:
|
|
if (name == None)
|
|
name = slowReject;
|
|
duration = SHORT_TONE;
|
|
pitch = DEEP_PITCH;
|
|
break;
|
|
|
|
/* Low followed by high pitch when a StickyKey is latched.
|
|
* High pitch when a StickyKey is locked.
|
|
* Low pitch when unlocked.
|
|
* If we cannot do pitch, two beeps for latch, nothing for
|
|
* lock, and two for unlock.
|
|
*/
|
|
case _BEEP_STICKY_LATCH:
|
|
if (name == None)
|
|
name = stickyLatch;
|
|
duration = SHORT_TONE;
|
|
if (xkbInfo->beepCount < 1) {
|
|
next = SHORT_DELAY;
|
|
pitch = LOW_PITCH;
|
|
}
|
|
else
|
|
pitch = HIGH_PITCH;
|
|
break;
|
|
case _BEEP_STICKY_LOCK:
|
|
if (name == None)
|
|
name = stickyLock;
|
|
if (doesPitch) {
|
|
duration = SHORT_TONE;
|
|
pitch = HIGH_PITCH;
|
|
}
|
|
break;
|
|
case _BEEP_STICKY_UNLOCK:
|
|
if (name == None)
|
|
name = stickyUnlock;
|
|
duration = SHORT_TONE;
|
|
pitch = LOW_PITCH;
|
|
if (!doesPitch && xkbInfo->beepCount < 1)
|
|
next = SHORT_DELAY;
|
|
break;
|
|
}
|
|
if (timer == NULL && duration > 0) {
|
|
CARD32 starttime = GetTimeInMillis();
|
|
CARD32 elapsedtime;
|
|
|
|
ctrl->bell_duration = duration;
|
|
ctrl->bell_pitch = pitch;
|
|
if (xkbInfo->beepCount == 0) {
|
|
XkbHandleBell(0, 0, dev, ctrl->bell, (void *) ctrl,
|
|
KbdFeedbackClass, name, None, NULL);
|
|
}
|
|
else if (xkbInfo->desc->ctrls->enabled_ctrls & XkbAudibleBellMask) {
|
|
(*dev->kbdfeed->BellProc) (ctrl->bell, dev, (void *) ctrl,
|
|
KbdFeedbackClass);
|
|
}
|
|
ctrl->bell_duration = oldDuration;
|
|
ctrl->bell_pitch = oldPitch;
|
|
xkbInfo->beepCount++;
|
|
|
|
/* Some DDX schedule the beep and return immediately, others don't
|
|
return until the beep is completed. We measure the time and if
|
|
it's less than the beep duration, make sure not to schedule the
|
|
next beep until after the current one finishes. */
|
|
|
|
elapsedtime = GetTimeInMillis();
|
|
if (elapsedtime > starttime) { /* watch out for millisecond counter
|
|
overflow! */
|
|
elapsedtime -= starttime;
|
|
}
|
|
else {
|
|
elapsedtime = 0;
|
|
}
|
|
if (elapsedtime < duration) {
|
|
next += duration - elapsedtime;
|
|
}
|
|
|
|
}
|
|
return next;
|
|
}
|
|
|
|
int
|
|
XkbDDXAccessXBeep(DeviceIntPtr dev, unsigned what, unsigned which)
|
|
{
|
|
XkbSrvInfoRec *xkbInfo = dev->key->xkbInfo;
|
|
CARD32 next;
|
|
|
|
xkbInfo->beepType = what;
|
|
xkbInfo->beepCount = 0;
|
|
next = _XkbDDXBeepExpire(NULL, 0, (void *) dev);
|
|
if (next > 0) {
|
|
xkbInfo->beepTimer = TimerSet(xkbInfo->beepTimer,
|
|
0, next,
|
|
_XkbDDXBeepExpire, (void *) dev);
|
|
}
|
|
return 1;
|
|
}
|