/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Events.c,v 3.42.2.6 1998/11/06 09:46:25 hohndel Exp $ */
/*
 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, 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 Thomas Roell not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Thomas Roell makes no representations
 * about the suitability of this software for any purpose.  It is provided
 * "as is" without express or implied warranty.
 *
 * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THOMAS ROELL 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.
 *
 */
/* $XConsortium: xf86Events.c /main/46 1996/10/25 11:36:30 kaleb $ */

/* [JCH-96/01/21] Extended std reverse map to four buttons. */

#include <math.h>

#define NEED_EVENTS
#include "X.h"
#include "Xproto.h"
#include "misc.h"
#include "inputstr.h"
#include "scrnintstr.h"

#include "compiler.h"

#include "Xpoll.h"
#include "xf86Procs.h"
#include "xf86_OSlib.h"
#include "xf86_Config.h"
#include "atKeynames.h"


#ifdef XFreeXDGA
#include "XIproto.h"
#include "extnsionst.h"
#include "scrnintstr.h"
#include "servermd.h"

#include "exevents.h"

#define _XF86DGA_SERVER_
#include "extensions/xf86dgastr.h"
#endif

#ifdef XINPUT
#include "XI.h"
#include "XIproto.h"
#include "xf86Xinput.h"
#endif

#include "mipointer.h"
#include "dixevents.h"
#include "opaque.h"
#ifdef DPMSExtension
#include "extensions/dpms.h"
#endif

#ifdef XKB
extern Bool noXkbExtension;
#endif

#define XE_POINTER  1
#define XE_KEYBOARD 2

#ifdef XTESTEXT1

#define	XTestSERVER_SIDE
#include "xtestext1.h"
extern short xtest_mousex;
extern short xtest_mousey;
extern int   on_steal_input;          
extern Bool  XTestStealKeyData();
extern void  XTestStealMotionData();

#ifdef XINPUT
#define ENQUEUE(ev, code, direction, dev_type) \
  (ev)->u.u.detail = (code); \
  (ev)->u.u.type   = (direction); \
  if (!on_steal_input ||  \
      XTestStealKeyData((ev)->u.u.detail, (ev)->u.u.type, dev_type, \
			xtest_mousex, xtest_mousey)) \
  xf86eqEnqueue((ev))
#else
#define ENQUEUE(ev, code, direction, dev_type) \
  (ev)->u.u.detail = (code); \
  (ev)->u.u.type   = (direction); \
  if (!on_steal_input ||  \
      XTestStealKeyData((ev)->u.u.detail, (ev)->u.u.type, dev_type, \
			xtest_mousex, xtest_mousey)) \
  mieqEnqueue((ev))
#endif

#define MOVEPOINTER(dx, dy, time) \
  if (on_steal_input) \
    XTestStealMotionData(dx, dy, XE_POINTER, xtest_mousex, xtest_mousey); \
  miPointerDeltaCursor (dx, dy, time)

#else /* ! XTESTEXT1 */

#ifdef XINPUT
#define ENQUEUE(ev, code, direction, dev_type) \
  (ev)->u.u.detail = (code); \
  (ev)->u.u.type   = (direction); \
  xf86eqEnqueue((ev))
#else
#define ENQUEUE(ev, code, direction, dev_type) \
  (ev)->u.u.detail = (code); \
  (ev)->u.u.type   = (direction); \
  mieqEnqueue((ev))
#endif
#define MOVEPOINTER(dx, dy, time) \
  miPointerDeltaCursor (dx, dy, time)

#endif

Bool xf86VTSema = TRUE;

#ifdef	XINPUT
extern	InputInfo 	inputInfo;
#endif	/* XINPUT */

/*
 * The first of many hack's to get VT switching to work under
 * Solaris 2.1 for x86. The basic problem is that Solaris is supposed
 * to be SVR4. It is for the most part, except where the video interface
 * is concerned.  These hacks work around those problems.
 * See the comments for Linux, and SCO. 
 *
 * This is a toggleling variable:
 *  FALSE = No VT switching keys have been pressed last time around
 *  TRUE  = Possible VT switch Pending
 * (DWH - 12/2/93)
 *
 * This has been generalised to work with Linux and *BSD+syscons (DHD)
 */

#ifdef USE_VT_SYSREQ
static Bool VTSysreqToggle = FALSE;
#endif /* !USE_VT_SYSREQ */
static Bool VTSwitchEnabled = TRUE;   /* Allows run-time disabling for *BSD */

extern fd_set EnabledDevices;

#if defined(CODRV_SUPPORT)
extern unsigned char xf86CodrvMap[];
#endif

#if defined(XQUEUE) && !defined(XQUEUE_ASYNC)
extern void xf86XqueRequest(
#if NeedFunctionPrototypes
	void
#endif
	);
#endif

static void xf86VTSwitch(
#if NeedFunctionPrototypes
	void
#endif
	);
