home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / sun / sunKbd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-23  |  24.2 KB  |  920 lines

  1. /*-
  2.  * sunKbd.c --
  3.  *    Functions for retrieving data from a keyboard.
  4.  *
  5.  * Copyright (c) 1987 by the Regents of the University of California
  6.  *
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  */
  16.  
  17. /************************************************************
  18. Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
  19.  
  20.                     All Rights Reserved
  21.  
  22. Permission  to  use,  copy,  modify,  and  distribute   this
  23. software  and  its documentation for any purpose and without
  24. fee is hereby granted, provided that the above copyright no-
  25. tice  appear  in all copies and that both that copyright no-
  26. tice and this permission notice appear in  supporting  docu-
  27. mentation,  and  that the names of Sun or MIT not be used in
  28. advertising or publicity pertaining to distribution  of  the
  29. software  without specific prior written permission. Sun and
  30. M.I.T. make no representations about the suitability of this
  31. software for any purpose. It is provided "as is" without any
  32. express or implied warranty.
  33.  
  34. SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
  35. INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
  36. NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
  37. ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  38. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
  39. PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
  40. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
  41. THE USE OR PERFORMANCE OF THIS SOFTWARE.
  42.  
  43. ********************************************************/
  44.  
  45. #ifndef    lint
  46. static char sccsid[] = "%W %G Copyright 1987 Sun Micro";
  47. #endif
  48.  
  49.  
  50. #define NEED_EVENTS
  51. #include "sun.h"
  52. #include <stdio.h>
  53. #include "Xproto.h"
  54. #include "keysym.h"
  55. #include "inputstr.h"
  56. #include <signal.h>
  57. #include <sys/ioctl.h>
  58.  
  59. typedef struct {
  60.     int              trans;              /* Original translation form */
  61. } SunKbPrivRec, *SunKbPrivPtr;
  62.  
  63. extern CARD8 *sunModMap[];
  64. extern KeySymsRec sunKeySyms[];
  65.  
  66. extern void    ProcessInputEvents();
  67. extern void    miPointerPosition();
  68.  
  69. static void       sunBell();
  70. static void       sunKbdCtrl();
  71. static Firm_event *sunKbdGetEvents();
  72. static void       sunKbdEnqueueEvent();
  73. int            autoRepeatKeyDown = 0;
  74. int            autoRepeatReady;
  75. long            autoRepeatInitiate = 1000 * AUTOREPEAT_INITIATE;
  76. long            autoRepeatDelay = 1000 * AUTOREPEAT_DELAY;
  77. static int      autoRepeatFirst;
  78. struct timeval    autoRepeatLastKeyDownTv;
  79. struct timeval    autoRepeatDeltaTv;
  80. static KeybdCtrl  sysKbCtrl;
  81.  
  82. static SunKbPrivRec    sunKbPriv;  
  83. static KbPrivRec      sysKbPriv = {
  84.     -1,                /* Type of keyboard */
  85.     -1,                /* Descriptor open to device */
  86.     sunKbdGetEvents,        /* Function to read events */
  87.     sunKbdEnqueueEvent,        /* Function to enqueue an event */
  88.     (pointer)&sunKbPriv,    /* Private to keyboard device */
  89.     (Bool)0,            /* Mapped queue */
  90.     0,                /* offset for device keycodes */
  91.     &sysKbCtrl,            /* Initial full duration = .25 sec. */
  92.     0,                /* lock state */
  93. };
  94.  
  95. /*-
  96.  *-----------------------------------------------------------------------
  97.  * sunKbdProc --
  98.  *    Handle the initialization, etc. of a keyboard.
  99.  *
  100.  * Results:
  101.  *    None.
  102.  *
  103.  * Side Effects:
  104.  *
  105.  * Note:
  106.  *    When using sunwindows, all input comes off a single fd, stored in the
  107.  *    global windowFd.  Therefore, only one device should be enabled and
  108.  *    disabled, even though the application still sees both mouse and
  109.  *    keyboard.  We have arbitrarily chosen to enable and disable windowFd
  110.  *    in the keyboard routine sunKbdProc rather than in sunMouseProc.
  111.  *
  112.  *-----------------------------------------------------------------------
  113.  */
  114. int
  115. sunKbdProc (pKeyboard, what)
  116.     DevicePtr      pKeyboard;    /* Keyboard to manipulate */
  117.     int              what;            /* What to do to it */
  118. {
  119.     KbPrivPtr      pPriv;
  120.     register int  kbdFd;
  121. #ifdef    SUN_WINDOWS
  122. #define    TR_UNDEFINED (TR_NONE-1)
  123.     static int      deviceOffKbdState = TR_UNDEFINED;
  124. #endif    SUN_WINDOWS
  125.  
  126.     switch (what) {
  127.     case DEVICE_INIT:
  128.         if (pKeyboard != LookupKeyboardDevice()) {
  129.         ErrorF ("Cannot open non-system keyboard");
  130.         return (!Success);
  131.         }
  132.         
  133.         /*
  134.          * First open and find the current state of the keyboard.
  135.          */
  136. /*
  137.  * The Sun 386i has system include files that preclude this pre SunOS 4.1
  138.  * test for the presence of a type 4 keyboard however it really doesn't
  139.  * matter since no 386i has ever been shipped with a type 3 keyboard.
  140.  * SunOS 4.1 no longer needs this kludge.
  141.  */
  142. #if !defined(i386) && !defined(KIOCGKEY)
  143. #define TYPE4KEYBOARDOVERRIDE
  144. #endif
  145.         if (sysKbPriv.fd >= 0) {
  146.         kbdFd = sysKbPriv.fd;
  147.         } else {
  148.         kbdFd = open ("/dev/kbd", O_RDWR, 0);
  149.         if (kbdFd < 0) {
  150.             Error ("Opening /dev/kbd");
  151.             return (!Success);
  152.         }
  153.         sysKbPriv.fd = kbdFd;
  154.         (void) ioctl (kbdFd, KIOCTYPE, &sysKbPriv.type);
  155.         (void) ioctl (kbdFd, KIOCGTRANS, &sunKbPriv.trans);
  156. #ifdef TYPE4KEYBOARDOVERRIDE
  157.                 /*
  158.                  * Magic. Look for a key which is non-existent on a real type
  159.                  * 3 keyboard but does exist on a type 4 keyboard.
  160.                  */
  161.                 if (sysKbPriv.type == KB_SUN3) {
  162.                     struct kiockey key;
  163.  
  164.                     key.kio_tablemask = 0;
  165.                     key.kio_station = 118;
  166.                     if (ioctl(kbdFd, KIOCGETKEY, &key)) {
  167.                         perror( "ioctl KIOCGETKEY" );
  168.             FatalError("Can't KIOCGETKEY on fd %d\n", kbdFd);
  169.                     }
  170.                     if (key.kio_entry != HOLE)
  171.                         sysKbPriv.type = KB_SUN4;
  172.                 }
  173. #endif
  174.  
  175.         if (sysKbPriv.type < 0 || sysKbPriv.type > KB_SUN4
  176.             || sunKeySyms[sysKbPriv.type].map == NULL)
  177.             FatalError("Unsupported keyboard type %d\n", 
  178.             sysKbPriv.type);
  179.         if (sunUseSunWindows()) {
  180.             (void) close( kbdFd );
  181.             sysKbPriv.fd = -1;
  182.         } else {
  183.             if (fcntl (kbdFd, F_SETFL, (FNDELAY|FASYNC)) < 0
  184.             || fcntl(kbdFd, F_SETOWN, getpid()) < 0) {
  185.             perror("sunKbdProc");
  186.             FatalError("Can't set up kbd on fd %d\n", kbdFd);
  187.             }
  188.         }
  189.         }
  190.  
  191.         /*
  192.          * Perform final initialization of the system private keyboard
  193.          * structure and fill in various slots in the device record
  194.          * itself which couldn't be filled in before.
  195.          */
  196.         pKeyboard->devicePrivate = (pointer)&sysKbPriv;
  197.         pKeyboard->on = FALSE;
  198.         sysKbCtrl = defaultKeyboardControl;
  199.         sysKbPriv.ctrl = &sysKbCtrl;
  200.         autoRepeatKeyDown = 0;
  201.  
  202.         /*
  203.          * ensure that the keycodes on the wire are >= MIN_KEYCODE
  204.          */
  205.         if (sunKeySyms[sysKbPriv.type].minKeyCode < MIN_KEYCODE) {
  206.         int offset = MIN_KEYCODE -sunKeySyms[sysKbPriv.type].minKeyCode;
  207.  
  208.         sunKeySyms[sysKbPriv.type].minKeyCode += offset;
  209.         sunKeySyms[sysKbPriv.type].maxKeyCode += offset;
  210.         sysKbPriv.offset = offset;
  211.         }
  212.         InitKeyboardDeviceStruct(
  213.             pKeyboard,
  214.             &(sunKeySyms[sysKbPriv.type]),
  215.             (sunModMap[sysKbPriv.type]),
  216.             sunBell,
  217.             sunKbdCtrl);
  218.         break;
  219.  
  220.     case DEVICE_ON:
  221.         if (sunUseSunWindows()) {
  222. #ifdef SUN_WINDOWS
  223.         if (! sunSetUpKbdSunWin(windowFd, TRUE)) {
  224.             FatalError("Can't set up keyboard\n");
  225.         }
  226.         /*
  227.          * Don't tamper with keyboard translation here
  228.          * unless this is a server reset.  If server
  229.          * is reset then set translation to that saved
  230.          * when DEVICE_CLOSE was executed.
  231.          * Translation is set/reset upon receipt of
  232.          * KBD_USE/KBD_DONE input events (sunIo.c)
  233.          */
  234.         if (deviceOffKbdState != TR_UNDEFINED) {
  235.             if (sunChangeKbdTranslation(pKeyboard,
  236.                 deviceOffKbdState == TR_UNTRANS_EVENT) < 0) {
  237.             FatalError("Can't set (SW) keyboard translation\n");
  238.             }
  239.         }
  240.         AddEnabledDevice(windowFd);
  241. #endif SUN_WINDOWS
  242.         }
  243.         else {
  244.         pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
  245.         kbdFd = pPriv->fd;
  246.  
  247.             /*
  248.              * Set the keyboard into "direct" mode and turn on
  249.              * event translation.
  250.              */
  251.         if (sunChangeKbdTranslation(pKeyboard,TRUE) < 0) {
  252.             FatalError("Can't set keyboard translation\n");
  253.         }
  254.  
  255.         AddEnabledDevice(kbdFd);
  256.         }
  257.         pKeyboard->on = TRUE;
  258.         break;
  259.  
  260.     case DEVICE_CLOSE:
  261.     case DEVICE_OFF:
  262.         if (sunUseSunWindows()) {
  263. #ifdef SUN_WINDOWS
  264.         /*
  265.          * Save current translation state in case of server
  266.          * reset.  Used above when DEVICE_ON is executed.
  267.          */
  268.         if ((kbdFd = open("/dev/kbd", O_RDONLY, 0)) < 0) {
  269.             Error("DEVICE_OFF: Can't open kbd\n");
  270.             goto badkbd;
  271.         }
  272.         if (ioctl(kbdFd, KIOCGTRANS, &deviceOffKbdState) < 0) {
  273.             Error("Can't save keyboard state\n");
  274.         }
  275.         (void) close(kbdFd);
  276.  
  277. badkbd:
  278.         if (! sunSetUpKbdSunWin(windowFd, FALSE)) {
  279.             FatalError("Can't close keyboard\n");
  280.         }
  281.  
  282.         /*
  283.          * Restore SunWindows translation.
  284.          */
  285.         if (sunChangeKbdTranslation(pKeyboard,FALSE) < 0) {
  286.             FatalError("Can't reset keyboard translation\n");
  287.         }
  288.  
  289.         RemoveEnabledDevice(windowFd);
  290. #endif SUN_WINDOWS
  291.         }
  292.         else {
  293.         pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
  294.         kbdFd = pPriv->fd;
  295.  
  296.             /*
  297.              * Restore original keyboard directness and translation.
  298.              */
  299.         if (sunChangeKbdTranslation(pKeyboard,FALSE) < 0) {
  300.             FatalError("Can't reset keyboard translation\n");
  301.         }
  302.  
  303.         RemoveEnabledDevice(kbdFd);
  304.         }
  305.         pKeyboard->on = FALSE;
  306.         break;
  307.     }
  308.     return (Success);
  309. }
  310.  
  311. /*-
  312.  *-----------------------------------------------------------------------
  313.  * sunBell --
  314.  *    Ring the terminal/keyboard bell
  315.  *
  316.  * Results:
  317.  *    Ring the keyboard bell for an amount of time proportional to
  318.  *    "loudness."
  319.  *
  320.  * Side Effects:
  321.  *    None, really...
  322.  *
  323.  *-----------------------------------------------------------------------
  324.  */
  325. static void
  326. sunBell (loudness, pKeyboard)
  327.     int              loudness;        /* Percentage of full volume */
  328.     DevicePtr      pKeyboard;        /* Keyboard to ring */
  329. {
  330.     KbPrivPtr      pPriv = (KbPrivPtr) pKeyboard->devicePrivate;
  331.     int            kbdCmd;           /* Command to give keyboard */
  332.     int           kbdOpenedHere; 
  333.  
  334.     if (loudness == 0) {
  335.      return;
  336.     }
  337.  
  338.     kbdOpenedHere = ( pPriv->fd < 0 );
  339.     if ( kbdOpenedHere ) {
  340.     pPriv->fd = open("/dev/kbd", O_RDWR, 0);
  341.     if (pPriv->fd < 0) {
  342.         ErrorF("sunBell: can't open keyboard");
  343.         return;
  344.     }
  345.     }    
  346.  
  347.     kbdCmd = KBD_CMD_BELL;
  348.     if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) < 0) {
  349.      ErrorF ("Failed to activate bell");
  350.     goto bad;
  351.     }
  352.  
  353.     /*
  354.      * Leave the bell on for a while == duration (ms) proportional to
  355.      * loudness desired with a 10 thrown in to convert from ms to usecs.
  356.      */
  357.     usleep (pPriv->ctrl->bell_duration * 1000);
  358.  
  359.     kbdCmd = KBD_CMD_NOBELL;
  360.     if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) < 0) {
  361.     ErrorF ("Failed to deactivate bell");
  362.     goto bad;
  363.     }
  364.  
  365. bad:
  366.     if ( kbdOpenedHere ) {
  367.     (void) close(pPriv->fd);
  368.     pPriv->fd = -1;
  369.     }
  370. }
  371.  
  372. /*
  373.  * The LEDs on the type-4 keyboard are in a *strange*
  374.  * order.  This code remaps them left-to-right, which
  375.  * may not be what you want, but it seems reasonable to me.
  376.  */
  377.  
  378. #define LED_LOCK    0x08
  379. #define LED_1        0x02
  380. #define LED_2        0x04
  381. #define LED_3        0x01
  382. #define LED_X        (LED_1 | LED_2 | LED_3)
  383. #define LED_ALL        (LED_LOCK | LED_X)
  384.  
  385. sunKbdSetLights (pKeyboard)
  386.     DevicePtr    pKeyboard;
  387. {
  388.     KbPrivPtr    pPriv = (KbPrivPtr) pKeyboard->devicePrivate;
  389.     char    device, request;
  390.  
  391.     request = pPriv->ctrl->leds;
  392.     device = 0;
  393.     if (request & 0x01)
  394.     device |= LED_1;
  395.     if (request & 0x02)
  396.     device |= LED_2;
  397.     if (request & 0x04)
  398.     device |= LED_3;
  399.     if (pPriv->lockLight)
  400.     device |= LED_LOCK;
  401. #ifdef KIOCSLED
  402.     if (ioctl (pPriv->fd, KIOCSLED, &device) == -1)
  403.     ErrorF("Failed to set keyboard lights");
  404. #endif
  405. }
  406.  
  407. /*-
  408.  *-----------------------------------------------------------------------
  409.  * sunKbdCtrl --
  410.  *    Alter some of the keyboard control parameters
  411.  *
  412.  * Results:
  413.  *    None.
  414.  *
  415.  * Side Effects:
  416.  *    Some...
  417.  *
  418.  *-----------------------------------------------------------------------
  419.  */
  420.  
  421. static void
  422. sunKbdCtrl (pKeyboard, ctrl)
  423.     DevicePtr      pKeyboard;        /* Keyboard to alter */
  424.     KeybdCtrl     *ctrl;
  425. {
  426.     KbPrivPtr      pPriv = (KbPrivPtr) pKeyboard->devicePrivate;
  427.     int           kbdOpenedHere; 
  428.     char      led;
  429.     int          i;
  430.  
  431.     kbdOpenedHere = ( pPriv->fd < 0 );
  432.     if ( kbdOpenedHere ) {
  433.     pPriv->fd = open("/dev/kbd", O_WRONLY, 0);
  434.     if (pPriv->fd < 0) {
  435.         ErrorF("sunKbdCtrl: can't open keyboard");
  436.         return;
  437.     }
  438.     }
  439.  
  440.     if (ctrl->click != pPriv->ctrl->click)
  441.     {
  442.         int kbdClickCmd;
  443.  
  444.     kbdClickCmd = pPriv->ctrl->click ? KBD_CMD_CLICK : KBD_CMD_NOCLICK;
  445.         if (ioctl (pPriv->fd, KIOCCMD, &kbdClickCmd) < 0)
  446.          ErrorF("Failed to set keyclick");
  447.     }
  448.  
  449.     if (ctrl->leds != pPriv->ctrl->leds)
  450.     {
  451.     pPriv->ctrl->leds = ctrl->leds & LED_X;
  452.     sunKbdSetLights (pKeyboard);
  453.     }
  454.  
  455.     pPriv->ctrl->bell = ctrl->bell;
  456.     pPriv->ctrl->bell_pitch = ctrl->bell_pitch;
  457.     pPriv->ctrl->bell_duration = ctrl->bell_duration;
  458.     pPriv->ctrl->autoRepeat = ctrl->autoRepeat;
  459.     for (i = 0; i < sizeof ctrl->autoRepeats / sizeof ctrl->autoRepeats[0]; i++)
  460.     pPriv->ctrl->autoRepeats[i] = ctrl->autoRepeats[i];
  461.  
  462.     if ( kbdOpenedHere ) {
  463.     (void) close(pPriv->fd);
  464.     pPriv->fd = -1;
  465.     }
  466. }
  467.  
  468. sunKbdLockLight (pKeyboard, on)
  469.     DevicePtr    pKeyboard;
  470.     Bool    on;
  471. {
  472.     KbPrivPtr    pPriv = (KbPrivPtr) pKeyboard->devicePrivate;
  473.     KeybdCtrl    ctrl;
  474.  
  475.     pPriv->lockLight = on;
  476.     sunKbdSetLights (pKeyboard);
  477. }
  478.  
  479. /*-
  480.  *-----------------------------------------------------------------------
  481.  * sunKbdGetEvents --
  482.  *    Return the events waiting in the wings for the given keyboard.
  483.  *
  484.  * Results:
  485.  *    A pointer to an array of Firm_events or (Firm_event *)0 if no events
  486.  *    The number of events contained in the array.
  487.  *    A boolean as to whether more events might be available.
  488.  *
  489.  * Side Effects:
  490.  *    None.
  491.  *-----------------------------------------------------------------------
  492.  */
  493. static Firm_event *
  494. sunKbdGetEvents (pKeyboard, pNumEvents, pAgain)
  495.     DevicePtr      pKeyboard;        /* Keyboard to read */
  496.     int              *pNumEvents;        /* Place to return number of events */
  497.     Bool      *pAgain;        /* whether more might be available */
  498. {
  499.     int              nBytes;        /* number of bytes of events available. */
  500.     KbPrivPtr      pPriv;
  501.     static Firm_event    evBuf[MAXEVENTS];   /* Buffer for Firm_events */
  502.  
  503.     pPriv = (KbPrivPtr) pKeyboard->devicePrivate;
  504.     nBytes = read (pPriv->fd, evBuf, sizeof(evBuf));
  505.  
  506.     if (nBytes < 0) {
  507.     if (errno == EWOULDBLOCK) {
  508.         *pNumEvents = 0;
  509.         *pAgain = FALSE;
  510.     } else {
  511.         Error ("Reading keyboard");
  512.         FatalError ("Could not read the keyboard");
  513.     }
  514.     } else {
  515.     *pNumEvents = nBytes / sizeof (Firm_event);
  516.     *pAgain = (nBytes == sizeof (evBuf));
  517.     }
  518.     return (evBuf);
  519. }
  520.  
  521. /*-
  522.  *-----------------------------------------------------------------------
  523.  * sunKbdEnqueueEvent --
  524.  *
  525.  * Results:
  526.  *
  527.  * Side Effects:
  528.  *
  529.  * Caveat:
  530.  *      To reduce duplication of code and logic (and therefore bugs), the
  531.  *      sunwindows version of kbd processing (sunKbdEnqueueEventSunWin())
  532.  *      counterfeits a firm event and calls this routine.  This
  533.  *      couunterfeiting relies on the fact this this routine only looks at the
  534.  *      id, time, and value fields of the firm event which it is passed.  If
  535.  *      this ever changes, the sunKbdEnqueueEventSunWin will also have to
  536.  *      change.
  537.  *
  538.  *-----------------------------------------------------------------------
  539.  */
  540.  
  541. static xEvent    autoRepeatEvent;
  542.  
  543. static void
  544. sunKbdEnqueueEvent (pKeyboard, fe)
  545.     DevicePtr      pKeyboard;
  546.     Firm_event      *fe;
  547. {
  548.     xEvent        xE;
  549.     KbPrivPtr        pPriv;
  550.     int            delta;
  551.     BYTE        key;
  552.     CARD8        keyModifiers;
  553.  
  554.     key = (fe->id & 0x7F) + sysKbPriv.offset;
  555.     keyModifiers = ((DeviceIntPtr)pKeyboard)->key->modifierMap[key];
  556.     if (autoRepeatKeyDown && (keyModifiers == 0) &&
  557.     ((fe->value == VKEY_DOWN) || (key == autoRepeatEvent.u.u.detail))) {
  558.     /*
  559.      * Kill AutoRepeater on any real non-modifier key down, or auto key up
  560.      */
  561.     autoRepeatKeyDown = 0;
  562.     }
  563.  
  564.     xE.u.keyButtonPointer.time = TVTOMILLI(fe->time);
  565.     xE.u.u.type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress);
  566.     xE.u.u.detail = key;
  567.  
  568.     if (keyModifiers & LockMask) {
  569.     if (xE.u.u.type == KeyRelease)
  570.         return; /* this assumes autorepeat is not desired */
  571.     if (BitIsOn(((DeviceIntPtr)pKeyboard)->key->down, key))
  572.         xE.u.u.type = KeyRelease;
  573.     sunKbdLockLight (pKeyboard, xE.u.u.type == KeyPress);
  574.     }
  575.  
  576.     if ((xE.u.u.type == KeyPress) && (keyModifiers == 0)) {
  577.     /* initialize new AutoRepeater event & mark AutoRepeater on */
  578.     autoRepeatEvent = xE;
  579.     autoRepeatFirst = TRUE;
  580.     autoRepeatKeyDown++;
  581.     autoRepeatLastKeyDownTv = fe->time;
  582.     }
  583.  
  584.     mieqEnqueue (&xE);
  585. }
  586.  
  587. sunEnqueueAutoRepeat ()
  588. {
  589.     int    oldmask;
  590.     int    delta;
  591.  
  592.     if (sysKbPriv.ctrl->autoRepeat != AutoRepeatModeOn) {
  593.     autoRepeatKeyDown = 0;
  594.     return;
  595.     }
  596.     /*
  597.      * Generate auto repeat event.    XXX one for now.
  598.      * Update time & pointer location of saved KeyPress event.
  599.      */
  600.  
  601.     delta = TVTOMILLI(autoRepeatDeltaTv);
  602.     autoRepeatFirst = FALSE;
  603.  
  604.     /*
  605.      * Fake a key up event and a key down event
  606.      * for the last key pressed.
  607.      */
  608.     autoRepeatEvent.u.keyButtonPointer.time += delta;
  609.     autoRepeatEvent.u.u.type = KeyRelease;
  610.     oldmask = sigblock (sigmask(SIGIO));
  611.     mieqEnqueue (&autoRepeatEvent);
  612.     autoRepeatEvent.u.u.type = KeyPress;
  613.     mieqEnqueue (&autoRepeatEvent);
  614.     sigsetmask (oldmask);
  615.     /* Update time of last key down */
  616.     tvplus(autoRepeatLastKeyDownTv, autoRepeatLastKeyDownTv, 
  617.             autoRepeatDeltaTv);
  618.  
  619. }
  620.  
  621. /*-
  622.  *-----------------------------------------------------------------------
  623.  * sunChangeKbdTranslation
  624.  *    Makes operating system calls to set keyboard translation 
  625.  *    and direction on or off.
  626.  *
  627.  * Results:
  628.  *    -1 if failure, else 0.
  629.  *
  630.  * Side Effects:
  631.  *     Changes kernel management of keyboard.
  632.  *
  633.  *-----------------------------------------------------------------------
  634.  */
  635. int
  636. sunChangeKbdTranslation(pKeyboard,makeTranslated)
  637.     DevicePtr pKeyboard;
  638.     Bool makeTranslated;
  639. {   
  640.     KbPrivPtr    pPriv;
  641.     int     kbdFd;
  642.     int     tmp;
  643.     int        kbdOpenedHere;
  644.     int        old_mask;
  645.     int        toread;
  646.     char    junk[8192];
  647.  
  648.     static struct timeval lastChngKbdTransTv;
  649.     struct timeval tv;
  650.     struct timeval lastChngKbdDeltaTv;
  651.     int lastChngKbdDelta;
  652.  
  653.     /*
  654.      * Workaround for SS1 serial driver kernel bug when KIOCTRANS ioctl()s
  655.      * occur too closely together in time.
  656.      */
  657.     old_mask = sigblock (~0);
  658.     gettimeofday(&tv, (struct timezone *) NULL);
  659.     tvminus(lastChngKbdDeltaTv, tv, lastChngKbdTransTv);
  660.     lastChngKbdDelta = TVTOMILLI(lastChngKbdDeltaTv);
  661.     if (lastChngKbdDelta < 750) {
  662.     struct timeval wait;
  663.  
  664.     /*
  665.          * We need to guarantee at least 750 milliseconds between
  666.      * calls to KIOCTRANS. YUCK!
  667.      */
  668.     wait.tv_sec = 0;
  669.     wait.tv_usec = (750L - lastChngKbdDelta) * 1000L;
  670.         (void) select(0, (int *)0, (int *)0, (int *)0, &wait);
  671.         gettimeofday(&tv, (struct timezone *) NULL);
  672.     }
  673.     lastChngKbdTransTv = tv;
  674.  
  675.     kbdFd = -1;
  676.     if (pKeyboard)
  677.     {
  678.         pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
  679.     if (pPriv)
  680.         kbdFd = pPriv->fd;
  681.     }
  682.  
  683.     kbdOpenedHere = ( kbdFd < 0 );
  684.     if ( kbdOpenedHere ) {
  685.     kbdFd = open("/dev/kbd", O_RDONLY, 0);
  686.     if ( kbdFd < 0 ) {
  687.         Error( "sunChangeKbdTranslation: Can't open keyboard" );
  688.         goto bad;
  689.     }
  690.     }
  691.     
  692.     if (makeTranslated) {
  693.         /*
  694.          * Next set the keyboard into "direct" mode and turn on
  695.          * event translation. If either of these fails, we can't go
  696.          * on.
  697.          */
  698.     if ( ! sunUseSunWindows() ) {
  699.         tmp = 1;
  700.         if (ioctl (kbdFd, KIOCSDIRECT, &tmp) < 0) {
  701.         Error ("Setting keyboard direct mode");
  702.         goto bad;
  703.         }
  704.     }
  705.     tmp = TR_UNTRANS_EVENT;
  706.     if (ioctl (kbdFd, KIOCTRANS, &tmp) < 0) {
  707.         ErrorF("sunChangeKbdTranslation: kbdFd=%d\n",kbdFd);
  708.         Error ("Setting keyboard translation");
  709.         goto bad;
  710.     }
  711.     }
  712.     else {
  713.         /*
  714.          * Next set the keyboard into "indirect" mode and turn off
  715.          * event translation.
  716.          */
  717.     if ( ! sunUseSunWindows() ) {
  718.         tmp = 0;
  719.         (void)ioctl (kbdFd, KIOCSDIRECT, &tmp);
  720.         tmp = TR_ASCII;
  721.     }
  722.     else if (pKeyboard && pPriv && pPriv->devPrivate)
  723.         tmp = ((SunKbPrivPtr)pPriv->devPrivate)->trans;
  724.     else
  725.         tmp = TR_ASCII;
  726.     (void)ioctl (kbdFd, KIOCTRANS, &tmp);
  727.     }
  728.  
  729.     if (ioctl (kbdFd, FIONREAD, &toread) != -1 && toread > 0) {
  730.     while (toread) {
  731.         tmp = toread;
  732.         if (toread > sizeof (junk))
  733.         tmp = sizeof (junk);
  734.         (void) read (kbdFd, junk, tmp);
  735.         toread -= tmp;
  736.     }
  737.     }
  738.     if ( kbdOpenedHere )
  739.     (void) close( kbdFd );
  740.     sigsetmask (old_mask);
  741.     return(0);
  742.  
  743. bad:
  744.     if ( kbdOpenedHere && kbdFd >= 0 )
  745.     (void) close( kbdFd );
  746.     sigsetmask (old_mask);
  747.     return(-1);
  748. }
  749.  
  750. #ifdef SUN_WINDOWS
  751.  
  752. /*-
  753.  *-----------------------------------------------------------------------
  754.  * sunSetUpKbdSunWin
  755.  *    Change which events the kernel will pass through as keyboard
  756.  *     events.
  757.  *
  758.  *    Does NOT affect keyboard translation.
  759.  *
  760.  * Results:
  761.  *    Inputevent mask modified.
  762.  *
  763.  * Side Effects:
  764.  *
  765.  *-----------------------------------------------------------------------
  766.  */
  767.  
  768. Bool
  769. sunSetUpKbdSunWin(windowFd, onoff)
  770.     int windowFd;
  771.     Bool onoff;
  772. {
  773.     struct inputmask inputMask;
  774.     static struct inputmask oldInputMask;
  775.  
  776.     if (onoff) {
  777.         register int i;
  778.  
  779.     win_get_kbd_mask(windowFd, &oldInputMask);
  780.     input_imnull(&inputMask);
  781.     inputMask.im_flags |= 
  782.         IM_ASCII | IM_NEGASCII | 
  783.         IM_META | IM_NEGMETA | 
  784.         IM_NEGEVENT | IM_INTRANSIT;
  785.     win_setinputcodebit(&inputMask, KBD_USE);
  786.     win_setinputcodebit(&inputMask, KBD_DONE);
  787.     win_setinputcodebit(&inputMask, SHIFT_CAPSLOCK);
  788.     win_setinputcodebit(&inputMask, SHIFT_LOCK);
  789.     win_setinputcodebit(&inputMask, SHIFT_LEFT);
  790.     win_setinputcodebit(&inputMask, SHIFT_RIGHT);
  791.     win_setinputcodebit(&inputMask, SHIFT_LEFTCTRL);
  792.     win_setinputcodebit(&inputMask, SHIFT_RIGHTCTRL);
  793.     win_setinputcodebit(&inputMask, SHIFT_META);
  794.     win_setinputcodebit(&inputMask, WIN_STOP);
  795.  
  796.         for (i=KEY_LEFTFIRST; i<=KEY_LEFTLAST; i++) {
  797.             win_setinputcodebit(&inputMask, i);
  798.         }
  799.         for (i=KEY_TOPFIRST; i<=KEY_TOPLAST; i++) {
  800.             win_setinputcodebit(&inputMask, i);
  801.         }
  802.         for (i=KEY_RIGHTFIRST; i<=KEY_RIGHTLAST; i++) {
  803.             win_setinputcodebit(&inputMask, i);
  804.         }
  805.  
  806.     win_set_kbd_mask(windowFd, &inputMask);
  807.     }
  808.     else {
  809.     win_set_kbd_mask(windowFd, &oldInputMask);
  810.     }
  811.     return (TRUE);
  812. }
  813.  
  814. #endif SUN_WINDOWS
  815.  
  816.  
  817. #ifdef SUN_WINDOWS
  818.  
  819. /*-
  820.  *-----------------------------------------------------------------------
  821.  * sunKbdEnqueueEventSunWin
  822.  *    Process sunwindows event destined for the keyboard.
  823.  *      Rather than replicate the logic (and therefore replicate
  824.  *     bug fixes, etc), this code counterfeits a vuid 
  825.  *    Firm_event and then uses the non-sunwindows code.
  826.  *     
  827.  * Results:
  828.  *
  829.  * Side Effects:
  830.  *
  831.  *-----------------------------------------------------------------------
  832.  */
  833.  
  834. void
  835. sunKbdEnqueueEventSunWin(pKeyboard,se)
  836.     DeviceRec *pKeyboard;
  837.     register struct inputevent *se;
  838. {   
  839.     Firm_event    fe;
  840.  
  841.     fe.time = event_time(se);
  842.     fe.id = event_id(se);
  843.     fe.value = (event_is_up(se) ? VKEY_UP : VKEY_DOWN);
  844.  
  845.     sunKbdEnqueueEvent (pKeyboard, &fe);
  846. }
  847. #endif SUN_WINDOWS
  848.  
  849. /*ARGSUSED*/
  850. Bool
  851. LegalModifier(key, pDev)
  852.     BYTE    key;
  853.     DevicePtr    pDev;
  854. {
  855.     return (TRUE);
  856. }
  857.  
  858. static KeybdCtrl *pKbdCtrl = (KeybdCtrl *) 0;
  859.  
  860. /*ARGSUSED*/
  861. void
  862. sunBlockHandler(nscreen, pbdata, pptv, pReadmask)
  863.     int nscreen;
  864.     pointer pbdata;
  865.     struct timeval **pptv;
  866.     pointer pReadmask;
  867. {
  868.     static struct timeval artv = { 0, 0 };    /* autorepeat timeval */
  869.  
  870.     if (!autoRepeatKeyDown)
  871.     return;
  872.  
  873.     if (pKbdCtrl == (KeybdCtrl *) 0)
  874.     pKbdCtrl = ((KbPrivPtr) LookupKeyboardDevice()->devicePrivate)->ctrl;
  875.  
  876.     if (pKbdCtrl->autoRepeat != AutoRepeatModeOn)
  877.     return;
  878.  
  879.     if (autoRepeatFirst == TRUE)
  880.     artv.tv_usec = autoRepeatInitiate;
  881.     else
  882.     artv.tv_usec = autoRepeatDelay;
  883.     *pptv = &artv;
  884.  
  885. }
  886.  
  887. /*ARGSUSED*/
  888. void
  889. sunWakeupHandler(nscreen, pbdata, err, pReadmask)
  890.     int nscreen;
  891.     pointer pbdata;
  892.     unsigned long err;
  893.     pointer pReadmask;
  894. {
  895.     struct timeval tv;
  896.  
  897.     if (pKbdCtrl == (KeybdCtrl *) 0)
  898.     pKbdCtrl = ((KbPrivPtr) LookupKeyboardDevice()->devicePrivate)->ctrl;
  899.  
  900.     if (pKbdCtrl->autoRepeat != AutoRepeatModeOn)
  901.     return;
  902.  
  903.     if (autoRepeatKeyDown) {
  904.     gettimeofday(&tv, (struct timezone *) NULL);
  905.     tvminus(autoRepeatDeltaTv, tv, autoRepeatLastKeyDownTv);
  906.     if (autoRepeatDeltaTv.tv_sec > 0 ||
  907.             (!autoRepeatFirst && autoRepeatDeltaTv.tv_usec >
  908.                 autoRepeatDelay) ||
  909.             (autoRepeatDeltaTv.tv_usec >
  910.                 autoRepeatInitiate))
  911.         autoRepeatReady++;
  912.     }
  913.     
  914.     if (autoRepeatReady)
  915.     {
  916.     sunEnqueueAutoRepeat ();
  917.     autoRepeatReady = 0;
  918.     }
  919. }
  920.