105b261ecSmrg/************************************************************
205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrgPermission to use, copy, modify, and distribute this
505b261ecSmrgsoftware and its documentation for any purpose and without
605b261ecSmrgfee is hereby granted, provided that the above copyright
705b261ecSmrgnotice appear in all copies and that both that copyright
805b261ecSmrgnotice and this permission notice appear in supporting
935c4bbdfSmrgdocumentation, and that the name of Silicon Graphics not be
1035c4bbdfSmrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
1235c4bbdfSmrgSilicon Graphics makes no representation about the suitability
1305b261ecSmrgof this software for any purpose. It is provided "as is"
1405b261ecSmrgwithout any express or implied warranty.
1505b261ecSmrg
1635c4bbdfSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1735c4bbdfSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1935c4bbdfSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2035c4bbdfSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2135c4bbdfSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <stdio.h>
3205b261ecSmrg#include <math.h>
3305b261ecSmrg#include <X11/X.h>
3405b261ecSmrg#include <X11/Xproto.h>
3505b261ecSmrg#include <X11/keysym.h>
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "inputstr.h"
3805b261ecSmrg#include "exevents.h"
396747b715Smrg#include "eventstr.h"
4005b261ecSmrg#include <xkbsrv.h>
4105b261ecSmrg#include <ctype.h>
426747b715Smrg#include "events.h"
4305b261ecSmrg
4405b261ecSmrg/***====================================================================***/
4505b261ecSmrg
4605b261ecSmrgvoid
476747b715SmrgXkbProcessKeyboardEvent(DeviceEvent *event, DeviceIntPtr keybd)
4805b261ecSmrg{
4935c4bbdfSmrg    KeyClassPtr keyc = keybd->key;
5035c4bbdfSmrg    XkbSrvInfoPtr xkbi;
5135c4bbdfSmrg    int key;
5235c4bbdfSmrg    XkbBehavior behavior;
5335c4bbdfSmrg    unsigned ndx;
5405b261ecSmrg
556747b715Smrg    xkbi = keyc->xkbInfo;
566747b715Smrg    key = event->detail.key;
576747b715Smrg    if (xkbDebugFlags & 0x8)
5835c4bbdfSmrg        DebugF("[xkb] XkbPKE: Key %d %s\n", key,
5935c4bbdfSmrg               (event->type == ET_KeyPress ? "down" : "up"));
6005b261ecSmrg
6135c4bbdfSmrg    if (xkbi->repeatKey == key && event->type == ET_KeyRelease &&
626747b715Smrg        !(xkbi->desc->ctrls->enabled_ctrls & XkbRepeatKeysMask))
6335c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, key);
6405b261ecSmrg
656747b715Smrg    behavior = xkbi->desc->server->behaviors[key];
6605b261ecSmrg    /* The "permanent" flag indicates a hard-wired behavior that occurs */
6705b261ecSmrg    /* below XKB, such as a key that physically locks.   XKB does not   */
6805b261ecSmrg    /* do anything to implement the behavior, but it *does* report that */
6905b261ecSmrg    /* key is hardwired */
7005b261ecSmrg
716747b715Smrg    if (!(behavior.type & XkbKB_Permanent)) {
7235c4bbdfSmrg        switch (behavior.type) {
7335c4bbdfSmrg        case XkbKB_Default:
7435c4bbdfSmrg            /* Neither of these should happen in practice, but ignore them
7535c4bbdfSmrg               anyway. */
7635c4bbdfSmrg            if (event->type == ET_KeyPress && !event->key_repeat &&
7735c4bbdfSmrg                key_is_down(keybd, key, KEY_PROCESSED))
7835c4bbdfSmrg                return;
7935c4bbdfSmrg            else if (event->type == ET_KeyRelease &&
8035c4bbdfSmrg                     !key_is_down(keybd, key, KEY_PROCESSED))
8135c4bbdfSmrg                return;
8235c4bbdfSmrg            break;
8335c4bbdfSmrg        case XkbKB_Lock:
8435c4bbdfSmrg            if (event->type == ET_KeyRelease)
8535c4bbdfSmrg                return;
8635c4bbdfSmrg            else if (key_is_down(keybd, key, KEY_PROCESSED))
8735c4bbdfSmrg                event->type = ET_KeyRelease;
8835c4bbdfSmrg            break;
8935c4bbdfSmrg        case XkbKB_RadioGroup:
9035c4bbdfSmrg            ndx = (behavior.data & (~XkbKB_RGAllowNone));
9135c4bbdfSmrg            if (ndx < xkbi->nRadioGroups) {
9235c4bbdfSmrg                XkbRadioGroupPtr rg;
9335c4bbdfSmrg
9435c4bbdfSmrg                if (event->type == ET_KeyRelease)
956747b715Smrg                    return;
9635c4bbdfSmrg
9735c4bbdfSmrg                rg = &xkbi->radioGroups[ndx];
9835c4bbdfSmrg                if (rg->currentDown == event->detail.key) {
9935c4bbdfSmrg                    if (behavior.data & XkbKB_RGAllowNone) {
10035c4bbdfSmrg                        event->type = ET_KeyRelease;
10135c4bbdfSmrg                        XkbHandleActions(keybd, keybd, event);
10235c4bbdfSmrg                        rg->currentDown = 0;
10335c4bbdfSmrg                    }
1046747b715Smrg                    return;
10535c4bbdfSmrg                }
10635c4bbdfSmrg                if (rg->currentDown != 0) {
10735c4bbdfSmrg                    int tmpkey = event->detail.key;
10835c4bbdfSmrg
1096747b715Smrg                    event->type = ET_KeyRelease;
11035c4bbdfSmrg                    event->detail.key = rg->currentDown;
11135c4bbdfSmrg                    XkbHandleActions(keybd, keybd, event);
11235c4bbdfSmrg                    event->type = ET_KeyPress;
11335c4bbdfSmrg                    event->detail.key = tmpkey;
11435c4bbdfSmrg                }
11535c4bbdfSmrg                rg->currentDown = key;
11635c4bbdfSmrg            }
11735c4bbdfSmrg            else
11835c4bbdfSmrg                ErrorF("[xkb] InternalError! Illegal radio group %d\n", ndx);
11935c4bbdfSmrg            break;
12035c4bbdfSmrg        case XkbKB_Overlay1:
12135c4bbdfSmrg        case XkbKB_Overlay2:
12235c4bbdfSmrg        {
12335c4bbdfSmrg            unsigned which;
1241b5d61b8Smrg            unsigned overlay_active_now;
1251b5d61b8Smrg            unsigned is_keyrelease = (event->type == ET_KeyRelease) ? 1 : 0;
1261b5d61b8Smrg            /* Remembers whether the key was pressed while overlay was down,
1271b5d61b8Smrg             * for when overlay is already released, but the key is not. */
1281b5d61b8Smrg            unsigned key_was_overlaid = 0;
12935c4bbdfSmrg
13035c4bbdfSmrg            if (behavior.type == XkbKB_Overlay1)
13135c4bbdfSmrg                which = XkbOverlay1Mask;
13235c4bbdfSmrg            else
13335c4bbdfSmrg                which = XkbOverlay2Mask;
1341b5d61b8Smrg            overlay_active_now = (xkbi->desc->ctrls->enabled_ctrls & which) ? 1 : 0;
1351b5d61b8Smrg
1361b5d61b8Smrg            if ((unsigned char)key == key) {
1371b5d61b8Smrg                key_was_overlaid = BitIsOn(xkbi->overlay_perkey_state, key);
1381b5d61b8Smrg                if (!is_keyrelease) {
1391b5d61b8Smrg                    if (overlay_active_now)
1401b5d61b8Smrg                        SetBit(xkbi->overlay_perkey_state, key);
1411b5d61b8Smrg                } else {
1421b5d61b8Smrg                    if (key_was_overlaid)
1431b5d61b8Smrg                        ClearBit(xkbi->overlay_perkey_state, key);
1441b5d61b8Smrg                }
1451b5d61b8Smrg            }
1461b5d61b8Smrg
1471b5d61b8Smrg            if ((overlay_active_now || key_was_overlaid) &&
1481b5d61b8Smrg                    (behavior.data >= xkbi->desc->min_key_code) &&
1491b5d61b8Smrg                    (behavior.data <= xkbi->desc->max_key_code)) {
15035c4bbdfSmrg                event->detail.key = behavior.data;
15135c4bbdfSmrg            }
15235c4bbdfSmrg        }
15335c4bbdfSmrg            break;
15435c4bbdfSmrg        default:
15535c4bbdfSmrg            ErrorF("[xkb] unknown key behavior 0x%04x\n", behavior.type);
15635c4bbdfSmrg            break;
15735c4bbdfSmrg        }
15805b261ecSmrg    }
1596747b715Smrg    XkbHandleActions(keybd, keybd, event);
16005b261ecSmrg    return;
16105b261ecSmrg}
16205b261ecSmrg
16305b261ecSmrgvoid
1646747b715SmrgProcessKeyboardEvent(InternalEvent *ev, DeviceIntPtr keybd)
16505b261ecSmrg{
16605b261ecSmrg
16705b261ecSmrg    KeyClassPtr keyc = keybd->key;
16805b261ecSmrg    XkbSrvInfoPtr xkbi = NULL;
16905b261ecSmrg    ProcessInputProc backup_proc;
17005b261ecSmrg    xkbDeviceInfoPtr xkb_priv = XKBDEVICEINFO(keybd);
1716747b715Smrg    DeviceEvent *event = &ev->device_event;
1726747b715Smrg    int is_press = (event->type == ET_KeyPress);
1736747b715Smrg    int is_release = (event->type == ET_KeyRelease);
17405b261ecSmrg
17505b261ecSmrg    /* We're only interested in key events. */
17605b261ecSmrg    if (!is_press && !is_release) {
17705b261ecSmrg        UNWRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc);
1786747b715Smrg        keybd->public.processInputProc(ev, keybd);
17905b261ecSmrg        COND_WRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc,
18005b261ecSmrg                                     xkbUnwrapProc);
18105b261ecSmrg        return;
18205b261ecSmrg    }
18305b261ecSmrg
1846747b715Smrg    xkbi = keyc->xkbInfo;
1856747b715Smrg
18605b261ecSmrg    /* If AccessX filters are active, then pass it through to
18705b261ecSmrg     * AccessXFilter{Press,Release}Event; else, punt to
18805b261ecSmrg     * XkbProcessKeyboardEvent.
18905b261ecSmrg     *
19005b261ecSmrg     * If AXF[PK]E don't intercept anything (which they probably won't),
19105b261ecSmrg     * they'll punt through XPKE anyway. */
19205b261ecSmrg    if ((xkbi->desc->ctrls->enabled_ctrls & XkbAllFilteredEventsMask)) {
19305b261ecSmrg        if (is_press)
1946747b715Smrg            AccessXFilterPressEvent(event, keybd);
19505b261ecSmrg        else if (is_release)
1966747b715Smrg            AccessXFilterReleaseEvent(event, keybd);
1976747b715Smrg        return;
1986747b715Smrg    }
1996747b715Smrg    else {
2006747b715Smrg        XkbProcessKeyboardEvent(event, keybd);
20105b261ecSmrg    }
2026747b715Smrg
20305b261ecSmrg    return;
20405b261ecSmrg}
205