#ifdef XFreeXDGA
#ifdef XINPUT
void XF86DirectVideoMoveMouse(
#else
static void XF86DirectVideoMoveMouse(
#endif
#if NeedFunctionPrototypes
	int x,
	int y,
	CARD32 mtime
#endif
	);
static void XF86DirectVideoKeyEvent(
#if NeedFunctionPrototypes
	xEvent *xE,
	int keycode,
	int etype
#endif
	);
#endif
static CARD32 buttonTimer(
#if NeedFunctionPrototypes
	OsTimerPtr timer,
	CARD32 now,
	pointer arg
#endif
     	);

/*
 * Lets create a simple finite-state machine:
 *
 *   state[?][0]: action1
 *   state[?][1]: action2
 *   state[?][2]: next state
 *
 *   action > 0: ButtonPress
 *   action = 0: nothing
 *   action < 0: ButtonRelease
 *
 * Why this stuff ??? Normally you cannot press both mousebuttons together, so
 * the mouse reports both pressed at the same time ...
 */

static signed char stateTab[48][3] = {

/* nothing pressed */
  {  0,  0,  0 },	
  {  0,  0,  8 },	/* 1 right -> delayed right */
  {  0,  0,  0 },       /* 2 nothing */
  {  0,  0,  8 },	/* 3 right -> delayed right */
  {  0,  0, 16 },	/* 4 left -> delayed left */
  {  2,  0, 24 },       /* 5 left & right (middle press) -> middle pressed */
  {  0,  0, 16 },	/* 6 left -> delayed left */
  {  2,  0, 24 },       /* 7 left & right (middle press) -> middle pressed */

/* delayed right */
  {  1, -1,  0 },	/* 8 nothing (right event) -> init */
  {  1,  0, 32 },       /* 9 right (right press) -> right pressed */
  {  1, -1,  0 },	/* 10 nothing (right event) -> init */
  {  1,  0, 32 },       /* 11 right (right press) -> right pressed */
  {  1, -1, 16 },       /* 12 left (right event) -> delayed left */
  {  2,  0, 24 },       /* 13 left & right (middle press) -> middle pressed */
  {  1, -1, 16 },       /* 14 left (right event) -> delayed left */
  {  2,  0, 24 },       /* 15 left & right (middle press) -> middle pressed */

/* delayed left */
  {  3, -3,  0 },	/* 16 nothing (left event) -> init */
  {  3, -3,  8 },       /* 17 right (left event) -> delayed right */
  {  3, -3,  0 },	/* 18 nothing (left event) -> init */
  {  3, -3,  8 },       /* 19 right (left event) -> delayed right */
  {  3,  0, 40 },	/* 20 left (left press) -> pressed left */
  {  2,  0, 24 },	/* 21 left & right (middle press) -> pressed middle */
  {  3,  0, 40 },	/* 22 left (left press) -> pressed left */
  {  2,  0, 24 },	/* 23 left & right (middle press) -> pressed middle */

/* pressed middle */
  { -2,  0,  0 },	/* 24 nothing (middle release) -> init */
  { -2,  0,  0 },	/* 25 right (middle release) -> init */
  { -2,  0,  0 },	/* 26 nothing (middle release) -> init */
  { -2,  0,  0 },	/* 27 right (middle release) -> init */
  { -2,  0,  0 },	/* 28 left (middle release) -> init */
  {  0,  0, 24 },	/* 29 left & right -> pressed middle */
  { -2,  0,  0 },	/* 30 left (middle release) -> init */
  {  0,  0, 24 },	/* 31 left & right -> pressed middle */

/* pressed right */
  { -1,  0,  0 },	/* 32 nothing (right release) -> init */
  {  0,  0, 32 },	/* 33 right -> pressed right */
  { -1,  0,  0 },	/* 34 nothing (right release) -> init */
  {  0,  0, 32 },	/* 35 right -> pressed right */
  { -1,  0, 16 },	/* 36 left (right release) -> delayed left */
  { -1,  2, 24 },	/* 37 left & right (r rel, m prs) -> middle pressed */
  { -1,  0, 16 },	/* 38 left (right release) -> delayed left */
  { -1,  2, 24 },	/* 39 left & right (r rel, m prs) -> middle pressed */

/* pressed left */
  { -3,  0,  0 },	/* 40 nothing (left release) -> init */
  { -3,  0,  8 },	/* 41 right (left release) -> delayed right */
  { -3,  0,  0 },	/* 42 nothing (left release) -> init */
  { -3,  0,  8 },	/* 43 right (left release) -> delayed right */
  {  0,  0, 40 },	/* 44 left -> left pressed */
  { -3,  2, 24 },	/* 45 left & right (l rel, mprs) -> middle pressed */
  {  0,  0, 40 },	/* 46 left -> left pressed */
  { -3,  2, 24 },	/* 47 left & right (l rel, mprs) -> middle pressed */
};


/*
 * Table to allow quick reversal of natural button mapping to correct mapping
 */

/*
 * [JCH-96/01/21] The ALPS GlidePoint pad extends the MS protocol
 * with a fourth button activated by tapping the PAD.
 * The 2nd line corresponds to 4th button on; the drv sends
 * the buttons in the following map (MSBit described first) :
 * 0 | 4th | 1st | 2nd | 3rd
 * And we remap them (MSBit described first) :
 * 0 | 4th | 3rd | 2nd | 1st
 */
static char reverseMap[32] = { 0,  4,  2,  6,  1,  5,  3,  7,
			       8, 12, 10, 14,  9, 13, 11, 15,
			      16, 20, 18, 22, 17, 21, 19, 23,
			      24, 28, 26, 30, 25, 29, 27, 31};


static char hitachMap[16] = {  0,  2,  1,  3, 
			       8, 10,  9, 11,
			       4,  6,  5,  7,
			      12, 14, 13, 15 };


/*
 * TimeSinceLastInputEvent --
 *      Function used for screensaver purposes by the os module. Retruns the
 *      time in milliseconds since there last was any input.
 */

int
TimeSinceLastInputEvent()
{
  if (xf86Info.lastEventTime == 0) {
    xf86Info.lastEventTime = GetTimeInMillis();
  }
  return GetTimeInMillis() - xf86Info.lastEventTime;
}



/*
 * SetTimeSinceLastInputEvent --
 *      Set the lastEventTime to now.
 */

void
SetTimeSinceLastInputEvent()
{
  xf86Info.lastEventTime = GetTimeInMillis();
}



/*
 * ProcessInputEvents --
 *      Retrieve all waiting input events and pass them to DIX in their
 *      correct chronological order. Only reads from the system pointer
 *      and keyboard.
 */

void
ProcessInputEvents ()
{
  int x, y;
#ifdef INHERIT_LOCK_STATE
  static int generation = 0;
#endif

#ifdef AMOEBA
#define MAXEVENTS	    32
#define BUTTON_PRESS	    0x1000
#define MAP_BUTTON(ev,but)  (((ev) == EV_ButtonPress) ? \
			     ((but) | BUTTON_PRESS) : ((but) & ~BUTTON_PRESS))
#define KEY_RELEASE	    0x80
#define MAP_KEY(ev, key)    (((ev) == EV_KeyReleaseEvent) ? \
			     ((key) | KEY_RELEASE) : ((key) & ~KEY_RELEASE))

    register IOPEvent  *e, *elast;
    IOPEvent		events[MAXEVENTS];
    int			dx, dy, nevents;
#endif

    /*
     * With INHERIT_LOCK_STATE defined, the initial state of CapsLock, NumLock
     * and ScrollLock will be set to match that of the VT the server is
     * running on.
     */
#ifdef INHERIT_LOCK_STATE
    if (generation != serverGeneration) {
      xEvent kevent;
      DevicePtr pKeyboard = xf86Info.pKeyboard;
      extern unsigned int xf86InitialCaps, xf86InitialNum, xf86InitialScroll;

      generation = serverGeneration;
      kevent.u.keyButtonPointer.time = GetTimeInMillis();
      kevent.u.keyButtonPointer.rootX = 0;
      kevent.u.keyButtonPointer.rootY = 0;
      kevent.u.u.type = KeyPress;


      if (xf86InitialCaps) {
        kevent.u.u.detail = xf86InitialCaps;
        (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1);
        xf86InitialCaps = 0;
      }
      if (xf86InitialNum) {
        kevent.u.u.detail = xf86InitialNum;
        (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1);
        xf86InitialNum = 0;
      }
      if (xf86InitialScroll) {
        kevent.u.u.detail = xf86InitialScroll;
        (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1);
        xf86InitialScroll = 0;
      }
    }
#endif

#ifdef AMOEBA
    /*
     * Get all events from the IOP server
     */
    while ((nevents = AmoebaGetEvents(events, MAXEVENTS)) > 0) {
      for (e = &events[0], elast = &events[nevents]; e < elast; e++) {
          xf86Info.lastEventTime = e->time;
          switch (e->type) {
          case EV_PointerDelta:
	      if (e->x != 0 || e->y != 0) {
                  xf86PostMseEvent(&xf86Info.pMouse, 0, e->x, e->y);
	      }
              break;
          case EV_ButtonPress:
          case EV_ButtonRelease:
              xf86PostMseEvent(&xf86Info.pMouse, MAP_BUTTON(e->type, e->keyorbut), 0, 0);
              break;
          case EV_KeyPressEvent:
          case EV_KeyReleaseEvent:
              xf86PostKbdEvent(MAP_KEY(e->type, e->keyorbut));
              break;
          default:
              /* this shouldn't happen */
              ErrorF("stray event %d (%d,%d) %x\n",
                      e->type, e->x, e->y, e->keyorbut);
              break;
          }
      }
    }
#endif

  xf86Info.inputPending = FALSE;

#ifdef XINPUT
  xf86eqProcessInputEvents();
#else
  mieqProcessInputEvents();
#endif
  miPointerUpdate();

  miPointerPosition(&x, &y);
  xf86SetViewport(xf86Info.currentScreen, x, y);
}



/*
 * xf86PostKbdEvent --
 *	Translate the raw hardware KbdEvent into an XEvent, and tell DIX
 *	about it. Scancode preprocessing and so on is done ...
 *
 *  OS/2 specific xf86PostKbdEvent(key) has been moved to os-support/os2/os2_kbd.c
 *  as some things differ, and I did not want to scatter this routine with
 *  ifdefs further (hv).
 */

#ifdef ASSUME_CUSTOM_KEYCODES
extern u_char SpecialServerMap[];
#endif /* ASSUME_CUSTOM_KEYCODES */

#if !defined(__EMX__)
void
xf86PostKbdEvent(key)
     unsigned key;
{
  int         scanCode = (key & 0x7f);
  int         specialkey;
  Bool        down = (key & 0x80 ? FALSE : TRUE);
  KeyClassRec *keyc = ((DeviceIntPtr)xf86Info.pKeyboard)->key;
  Bool        updateLeds = FALSE;
  Bool        UsePrefix = FALSE;
  Bool        Direction = FALSE;
  xEvent      kevent;
  KeySym      *keysym;
  int         keycode;
  static int  lockkeys = 0;
#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT)
  static Bool first_time = TRUE;
#endif

#if defined(CODRV_SUPPORT)
  if (xf86Info.consType == CODRV011 || xf86Info.consType == CODRV01X)
    scanCode = xf86CodrvMap[scanCode];
#endif

#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT)
  if (first_time)
  {
    first_time = FALSE;
    VTSwitchEnabled = (xf86Info.consType == SYSCONS)
	    || (xf86Info.consType == PCVT);
  }
#endif

#if defined (i386) && defined (SVR4) && !defined (PC98)
    /* 
     * PANIX returns DICOP standards based keycodes in using 106jp 
     * keyboard. We need to remap some keys. 
     */
#define KEY_P_UP	0x5A
#define KEY_P_PGUP	0x5B
#define KEY_P_LEFT	0x5C
#define KEY_P_BKSL	0x73
#define KEY_P_YEN	0x7D
#define KEY_P_NFER	0x7B
#define KEY_P_XFER	0x79

  if(xf86Info.panix106 == TRUE){
    switch (scanCode) {
    /* case 0x78:        scanCode = KEY_P_UP;     break;   not needed*/
    case 0x56:        scanCode = KEY_P_BKSL;   break;  /* Backslash */
    case 0x5A:        scanCode = KEY_P_NFER;   break;  /* No Kanji Transfer*/
    case 0x5B:        scanCode = KEY_P_XFER;   break;  /* Kanji Tranfer */
    case 0x5C:        scanCode = KEY_P_YEN;    break;  /* Yen curs pgup */
    case 0x6B:        scanCode = KEY_P_LEFT;   break;  /* Cur Left */
    case 0x6F:        scanCode = KEY_P_PGUP;   break;  /* Cur PageUp */
    case 0x72:        scanCode = KEY_AltLang;  break;  /* AltLang(right) */
    case 0x73:        scanCode = KEY_RCtrl;    break;  /* not needed */
    }
  }
#endif  /* i386 && SVR4 */

#ifndef ASSUME_CUSTOM_KEYCODES
  /*
   * First do some special scancode remapping ...
   */
  if (xf86Info.scanPrefix == 0) {

    switch (scanCode) {
      
#ifndef PC98
    case KEY_Prefix0:
    case KEY_Prefix1:
#if defined(PCCONS_SUPPORT) || defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT)
      if (xf86Info.consType == PCCONS || xf86Info.consType == SYSCONS
	  || xf86Info.consType == PCVT) {
#endif
        xf86Info.scanPrefix = scanCode;  /* special prefixes */
        return;
#if defined(PCCONS_SUPPORT) || defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT)
      }
      break;
#endif
#endif /* not PC98 */
    }
#ifndef PC98
    if (xf86Info.serverNumLock) {
     if ((!xf86Info.numLock && ModifierDown(ShiftMask)) ||
         (xf86Info.numLock && !ModifierDown(ShiftMask))) {
      /*
       * Hardwired numlock handling ... (Some applications break if they have
       * these keys double defined, like twm)
       */
      switch (scanCode) {
      case KEY_KP_7:        scanCode = KEY_SN_KP_7;   break;  /* curs 7 */
      case KEY_KP_8:        scanCode = KEY_SN_KP_8;   break;  /* curs 8 */
      case KEY_KP_9:        scanCode = KEY_SN_KP_9;   break;  /* curs 9 */
      case KEY_KP_4:        scanCode = KEY_SN_KP_4;   break;  /* curs 4 */
      case KEY_KP_5:        scanCode = KEY_SN_KP_5;   break;  /* curs 5 */
      case KEY_KP_6:        scanCode = KEY_SN_KP_6;   break;  /* curs 6 */
      case KEY_KP_1:        scanCode = KEY_SN_KP_1;   break;  /* curs 1 */
      case KEY_KP_2:        scanCode = KEY_SN_KP_2;   break;  /* curs 2 */
      case KEY_KP_3:        scanCode = KEY_SN_KP_3;   break;  /* curs 3 */
      case KEY_KP_0:        scanCode = KEY_SN_KP_0;   break;  /* curs 0 */
      case KEY_KP_Decimal:  scanCode = KEY_SN_KP_Dec; break;  /* curs decimal */
      }
     } else {
      switch (scanCode) {
      case KEY_KP_7:        scanCode = KEY_SN_KP_Home;  break;  /* curs home */
      case KEY_KP_8:        scanCode = KEY_SN_KP_Up  ;  break;  /* curs up */
      case KEY_KP_9:        scanCode = KEY_SN_KP_Prior; break;  /* curs pgup */
      case KEY_KP_4:        scanCode = KEY_SN_KP_Left;  break;  /* curs left */
      case KEY_KP_5:        scanCode = KEY_SN_KP_Begin; break;  /* curs begin */
      case KEY_KP_6:        scanCode = KEY_SN_KP_Right; break;  /* curs right */
      case KEY_KP_1:        scanCode = KEY_SN_KP_End;   break;  /* curs end */
      case KEY_KP_2:        scanCode = KEY_SN_KP_Down;  break;  /* curs down */
      case KEY_KP_3:        scanCode = KEY_SN_KP_Next;  break;  /* curs pgdn */
      case KEY_KP_0:        scanCode = KEY_SN_KP_Ins;   break;  /* curs ins */
      case KEY_KP_Decimal:  scanCode = KEY_SN_KP_Del;   break;  /* curs del */
      }
     }
    }
#endif /* not PC98 */
  }

#ifndef PC98
  else if (
#ifdef CSRG_BASED
           (xf86Info.consType == PCCONS || xf86Info.consType == SYSCONS
	    || xf86Info.consType == PCVT) &&
#endif
           (xf86Info.scanPrefix == KEY_Prefix0)) {
    xf86Info.scanPrefix = 0;
	  
    switch (scanCode) {
    case KEY_KP_7:        scanCode = KEY_Home;      break;  /* curs home */
    case KEY_KP_8:        scanCode = KEY_Up;        break;  /* curs up */
    case KEY_KP_9:        scanCode = KEY_PgUp;      break;  /* curs pgup */
    case KEY_KP_4:        scanCode = KEY_Left;      break;  /* curs left */
    case KEY_KP_5:        scanCode = KEY_Begin;     break;  /* curs begin */
    case KEY_KP_6:        scanCode = KEY_Right;     break;  /* curs right */
    case KEY_KP_1:        scanCode = KEY_End;       break;  /* curs end */
    case KEY_KP_2:        scanCode = KEY_Down;      break;  /* curs down */
    case KEY_KP_3:        scanCode = KEY_PgDown;    break;  /* curs pgdown */
    case KEY_KP_0:        scanCode = KEY_Insert;    break;  /* curs insert */
    case KEY_KP_Decimal:  scanCode = KEY_Delete;    break;  /* curs delete */
    case KEY_Enter:       scanCode = KEY_KP_Enter;  break;  /* keypad enter */
    case KEY_LCtrl:       scanCode = KEY_RCtrl;     break;  /* right ctrl */
    case KEY_KP_Multiply: scanCode = KEY_Print;     break;  /* print */
    case KEY_Slash:       scanCode = KEY_KP_Divide; break;  /* keyp divide */
    case KEY_Alt:         scanCode = KEY_AltLang;   break;  /* right alt */
    case KEY_ScrollLock:  scanCode = KEY_Break;     break;  /* curs break */
    case 0x5b:            scanCode = KEY_LMeta;     break;
    case 0x5c:            scanCode = KEY_RMeta;     break;
    case 0x5d:            scanCode = KEY_Menu;      break;
    case KEY_F3:          scanCode = KEY_F13;       break;
    case KEY_F4:          scanCode = KEY_F14;       break;
    case KEY_F5:          scanCode = KEY_F15;       break;
    case KEY_F6:          scanCode = KEY_F16;       break;
    case KEY_F7:          scanCode = KEY_F17;       break;
    case KEY_KP_Plus:     scanCode = KEY_KP_DEC;    break;
      /*
       * Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6)
       */
    default:
      return;                                  /* skip illegal */
    }
  }
  
  else if (xf86Info.scanPrefix == KEY_Prefix1)
    {
      xf86Info.scanPrefix = (scanCode == KEY_LCtrl) ? KEY_LCtrl : 0;
      return;
    }
  
  else if (xf86Info.scanPrefix == KEY_LCtrl)
    {
      xf86Info.scanPrefix = 0;
      if (scanCode != KEY_NumLock) return;
      scanCode = KEY_Pause;       /* pause */
    }
#endif /* not PC98 */  
#endif /* !ASSUME_CUSTOM_KEYCODES */

  /*
   * and now get some special keysequences
   */

#ifdef ASSUME_CUSTOM_KEYCODES
  specialkey = SpecialServerMap[scanCode];
#else /* ASSUME_CUSTOM_KEYCODES */
  specialkey = scanCode;
#endif /* ASSUME_CUSTOM_KEYCODES */

  if ((ModifierDown(ControlMask | AltMask)) ||
      (ModifierDown(ControlMask | AltLangMask)))
    {
      
      switch (specialkey) {
	
      case KEY_BackSpace:
	if (!xf86Info.dontZap) {
#ifdef XFreeXDGA
  if (((ScrnInfoPtr)(xf86Info.currentScreen->devPrivates[xf86ScreenIndex].ptr))->directMode&XF86DGADirectGraphics) 
	break;
#endif
	 GiveUp(0);
        }
	break;
	
	/*
	 * The idea here is to pass the scancode down to a list of
	 * registered routines. There should be some standard conventions
	 * for processing certain keys.
	 */
      case KEY_KP_Minus:   /* Keypad - */
	if (!xf86Info.dontZoom) {
	  if (down) xf86ZoomViewport(xf86Info.currentScreen, -1);
	  return;
	}
	break;
	
      case KEY_KP_Plus:   /* Keypad + */
	if (!xf86Info.dontZoom) {
	  if (down) xf86ZoomViewport(xf86Info.currentScreen,  1);
	  return;
	}
	break;

#if defined(linux) || (defined(CSRG_BASED) && (defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT))) || defined(SCO)
	/*
	 * Under Linux, the raw keycodes are consumed before the kernel
	 * does any processing on them, so we must emulate the vt switching
	 * we want ourselves.
	 */
      case KEY_F1:
      case KEY_F2:
      case KEY_F3:
      case KEY_F4:
      case KEY_F5:
      case KEY_F6:
      case KEY_F7:
      case KEY_F8:
      case KEY_F9:
      case KEY_F10:
        if (VTSwitchEnabled && !xf86Info.vtSysreq
#if (defined(CSRG_BASED) && (defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT)))
	    && (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT)
#endif
	    )
        {
	  if (down)
#ifdef SCO325
            ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey - KEY_F1);
#else
            ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey - KEY_F1 + 1);
#endif
          return;
        }
	break;
      case KEY_F11:
      case KEY_F12:
        if (VTSwitchEnabled && !xf86Info.vtSysreq
#if (defined(CSRG_BASED) && (defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT)))
	    && (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT)
#endif
	    )
        {
	  if (down)
#ifdef SCO325
            ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey - KEY_F11 + 10);
#else
            ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey - KEY_F11 + 11);
#endif
          return;
        }
	break;
#endif /* linux || BSD with VTs */

      /* just worth mentioning here: any 386bsd keyboard driver
       * (pccons.c or co_kbd.c) catches CTRL-ALT-DEL and CTRL-ALT-ESC
       * before any application (e.g. XF86) will see it
       * OBS: syscons does not, nor does pcvt !
       */
      } 
    }

    /*
     * Start of actual Solaris VT switching code.  
     * This should pretty much emulate standard SVR4 switching keys.
     * 
     * DWH 12/2/93
     */

#ifdef USE_VT_SYSREQ
    if (VTSwitchEnabled && xf86Info.vtSysreq)
    {
      switch (specialkey)
      {
      /*
       * syscons on *BSD doesn't have a VT #0  -- don't think Linux does
       * either
       */
#if defined (sun) && defined (i386) && defined (SVR4)
      case KEY_H: 
	if (VTSysreqToggle && down)
        {
          ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0);
          VTSysreqToggle = 0;
          return; 
        }
	break;

      /*
       * Yah, I know the N, and P keys seem backwards, however that's
       * how they work under Solaris
       * XXXX N means go to next active VT not necessarily vtno+1 (or vtno-1)
       */

      case KEY_N:
	if (VTSysreqToggle && down)
	{
          if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno - 1 ) < 0)
            ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
          VTSysreqToggle = FALSE;
          return;
        }
	break;

      case KEY_P:
	if (VTSysreqToggle && down)
	{
          if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno + 1 ) < 0)
            if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0) < 0)
              ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
          VTSysreqToggle = FALSE;
          return;
        }
	break;
#endif

      case KEY_F1:
      case KEY_F2:
      case KEY_F3:
      case KEY_F4:
      case KEY_F5:
      case KEY_F6:
      case KEY_F7:
      case KEY_F8:
      case KEY_F9:
      case KEY_F10:
	if (VTSysreqToggle && down)
	{
          if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey-KEY_F1 + 1) < 0)
            ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
          VTSysreqToggle = FALSE;
          return;
        }
	break;

      case KEY_F11:
      case KEY_F12:
	if (VTSysreqToggle && down)
	{
          if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, specialkey-KEY_F11 + 11) < 0)
            ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
          VTSysreqToggle = FALSE;
          return;
        }
	break;

      /* Ignore these keys -- ie don't let them cancel an alt-sysreq */
      case KEY_Alt:
#ifndef PC98
      case KEY_AltLang:
#endif /* not PC98 */
	break;

#ifndef PC98
      case KEY_SysReqest:
        if (down && (ModifierDown(AltMask) || ModifierDown(AltLangMask)))
          VTSysreqToggle = TRUE;
	break;
#endif /* not PC98 */

      default:
        if (VTSysreqToggle)
	{
	  /*
	   * We only land here when Alt-SysReq is followed by a
	   * non-switching key.
	   */
          VTSysreqToggle = FALSE;

        }
      }
    }

#endif /* USE_VT_SYSREQ */

#ifdef SCO
    /*
     *	With the console in raw mode, SCO will not switch consoles,
     *	you get around this by activating the next console along, if
     *	this fails then go back to console 0, if there is only one
     *	then it doesn't matter, switching to yourself is a nop as far
     *	as the console driver is concerned.
     *	We could do something similar to linux here but SCO ODT uses
     *	Ctrl-PrintScrn, so why change?
     */
    if (specialkey == KEY_Print && ModifierDown(ControlMask)) {
      if (down)
        if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno + 1) < 0)
          if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0) < 0)
            ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
      return;
    }
#endif /* SCO */

  /*
   * Now map the scancodes to real X-keycodes ...
   */
  keycode = scanCode + MIN_KEYCODE;
  keysym = (keyc->curKeySyms.map +
	    keyc->curKeySyms.mapWidth * 
	    (keycode - keyc->curKeySyms.minKeyCode));
#ifdef XKB
  if (noXkbExtension) {
#endif
  /*
   * Filter autorepeated caps/num/scroll lock keycodes.
   */
#define CAPSFLAG 0x01
#define NUMFLAG 0x02
#define SCROLLFLAG 0x04
#define MODEFLAG 0x08
  if( down ) {
    switch( keysym[0] ) {
        case XK_Caps_Lock :
          if (lockkeys & CAPSFLAG)
              return;
	  else
	      lockkeys |= CAPSFLAG;
          break;

        case XK_Num_Lock :
          if (lockkeys & NUMFLAG)
              return;
	  else
	      lockkeys |= NUMFLAG;
          break;

        case XK_Scroll_Lock :
          if (lockkeys & SCROLLFLAG)
              return;
	  else
	      lockkeys |= SCROLLFLAG;
          break;
    }
    if (keysym[1] == XF86XK_ModeLock)
    {
      if (lockkeys & MODEFLAG)
          return;
      else
          lockkeys |= MODEFLAG;
    }
      
  }
  else {
    switch( keysym[0] ) {
        case XK_Caps_Lock :
            lockkeys &= ~CAPSFLAG;
            break;

        case XK_Num_Lock :
            lockkeys &= ~NUMFLAG;
            break;

        case XK_Scroll_Lock :
            lockkeys &= ~SCROLLFLAG;
            break;
    }
    if (keysym[1] == XF86XK_ModeLock)
      lockkeys &= ~MODEFLAG;
  }

  /*
   * LockKey special handling:
   * ignore releases, toggle on & off on presses.
   * Don't deal with the Caps_Lock keysym directly, but check the lock modifier
   */
#ifndef PC98
  if (keyc->modifierMap[keycode] & LockMask ||
      keysym[0] == XK_Scroll_Lock ||
      keysym[1] == XF86XK_ModeLock ||
      keysym[0] == XK_Num_Lock)
    {
      Bool flag;

      if (!down) return;
      if (KeyPressed(keycode)) {
	down = !down;
	flag = FALSE;
      }
      else
	flag = TRUE;

      if (keyc->modifierMap[keycode] & LockMask)   xf86Info.capsLock   = flag;
      if (keysym[0] == XK_Num_Lock)    xf86Info.numLock    = flag;
      if (keysym[0] == XK_Scroll_Lock) xf86Info.scrollLock = flag;
      if (keysym[1] == XF86XK_ModeLock)   xf86Info.modeSwitchLock = flag;
      updateLeds = TRUE;
    }
#endif /* not PC98 */	

#ifndef ASSUME_CUSTOM_KEYCODES
  /*
   * normal, non-keypad keys
   */
  if (scanCode < KEY_KP_7 || scanCode > KEY_KP_Decimal) {
#if !defined(CSRG_BASED) && !defined(MACH386) && !defined(MINIX) && !defined(__OSF__)
    /*
     * magic ALT_L key on AT84 keyboards for multilingual support
     */
    if (xf86Info.kbdType == KB_84 &&
	ModifierDown(AltMask) &&
	keysym[2] != NoSymbol)
      {
	UsePrefix = TRUE;
	Direction = TRUE;
      }
#endif /* !CSRG_BASED && !MACH386 && !MINIX && !__OSF__ */
  }
#endif /* !ASSUME_CUSTOM_KEYCODES */
  if (updateLeds) xf86KbdLeds();
#ifdef XKB
  }
#endif

  /*
   * check for an autorepeat-event
   */
  if ((down && KeyPressed(keycode)) &&
      (xf86Info.autoRepeat != AutoRepeatModeOn || keyc->modifierMap[keycode]))
    return;

  xf86Info.lastEventTime = kevent.u.keyButtonPointer.time = GetTimeInMillis();
  /*
   * And now send these prefixes ...
   * NOTE: There cannot be multiple Mode_Switch keys !!!!
   */
  if (UsePrefix)
    {
      ENQUEUE(&kevent,
	      keyc->modifierKeyMap[keyc->maxKeysPerModifier*7],
	      (Direction ? KeyPress : KeyRelease),
	      XE_KEYBOARD);
      ENQUEUE(&kevent, keycode, (down ? KeyPress : KeyRelease), XE_KEYBOARD);
      ENQUEUE(&kevent,
	      keyc->modifierKeyMap[keyc->maxKeysPerModifier*7],
	      (Direction ? KeyRelease : KeyPress),
	      XE_KEYBOARD);
    }
  else 
    {
#ifdef XFreeXDGA
      if (((ScrnInfoPtr)(xf86Info.currentScreen->devPrivates[xf86ScreenIndex].ptr))->directMode&XF86DGADirectKeyb) {
	  XF86DirectVideoKeyEvent(&kevent, keycode, (down ? KeyPress : KeyRelease));
      } else
#endif
      {
         ENQUEUE(&kevent, keycode, (down ? KeyPress : KeyRelease), XE_KEYBOARD);

      }
    }
}
#endif /* !__EMX__ */


static CARD32
buttonTimer(timer, now, arg)
     OsTimerPtr timer;
     CARD32 now;
     pointer arg;
{
    MouseDevPtr	priv = MOUSE_DEV((DeviceIntPtr) arg);

    xf86PostMseEvent(((DeviceIntPtr) arg), priv->truebuttons, 0, 0);
    return(0);
}

/*      
 * xf86PostMseEvent --
 *	Translate the raw hardware MseEvent into an XEvent(s), and tell DIX
 *	about it. Perform a 3Button emulation if required.
 */

void
xf86PostMseEvent(device, buttons, dx, dy)
    DeviceIntPtr device;
    int buttons, dx, dy;
{
  static OsTimerPtr timer = NULL;
  MouseDevPtr private = MOUSE_DEV(device);
  int         id, change;
  int         truebuttons;
  xEvent      mevent[2];
#ifdef XINPUT
  deviceKeyButtonPointer	*xev = (deviceKeyButtonPointer *) mevent;
  deviceValuator		*xv = (deviceValuator *) (xev+1);
  int				is_pointer; /* the mouse is the pointer ? */
#endif

  float mult;
  static float dxremaind = 0.0, dyremaind = 0.0;

#ifdef AMOEBA
  int	      pressed;

  pressed = ((buttons & BUTTON_PRESS) != 0);
  buttons &= ~BUTTON_PRESS;
#endif

#ifdef XINPUT
  is_pointer = xf86IsCorePointer(device);

  if (!is_pointer) {
    xev->time = xf86Info.lastEventTime = GetTimeInMillis();
  }
  else
#endif
  xf86Info.lastEventTime = mevent->u.keyButtonPointer.time = GetTimeInMillis();

  truebuttons = buttons;
  if (private->mseType == P_MMHIT)
    buttons = hitachMap[buttons];
  else
    buttons = reverseMap[buttons];

  if (dx || dy) {

    /*
     * The accelaration stuff is now done in xf86Xinput.c when XInput
     * support is enabled.
     */
#ifndef XINPUT
    /*
     * accelerate the baby now if sqrt(dx*dx + dy*dy) > threshold !
     * but do some simpler arithmetic here...
     */

      if ( private->threshold ) 
      {
	  if ((abs(dx) + abs(dy)) >= private->threshold) {
	      dx = (dx * private->num) / private->den;
	      dy = (dy * private->num)/ private->den;
	  }
      }
      else
      {
#if 0
	  mult = sqrt((float)(dx*dx+dy*dy)) *
	      (float)(private->num) / (float)(private->den) + 0.5;
#else
	  mult = pow((float)(dx*dx+dy*dy), (float)(private->num) /
		     (float)(private->den) / 2.0) / 2.0;
#endif
	  if ( dx )
	  {
	      dxremaind = mult * (float)dx + dxremaind;
	      dx = (int)dxremaind;
	      dxremaind = dxremaind - (float)dx;
	  }
	  if ( dy )
	  {
	      dyremaind = mult * (float)dy + dyremaind;
	      dy = (int)dyremaind;
	      dyremaind = dyremaind - (float)dy;
	  }
      }

#ifdef XFreeXDGA
      if (((ScrnInfoPtr)(xf86Info.currentScreen->devPrivates[xf86ScreenIndex].ptr))->directMode&XF86DGADirectMouse) {
	XF86DirectVideoMoveMouse(dx, dy, mevent->u.keyButtonPointer.time);
      } else
#endif
	{
	  MOVEPOINTER(dx, dy, mevent->u.keyButtonPointer.time);
	}
#else
      xf86PostMotionEvent(device, 0, 0, 2, dx, dy);
#endif /* XINPUT */
  }

  if (private->emulate3Buttons)
    {

      /*
       * Hack to operate the middle button even with Emulate3Buttons set.
       * Modifying the state table to keep track of the middle button state
       * would nearly double its size, so I'll stick with this fix.  - TJW
       */
      if (private->mseType == P_MMHIT)
        change = buttons ^ hitachMap[private->lastButtons];
      else
        change = buttons ^ reverseMap[private->lastButtons];
      if (change & 02)
	{
#ifndef XINPUT
	  ENQUEUE(mevent,
		  2, (buttons & 02) ? ButtonPress : ButtonRelease,
		  XE_POINTER);
#else
	  xf86PostButtonEvent(device, 0, 2, (buttons & 02), 0, 0);	  
#endif
	}
      
      /*
       * emulate the third button by the other two
       */
      if ((id = stateTab[buttons + private->emulateState][0]) != 0)
	{
#ifndef XINPUT
            ENQUEUE(mevent,
                    abs(id), (id < 0 ? ButtonRelease : ButtonPress), 
                    XE_POINTER);
#else
	    xf86PostButtonEvent(device, 0, abs(id), (id >= 0), 0, 0);
#endif 
	}

      if ((id = stateTab[buttons + private->emulateState][1]) != 0)
	{
#ifndef XINPUT
            ENQUEUE(mevent,
                    abs(id), (id < 0 ? ButtonRelease : ButtonPress), 
                    XE_POINTER);
#else
	    xf86PostButtonEvent(device, 0, abs(id), (id >= 0), 0, 0);
#endif
	}

      private->emulateState = stateTab[buttons + private->emulateState][2];
      if (stateTab[buttons + private->emulateState][0] ||
          stateTab[buttons + private->emulateState][1])
        {
	    private->truebuttons = truebuttons;
	    timer = TimerSet(timer, 0, private->emulate3Timeout, buttonTimer,
			     (pointer)device);
        }
      else
        {
          if (timer)
            {
              TimerFree(timer);
              timer = NULL;
            }
        }
    }
  else
    {
#ifdef AMOEBA
      if (truebuttons != 0) {
# ifndef XINPUT
	    ENQUEUE(mevent,
		    truebuttons, (pressed ? ButtonPress : ButtonRelease),
		    XE_POINTER);
# else
	    xf86PostButtonEvent(device, 0, truebuttons, pressed, 0, 0);
# endif
      }
#else
      /*
       * real three button event
       * Note that xf86Info.lastButtons has the hardware button mapping which
       * is the reverse of the button mapping reported to the server.
       */
      if (private->mseType == P_MMHIT)
        change = buttons ^ hitachMap[private->lastButtons];
      else
        change = buttons ^ reverseMap[private->lastButtons];
      while (change)
	{
	  id = ffs(change);
	  change &= ~(1 << (id-1));
# ifndef XINPUT
            ENQUEUE(mevent,
                    id, (buttons&(1<<(id-1)))? ButtonPress : ButtonRelease,
                    XE_POINTER);
# else
	    xf86PostButtonEvent(device, 0, id, (buttons&(1<<(id-1))), 0, 0);
#endif
	}
#endif
    }
    private->lastButtons = truebuttons;
}



/*
 * xf86Block --
 *      Os block handler.
 */

/* ARGSUSED */
void
xf86Block(blockData, pTimeout, pReadmask)
     pointer blockData;
     OSTimePtr pTimeout;
     pointer  pReadmask;
{
}


#ifndef AMOEBA

/*
 * xf86Wakeup --
 *      Os wakeup handler.
 */

/* ARGSUSED */
void
xf86Wakeup(blockData, err, pReadmask)
     pointer blockData;
     int err;
     pointer pReadmask;
{

#ifndef __EMX__
#ifdef	__OSF__
  fd_set kbdDevices;
  fd_set mseDevices;
#endif	/* __OSF__ */
  fd_set* LastSelectMask = (fd_set*)pReadmask;
  fd_set devicesWithInput;

  if ((int)err >= 0) {
    XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices);
#ifdef	__OSF__
   /*
     * Until the two devices are made nonblock on read, we have to do this.
     */

    MASKANDSETBITS(devicesWithInput, pReadmask, EnabledDevices);

    CLEARBITS(kbdDevices);
    BITSET(kbdDevices, xf86Info.consoleFd);
    MASKANDSETBITS(kbdDevices, kbdDevices, devicesWithInput);

    CLEARBITS(mseDevices);
    BITSET(mseDevices, xf86Info.mouseDev->mseFd);
    MASKANDSETBITS(mseDevices, mseDevices, devicesWithInput);

    if (ANYSET(kbdDevices) || xf86Info.kbdRate)
        (xf86Info.kbdEvents)(ANYSET(kbdDevices));
    if (ANYSET(mseDevices))
        (xf86Info.mouseDev->mseEvents)(1);

#else
    if (XFD_ANYSET(&devicesWithInput))
      {
	(xf86Info.kbdEvents)();
	(xf86Info.mouseDev->mseEvents)(xf86Info.mouseDev);
      }
#endif	/* __OSF__ */
  }
#else   /* __EMX__ */

	(xf86Info.kbdEvents)();  /* Under OS/2, always call */
	(xf86Info.mouseDev->mseEvents)(xf86Info.mouseDev);

#endif  /* __EMX__ */

#if defined(XQUEUE) && !defined(XQUEUE_ASYNC)
  /* This could be done more cleanly */
  if (xf86Info.mouseDev->xqueSema && xf86Info.mouseDev->xquePending)
    xf86XqueRequest();
#endif

  if (xf86VTSwitchPending()) xf86VTSwitch();

  if (xf86Info.inputPending) ProcessInputEvents();
}

#endif /* AMOEBA */


/*
 * xf86SigHandler --
 *    Catch unexpected signals and exit cleanly.
 */
void
xf86SigHandler(signo)
     int signo;
{
  signal(signo,SIG_IGN);
  xf86Info.caughtSignal = TRUE;
  FatalError("Caught signal %d.  Server aborting\n", signo);
}

/*
 * xf86VTSwitch --
 *      Handle requests for switching the vt.
 */
static void
xf86VTSwitch()
{
  int j;

#ifdef XFreeXDGA
  /*
   * Not ideal, but until someone adds DGA events to the DGA client we
   * should protect the machine
   */
  if (((ScrnInfoPtr)(xf86Info.currentScreen->devPrivates[xf86ScreenIndex].ptr))->directMode&XF86DGADirectGraphics) {
   xf86Info.vtRequestsPending = FALSE;
   return;
  }
#endif
  if (xf86VTSema) {
    for (j = 0; j < screenInfo.numScreens; j++)
      (XF86SCRNINFO(screenInfo.screens[j])->EnterLeaveVT)(LEAVE, j);

#ifndef __EMX__
    DisableDevice((DeviceIntPtr)xf86Info.pKeyboard);
    DisableDevice((DeviceIntPtr)xf86Info.pMouse);
#endif

    if (!xf86VTSwitchAway()) {
      /*
       * switch failed 
       */

      for (j = 0; j < screenInfo.numScreens; j++)
        (XF86SCRNINFO(screenInfo.screens[j])->EnterLeaveVT)(ENTER, j);
      SaveScreens(SCREEN_SAVER_FORCER,ScreenSaverReset);
#ifdef DPMSExtension
      if (DPMSEnabled)
        DPMSSet(DPMSModeOn);
#endif

#ifndef __EMX__
      EnableDevice((DeviceIntPtr)xf86Info.pKeyboard);
      EnableDevice((DeviceIntPtr)xf86Info.pMouse);
#endif

    } else {
      xf86VTSema = FALSE;
    }
  } else {
    if (!xf86VTSwitchTo()) return;
      
    xf86VTSema = TRUE;
    for (j = 0; j < screenInfo.numScreens; j++)
      (XF86SCRNINFO(screenInfo.screens[j])->EnterLeaveVT)(ENTER, j);
      
    /* Turn screen saver off when switching back */
    SaveScreens(SCREEN_SAVER_FORCER,ScreenSaverReset);
#ifdef DPMSExtension
    if (DPMSEnabled)
      DPMSSet(DPMSModeOn);
#endif

#ifndef __EMX__
    EnableDevice((DeviceIntPtr)xf86Info.pKeyboard);
    EnableDevice((DeviceIntPtr)xf86Info.pMouse);
#endif

  }
}

#ifdef XTESTEXT1

void
XTestGetPointerPos(fmousex, fmousey)
     short *fmousex;
     short *fmousey;
{
  int x,y;

  miPointerPosition(&x, &y);
  *fmousex = x;
  *fmousey = y;
}



void
XTestJumpPointer(jx, jy, dev_type)
     int jx;
     int jy;
     int dev_type;
{
  miPointerAbsoluteCursor(jx, jy, GetTimeInMillis() );
}



void
XTestGenerateEvent(dev_type, keycode, keystate, mousex, mousey)
     int dev_type;
     int keycode;
     int keystate;
     int mousex;
     int mousey;
{
  xEvent tevent;
  
  tevent.u.u.type = (dev_type == XE_POINTER) ?
    (keystate == XTestKEY_UP) ? ButtonRelease : ButtonPress :
      (keystate == XTestKEY_UP) ? KeyRelease : KeyPress;
  tevent.u.u.detail = keycode;
  tevent.u.keyButtonPointer.rootX = mousex;
  tevent.u.keyButtonPointer.rootY = mousey;
  tevent.u.keyButtonPointer.time = xf86Info.lastEventTime = GetTimeInMillis();
#ifdef XINPUT
  xf86eqEnqueue(&tevent);
#else
  mieqEnqueue(&tevent);
#endif
  xf86Info.inputPending = TRUE;               /* virtual event */
}

#endif /* XTESTEXT1 */


#ifdef XFreeXDGA
#ifdef XINPUT
void
#else
static void
#endif
XF86DirectVideoMoveMouse(x, y, mtime)
     int x;
     int y;
     CARD32 mtime;
{
  xEvent xE;

  xE.u.u.type = MotionNotify;
  xE.u.keyButtonPointer.time = xf86Info.lastEventTime = mtime;
  xf86Info.lastEventTime = mtime;


  xE.u.keyButtonPointer.eventY = x;
  xE.u.keyButtonPointer.eventY = y;
  xE.u.keyButtonPointer.rootX = x;
  xE.u.keyButtonPointer.rootY = y;

  if (((DeviceIntPtr)(xf86Info.pMouse))->grab)
     DeliverGrabbedEvent(&xE, (xf86Info.pMouse), FALSE, 1);
  else
     DeliverDeviceEvents(GetSpriteWindow(), &xE, NullGrab, NullWindow,
			   (xf86Info.pMouse), 1);
}

static void
XF86DirectVideoKeyEvent(xE, keycode, etype)
xEvent *xE;
int keycode;
int etype;
{
  DeviceIntPtr keybd = (DeviceIntPtr)xf86Info.pKeyboard;
  KeyClassPtr keyc = keybd->key;
  BYTE *kptr;

  kptr = &keyc->down[keycode >> 3];
  xE->u.u.type = etype;
  xE->u.u.detail = keycode;

  /* clear the keypress state */
  if (etype == KeyPress) {
    *kptr &= ~(1 << (keycode & 7));
  }
  keybd->public.processInputProc(xE, keybd, 1);
}
#endif
