mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-15 23:55:03 -04:00
1167 lines
26 KiB
C
1167 lines
26 KiB
C
/***********************************************************
|
|
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
|
|
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
|
|
|
|
All Rights Reserved
|
|
|
|
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 names of Digital or MIT not be
|
|
used in advertising or publicity pertaining to distribution of the
|
|
software without specific, written prior permission.
|
|
|
|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
|
DIGITAL 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: qvss_io.c,v 1.105 91/07/17 17:26:20 rws Exp $ */
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/file.h>
|
|
#include <sys/time.h>
|
|
#include <sys/mman.h>
|
|
#include <errno.h>
|
|
|
|
#include <dev/wscons/wsconsio.h>
|
|
|
|
#include "X.h"
|
|
#define NEED_EVENTS
|
|
#include "Xproto.h"
|
|
#include "scrnintstr.h"
|
|
#include "cursorstr.h"
|
|
#include "pixmap.h"
|
|
#include "input.h"
|
|
#include "windowstr.h"
|
|
#include "regionstr.h"
|
|
#include "resource.h"
|
|
|
|
#include <machine/qvioctl.h>
|
|
|
|
#include "mfb.h"
|
|
#include "mi.h"
|
|
|
|
static Bool qvRealizeCursor(), qvUnrealizeCursor(), qvDisplayCursor();
|
|
static Bool qvSetCursorPosition();
|
|
static void qvCursorLimits();
|
|
static void qvPointerNonInterestBox();
|
|
static void qvConstrainCursor();
|
|
static void qvQueryBestSize();
|
|
void qvResolveColor();
|
|
Bool qvCreateColormap();
|
|
void qvDestroyColormap();
|
|
|
|
extern void miRecolorCursor();
|
|
static int qvGetMotionEvents();
|
|
static void qvChangePointerControl(), qvChangeKeyboardControl(), qvBell();
|
|
extern Bool mfbScreenInit();
|
|
|
|
extern int monitorResolution;
|
|
|
|
extern int errno;
|
|
|
|
/*
|
|
* Ultrix 3.0 uses new names for everything!
|
|
*/
|
|
#ifdef _QVEVENT_
|
|
# define ULTRIX3_0
|
|
#endif
|
|
|
|
#ifdef ULTRIX3_0
|
|
/*
|
|
* the stuff below makes this code work on
|
|
* both qv and sm drivers under Ultrix 3.0 (ne 2.4)
|
|
*/
|
|
|
|
/* XXX WARNING!!! This kludge assumes that
|
|
* the event/cursor/box structures are identical
|
|
* in size for both qv and sm. If they change
|
|
* radically, get help
|
|
*/
|
|
|
|
#undef QIOCGINFO
|
|
#undef QIOCSMSTATE
|
|
#undef QIOCINIT
|
|
#undef QIOCKPCMD
|
|
#undef QIOCADDR
|
|
#undef QIOWCURSOR
|
|
#undef QIOKERNLOOP
|
|
#undef QIOKERNUNLOOP
|
|
#undef QIODISPON
|
|
#undef QIOVIDEOON
|
|
#undef QIODISPOFF
|
|
#undef QIOVIDEOOFF
|
|
#undef QD_KERN_UNLOOP
|
|
#undef HOLD
|
|
|
|
#define mouse_report bogus_mouse_report
|
|
#define _event sm_event
|
|
#define _timecoord sm_timecoord
|
|
#define _eventqueue sm_eventqueue
|
|
#define _cursor sm_cursor
|
|
#define _box sm_box
|
|
|
|
# include <vaxuba/smioctl.h>
|
|
|
|
#undef mouse_report
|
|
#undef _event
|
|
#undef _timecoord
|
|
#undef _eventqueue
|
|
#undef _cursor
|
|
#undef _box
|
|
|
|
static Bool isSMdevice;
|
|
static struct sm_info *smInfo;
|
|
static struct qv_info *qvInfo;
|
|
|
|
/*
|
|
* magic defines to make the code below less
|
|
* ugly
|
|
*/
|
|
# define vsEventQueue qvEventQueue
|
|
# define vsCursor qvCursor
|
|
# define vsEvent qvEvent
|
|
# define vsTimeCoord qvTimeCoord
|
|
# define vsBox qvBox
|
|
# define head eHead
|
|
# define tail eTail
|
|
# define size eSize
|
|
# define vse_x x
|
|
# define vse_y y
|
|
# define vse_time time
|
|
# define vse_type type
|
|
# define vse_device device
|
|
# define vse_key key
|
|
# define vse_direction direction
|
|
# define VSE_KBTDOWN QV_KBTDOWN
|
|
# define VSE_KBTUP QV_KBTUP
|
|
# define VSE_KBTRAW QV_KBTRAW
|
|
# define VSE_BUTTON QV_BUTTON
|
|
|
|
#else
|
|
static struct qv_info *qvInfo;
|
|
static struct qv_info qvInfostore;
|
|
static short cursorbitsstore[16];
|
|
#endif
|
|
|
|
static vsEventQueue *queue;
|
|
static vsBox *mbox;
|
|
static vsCursor *mouse;
|
|
|
|
static caddr_t smaddr;
|
|
static int fdQVSS;
|
|
static int qLimit;
|
|
static int lastEventTime;
|
|
static DevicePtr qvKeyboard;
|
|
static DevicePtr qvPointer;
|
|
static int hotX, hotY;
|
|
static BoxRec constraintBox;
|
|
|
|
static Bool (*CloseScreen)();
|
|
|
|
#define MAX_LED 3 /* only 3 LED's can be set by user; Lock LED is controlled by server */
|
|
|
|
/* ARGSUSED */
|
|
static Bool qvssSaveScreen(pScreen, on)
|
|
ScreenPtr pScreen;
|
|
int on;
|
|
{
|
|
if (on == SCREEN_SAVER_FORCER)
|
|
{
|
|
lastEventTime = GetTimeInMillis();
|
|
return TRUE;
|
|
}
|
|
else if (on == SCREEN_SAVER_ON || on == SCREEN_SAVER_CYCLE)
|
|
{
|
|
#ifdef QIOVIDEOOFF
|
|
(void) ioctl(fdQVSS, QIOVIDEOOFF, (char *)NULL);
|
|
return TRUE;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef QIOVIDEOON
|
|
(void) ioctl(fdQVSS, QIOVIDEOON, (char *)NULL);
|
|
return TRUE;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static Bool
|
|
qvssScreenClose(index, pScreen)
|
|
int index;
|
|
ScreenPtr pScreen;
|
|
{
|
|
/* This routine frees all of the dynamically allocated space associate
|
|
with a screen. */
|
|
|
|
(*CloseScreen) (index, pScreen);
|
|
|
|
if(close(fdQVSS))
|
|
{
|
|
ErrorF("Closing QVSS yielded %d\n", errno);
|
|
return (FALSE);
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
static
|
|
qvssPixelError(index)
|
|
int index;
|
|
{
|
|
ErrorF("Only 0 or 1 are acceptable pixels for device %d\n", index);
|
|
}
|
|
|
|
|
|
Bool
|
|
qvssScreenInit(index, pScreen, argc, argv)
|
|
int index;
|
|
ScreenPtr pScreen;
|
|
int argc; /* these two may NOT be changed */
|
|
char **argv;
|
|
{
|
|
Bool retval, SpecificB, SpecificW;
|
|
ColormapPtr pColormap;
|
|
VisualPtr pVisual;
|
|
int i;
|
|
char *blackValue, *whiteValue;
|
|
|
|
qvInfo = &qvInfostore;
|
|
qvInfo->cursorbits = cursorbitsstore;
|
|
if ((fdQVSS = open("/dev/ttyw7", O_RDWR | O_NDELAY, 0)) < 0)
|
|
{
|
|
ErrorF( "couldn't open console (ttyw7)\n");
|
|
return FALSE;
|
|
}
|
|
i = WSDISPLAYIO_MODE_MAPPED;
|
|
if ((ioctl(fdQVSS, WSDISPLAYIO_SMODE, &i)) < 0) {
|
|
ErrorF("Couldn't set console graphics mode\n");
|
|
return FALSE;
|
|
}
|
|
smaddr = mmap(0, 128*1024, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
|
|
fdQVSS, 0);
|
|
if (smaddr < 0) {
|
|
ErrorF("Couldn't mmap graphics\n");
|
|
return FALSE;
|
|
}
|
|
#if 0
|
|
/* force an init to get the scrollmap right */
|
|
ioctl(fdQVSS, QIOCINIT, (char *)NULL);
|
|
if (ioctl(fdQVSS, QIOCADDR, (char *)&qvInfo) < 0)
|
|
{
|
|
ErrorF( "error getting address of QVSS \n");
|
|
close(fdQVSS);
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
#ifdef QIOVIDEOON
|
|
(void) ioctl(fdQVSS, QIOVIDEOON, (char *)NULL);
|
|
#endif
|
|
#ifdef ULTRIX3_0
|
|
/*
|
|
* test to see if we're using the sm driver instead
|
|
*/
|
|
isSMdevice = FALSE;
|
|
if ((char *) 0 <= qvInfo->bitmap && qvInfo->bitmap <= (char *) 0x7fffffff) {
|
|
smInfo = (struct sm_info *) qvInfo;
|
|
isSMdevice = TRUE;
|
|
}
|
|
#endif
|
|
|
|
#ifdef ULTRIX3_0
|
|
if (isSMdevice) {
|
|
mouse = (vsCursor *) &smInfo->mouse;
|
|
mbox = (vsBox *) &smInfo->mbox;
|
|
queue = (vsEventQueue *) &smInfo->qe;
|
|
} else
|
|
#endif
|
|
{
|
|
mouse = (vsCursor *) &qvInfo->mouse;
|
|
mbox = (vsBox *) &qvInfo->mbox;
|
|
mbox->bottom = 0; /* trash pointer non-interest box 'cause driver won't */
|
|
#ifdef ULTRIX3_0
|
|
queue = &qvInfo->qe;
|
|
#else
|
|
/*
|
|
the following hack is really pretending a part of one record
|
|
is really a record of another type!
|
|
*/
|
|
queue = (vsEventQueue *) &qvInfo->ibuff;
|
|
#endif
|
|
}
|
|
qLimit = queue->size - 1;
|
|
|
|
blackValue = NULL;
|
|
SpecificB = FALSE;
|
|
whiteValue = NULL;
|
|
SpecificW = FALSE;
|
|
for(i = 1; i < argc; i++)
|
|
{
|
|
if(strncmp(argv[i], "-bp:", 4) == 0 && atoi(argv[i] + 4) == index)
|
|
{
|
|
if(++i < argc)
|
|
{
|
|
blackValue = argv[i];
|
|
SpecificB = TRUE;
|
|
}
|
|
else
|
|
UseMsg();
|
|
}
|
|
if(strncmp(argv[i], "-wp:", 4) == 0 && atoi(argv[i] + 4) == index)
|
|
{
|
|
if(++i < argc)
|
|
{
|
|
whiteValue = argv[i];
|
|
SpecificW = TRUE;
|
|
}
|
|
else
|
|
UseMsg();
|
|
}
|
|
if(strcmp(argv[i], "-bp") == 0 && !SpecificB)
|
|
{
|
|
if(++i < argc)
|
|
{
|
|
blackValue = argv[i];
|
|
}
|
|
else
|
|
UseMsg();
|
|
}
|
|
if(strcmp(argv[i], "-wp") == 0 && !SpecificW)
|
|
{
|
|
if(++i < argc)
|
|
{
|
|
whiteValue = argv[i];
|
|
}
|
|
else
|
|
UseMsg();
|
|
}
|
|
|
|
}
|
|
pScreen->blackPixel = 0;
|
|
pScreen->whitePixel = 1;
|
|
if(blackValue)
|
|
{
|
|
if((i = atoi(blackValue)) == 0 || i == 1)
|
|
pScreen->blackPixel = i;
|
|
else
|
|
qvssPixelError(index);
|
|
}
|
|
if(whiteValue)
|
|
{
|
|
if((i = atoi(whiteValue)) == 0 || i == 1)
|
|
pScreen->whitePixel = i;
|
|
else
|
|
qvssPixelError(index);
|
|
}
|
|
|
|
/*
|
|
* qv screen saver
|
|
*/
|
|
pScreen->SaveScreen = qvssSaveScreen;
|
|
/*
|
|
* qv cursor routines
|
|
*/
|
|
pScreen->RealizeCursor = qvRealizeCursor;
|
|
pScreen->UnrealizeCursor = qvUnrealizeCursor;
|
|
pScreen->DisplayCursor = qvDisplayCursor;
|
|
pScreen->SetCursorPosition = qvSetCursorPosition;
|
|
pScreen->CursorLimits = qvCursorLimits;
|
|
pScreen->PointerNonInterestBox = qvPointerNonInterestBox;
|
|
pScreen->ConstrainCursor = qvConstrainCursor;
|
|
pScreen->RecolorCursor = miRecolorCursor;
|
|
|
|
i = monitorResolution ? monitorResolution : 80;
|
|
|
|
#ifdef ULTRIX3_0
|
|
if (isSMdevice)
|
|
retval = mfbScreenInit(pScreen, smaddr, 1024, 864, i, i, 1024);
|
|
else
|
|
#endif
|
|
retval = mfbScreenInit(pScreen, smaddr, 1024, 864, i, i, 1024);
|
|
if (!retval)
|
|
{
|
|
close(fdQVSS);
|
|
return FALSE;
|
|
}
|
|
/*
|
|
* qvQueryBestSize gives hints for cursors, as well as
|
|
* for pixmaps and tiles, mash the mfb supplied version
|
|
*/
|
|
pScreen->QueryBestSize = qvQueryBestSize;
|
|
/*
|
|
* wrap screen close routine with our own
|
|
*/
|
|
CloseScreen = pScreen->CloseScreen;
|
|
pScreen->CloseScreen = qvssScreenClose;
|
|
/*
|
|
* create and install the default colormap
|
|
*/
|
|
if (!mfbCreateDefColormap (pScreen))
|
|
{
|
|
close (fdQVSS);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
int
|
|
qvssMouseProc(pDev, onoff, argc, argv)
|
|
DevicePtr pDev;
|
|
int onoff, argc;
|
|
char *argv[];
|
|
{
|
|
BYTE map[4];
|
|
|
|
switch (onoff)
|
|
{
|
|
case DEVICE_INIT:
|
|
qvPointer = pDev;
|
|
pDev->devicePrivate = (pointer) &queue;
|
|
map[1] = 1;
|
|
map[2] = 2;
|
|
map[3] = 3;
|
|
InitPointerDeviceStruct(
|
|
qvPointer, map, 3, qvGetMotionEvents, qvChangePointerControl,
|
|
0);
|
|
SetInputCheck(&queue->head, &queue->tail);
|
|
break;
|
|
case DEVICE_ON:
|
|
pDev->on = TRUE;
|
|
hotX = hotY = 0;
|
|
AddEnabledDevice(fdQVSS);
|
|
break;
|
|
case DEVICE_OFF:
|
|
pDev->on = FALSE;
|
|
/* RemoveEnabledDevice(fdQVSS); */
|
|
break;
|
|
case DEVICE_CLOSE:
|
|
break;
|
|
}
|
|
return Success;
|
|
|
|
}
|
|
|
|
#define LK_REPEAT_ON 0xe3
|
|
#define LK_REPEAT_OFF 0xe1
|
|
|
|
int
|
|
SetLKAutoRepeat (onoff)
|
|
Bool onoff;
|
|
{
|
|
extern char *AutoRepeatLKMode();
|
|
extern char *UpDownLKMode();
|
|
|
|
struct qv_kpcmd ioc;
|
|
register char *divsets;
|
|
divsets = onoff ? (char *) AutoRepeatLKMode() : (char *) UpDownLKMode();
|
|
|
|
ioc.nbytes = 0;
|
|
while (ioc.cmd = *divsets++)
|
|
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
|
|
ioc.cmd = ((onoff > 0) ? LK_REPEAT_ON : LK_REPEAT_OFF);
|
|
return(ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc));
|
|
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
int
|
|
qvssKeybdProc(pDev, onoff, argc, argv)
|
|
DevicePtr pDev;
|
|
int onoff, argc;
|
|
char *argv[];
|
|
{
|
|
KeySymsRec keySyms;
|
|
CARD8 modMap[MAP_LENGTH];
|
|
|
|
switch (onoff)
|
|
{
|
|
case DEVICE_INIT:
|
|
qvKeyboard = pDev;
|
|
pDev->devicePrivate = (pointer) & queue;
|
|
if (!GetLK201Mappings( &keySyms, modMap))
|
|
return BadAlloc;
|
|
InitKeyboardDeviceStruct(
|
|
qvKeyboard, &keySyms, modMap, qvBell,
|
|
qvChangeKeyboardControl);
|
|
xfree(keySyms.map);
|
|
/* SetLKAutoRepeat(FALSE); */
|
|
break;
|
|
case DEVICE_ON:
|
|
pDev->on = TRUE;
|
|
AddEnabledDevice(fdQVSS);
|
|
break;
|
|
case DEVICE_OFF:
|
|
pDev->on = FALSE;
|
|
/* RemoveEnabledDevice(fdQVSS); */
|
|
break;
|
|
case DEVICE_CLOSE:
|
|
break;
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
|
|
/*****************
|
|
* ProcessInputEvents:
|
|
* processes all the pending input events
|
|
*****************/
|
|
|
|
extern int screenIsSaved;
|
|
|
|
void
|
|
ProcessInputEvents()
|
|
{
|
|
#define DEVICE_KEYBOARD 2
|
|
register int i;
|
|
register vsEvent * pE;
|
|
xEvent x;
|
|
int nowInCentiSecs, nowInMilliSecs, adjustCentiSecs;
|
|
struct timeval tp;
|
|
int needTime = 1;
|
|
#ifndef NO_EVENT_COMPRESSION
|
|
int j;
|
|
#endif
|
|
|
|
i = queue->head;
|
|
while (i != queue->tail)
|
|
{
|
|
if (screenIsSaved == SCREEN_SAVER_ON)
|
|
SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
|
|
pE = &queue->events[i];
|
|
x.u.keyButtonPointer.rootX = pE->vse_x + hotX;
|
|
x.u.keyButtonPointer.rootY = pE->vse_y + hotY;
|
|
if (sizeof(pE->vse_time) == 4)
|
|
x.u.keyButtonPointer.time = lastEventTime = pE->vse_time;
|
|
else {
|
|
/*
|
|
* The following silly looking code is because the old version of the
|
|
* driver only delivers 16 bits worth of centiseconds. We are supposed
|
|
* to be keeping time in terms of 32 bits of milliseconds.
|
|
*/
|
|
if (needTime)
|
|
{
|
|
needTime = 0;
|
|
gettimeofday(&tp, 0);
|
|
nowInCentiSecs = ((tp.tv_sec * 100) + (tp.tv_usec / 10000)) & 0xFFFF;
|
|
/* same as driver */
|
|
nowInMilliSecs = (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
|
|
/* beware overflow */
|
|
}
|
|
if ((adjustCentiSecs = nowInCentiSecs - pE->vse_time) < -20000)
|
|
adjustCentiSecs += 0x10000;
|
|
else
|
|
if (adjustCentiSecs > 20000)
|
|
adjustCentiSecs -= 0x10000;
|
|
x.u.keyButtonPointer.time = lastEventTime =
|
|
nowInMilliSecs - adjustCentiSecs * 10;
|
|
}
|
|
|
|
#ifdef ULTRIX3_0
|
|
if (isSMdevice) {
|
|
if ((pE->type != MOTION_TYPE) &&
|
|
(pE->device == KEYBOARD_DEVICE))
|
|
{
|
|
x.u.u.detail = pE->key;
|
|
switch (pE->type)
|
|
{
|
|
case BUTTON_DOWN_TYPE:
|
|
x.u.u.type = KeyPress;
|
|
(*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
|
|
break;
|
|
case BUTTON_UP_TYPE:
|
|
x.u.u.type = KeyRelease;
|
|
(*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
|
|
break;
|
|
case BUTTON_RAW_TYPE:
|
|
ProcessLK201Input(&x, qvKeyboard);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pE->type != MOTION_TYPE)
|
|
{
|
|
if (pE->type == BUTTON_DOWN_TYPE)
|
|
x.u.u.type = ButtonPress;
|
|
else
|
|
x.u.u.type = ButtonRelease;
|
|
/* mouse buttons numbered from one */
|
|
x.u.u.detail = pE->key;
|
|
}
|
|
else {
|
|
/* tell the server that the mouse moved */
|
|
x.u.u.type = MotionNotify;
|
|
}
|
|
(*qvPointer->processInputProc)(&x, qvPointer, 1);
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if ((pE->vse_type == VSE_BUTTON) &&
|
|
(pE->vse_device == DEVICE_KEYBOARD))
|
|
{ /* better be a button */
|
|
x.u.u.detail = pE->vse_key;
|
|
switch (pE->vse_direction)
|
|
{
|
|
case VSE_KBTDOWN:
|
|
x.u.u.type = KeyPress;
|
|
(*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
|
|
break;
|
|
case VSE_KBTUP:
|
|
x.u.u.type = KeyRelease;
|
|
(*qvKeyboard->processInputProc)(&x, qvKeyboard, 1);
|
|
break;
|
|
default: /* hopefully BUTTON_RAW_TYPE */
|
|
ProcessLK201Input(&x, qvKeyboard);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pE->vse_type == VSE_BUTTON)
|
|
{
|
|
if (pE->vse_direction == VSE_KBTDOWN)
|
|
x.u.u.type = ButtonPress;
|
|
else
|
|
x.u.u.type = ButtonRelease;
|
|
/* mouse buttons numbered from one */
|
|
x.u.u.detail = pE->vse_key + 1;
|
|
}
|
|
else {
|
|
#ifndef NO_EVENT_COMPRESSION
|
|
j = (i == qLimit) ? 0 : i + 1;
|
|
/*
|
|
* to get here we knew that
|
|
*
|
|
* (vse_type != VSE_BUTTON ||
|
|
* vse_device != DEVICE_KEYBOARD) &&
|
|
* (vse_type != VSE_BUTTON)
|
|
*
|
|
* which means that for the next event to be a mouse
|
|
* motion, it must satisfy vse_type != VSE_BUTTON
|
|
*
|
|
* XXX -- We should implement motion history since we are
|
|
* throwing device events away....
|
|
*/
|
|
if (j != queue->tail &&
|
|
queue->events[j].vse_type != VSE_BUTTON)
|
|
goto next; /* sometimes the dragon wins */
|
|
|
|
#endif
|
|
/* tell the server that the mouse moved */
|
|
x.u.u.type = MotionNotify;
|
|
}
|
|
(*qvPointer->processInputProc)(&x, qvPointer, 1);
|
|
}
|
|
}
|
|
|
|
next:
|
|
if (i == qLimit)
|
|
i = queue->head = 0;
|
|
else
|
|
i = ++queue->head;
|
|
}
|
|
#undef DEVICE_KEYBOARD
|
|
}
|
|
|
|
TimeSinceLastInputEvent()
|
|
{
|
|
if (lastEventTime == 0)
|
|
lastEventTime = GetTimeInMillis();
|
|
return GetTimeInMillis() - lastEventTime;
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
qvBell(loud, pDevice)
|
|
int loud;
|
|
DevicePtr pDevice;
|
|
{
|
|
#define LK_ENABLE_BELL 0x23 /* enable bell / set volume */
|
|
struct qv_kpcmd ioc;
|
|
|
|
/* the lk201 volume is between 7 (quiet but audible) and 0 (loud) */
|
|
loud = 7 - ((loud / 14) & 7);
|
|
ioc.nbytes = 1;
|
|
ioc.cmd = LK_ENABLE_BELL;
|
|
ioc.par[0] = loud;
|
|
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
|
|
|
|
ioc.nbytes = 0;
|
|
ioc.cmd = LK_RING_BELL;
|
|
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
|
|
}
|
|
|
|
static void
|
|
ChangeLED(led, on)
|
|
int led;
|
|
Bool on;
|
|
{
|
|
struct qv_kpcmd ioc;
|
|
|
|
switch (led) {
|
|
case 1:
|
|
ioc.par[0] = LED_1;
|
|
break;
|
|
case 2:
|
|
ioc.par[0] = LED_2;
|
|
break;
|
|
case 3:
|
|
/* the keyboard's LED_3 is the Lock LED, which the server owns.
|
|
So the user's LED #3 maps to the keyboard's LED_4. */
|
|
ioc.par[0] = LED_4;
|
|
break;
|
|
default:
|
|
return; /* out-of-range LED value */
|
|
}
|
|
|
|
ioc.cmd = on ? LK_LED_ENABLE : LK_LED_DISABLE;
|
|
ioc.par[1] = 0;
|
|
ioc.nbytes = 1;
|
|
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
|
|
}
|
|
|
|
SetLockLED (on)
|
|
Bool on;
|
|
{
|
|
struct qv_kpcmd ioc;
|
|
ioc.cmd = on ? LK_LED_ENABLE : LK_LED_DISABLE;
|
|
ioc.par[0] = LED_3;
|
|
ioc.par[1] = 0;
|
|
ioc.nbytes = 1;
|
|
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
qvChangeKeyboardControl(pDevice, ctrl)
|
|
DevicePtr pDevice;
|
|
KeybdCtrl *ctrl;
|
|
{
|
|
#define LK_ENABLE_CLICK 0x1b /* enable keyclick / set volume */
|
|
#define LK_DISABLE_CLICK 0x99 /* disable keyclick entirely */
|
|
#define LK_ENABLE_BELL 0x23 /* enable bell / set volume */
|
|
|
|
struct qv_kpcmd ioc;
|
|
int i;
|
|
|
|
if (ctrl->click == 0) /* turn click off */
|
|
{
|
|
ioc.nbytes = 0;
|
|
ioc.cmd = LK_DISABLE_CLICK;
|
|
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
|
|
}
|
|
else
|
|
{
|
|
int volume;
|
|
|
|
volume = 7 - ((ctrl->click / 14) & 7);
|
|
ioc.nbytes = 1;
|
|
ioc.cmd = LK_ENABLE_CLICK;
|
|
ioc.par[0] = volume;
|
|
ioctl(fdQVSS, QIOCKPCMD, (char *)&ioc);
|
|
}
|
|
|
|
/* ctrl->bell: the DIX layer handles the base volume for the bell */
|
|
|
|
/* ctrl->bell_pitch: as far as I can tell, you can't set this on lk201 */
|
|
|
|
/* ctrl->bell_duration: as far as I can tell, you can't set this */
|
|
|
|
/* LEDs */
|
|
for (i=1; i<=MAX_LED; i++)
|
|
ChangeLED(i, (ctrl->leds & (1 << (i-1))) ? TRUE : FALSE);
|
|
|
|
/* ctrl->autoRepeat: I'm turning it all on or all off. */
|
|
|
|
SetLKAutoRepeat(ctrl->autoRepeat);
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
qvChangePointerControl(pDevice, ctrl)
|
|
DevicePtr pDevice;
|
|
PtrCtrl *ctrl;
|
|
{
|
|
#ifdef ULTRIX3_0
|
|
if (isSMdevice)
|
|
{
|
|
smInfo->mthreshold = ctrl->threshold;
|
|
if (!(smInfo->mscale = ctrl->num / ctrl->den))
|
|
smInfo->mscale = 1; /* watch for den > num */
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
qvInfo->mthreshold = ctrl->threshold;
|
|
if (!(qvInfo->mscale = ctrl->num / ctrl->den))
|
|
qvInfo->mscale = 1; /* watch for den > num */
|
|
}
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static int
|
|
qvGetMotionEvents(buff, start, stop, pScr)
|
|
CARD32 start, stop;
|
|
xTimecoord *buff;
|
|
ScreenPtr pScr;
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static Bool
|
|
qvSetCursorPosition( pScr, newx, newy, generateEvent)
|
|
ScreenPtr pScr;
|
|
int newx;
|
|
int newy;
|
|
Bool generateEvent;
|
|
{
|
|
vsCursor cursor;
|
|
xEvent motion;
|
|
|
|
cursor.x = newx - hotX;
|
|
cursor.y = newy - hotY;
|
|
#if 0
|
|
if ( ioctl(fdQVSS, QIOCSMSTATE, (char *)&cursor) < 0)
|
|
{
|
|
ErrorF( "error warping cursor\n");
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
if (generateEvent)
|
|
{
|
|
if (queue->head != queue->tail)
|
|
ProcessInputEvents();
|
|
motion.u.keyButtonPointer.rootX = newx;
|
|
motion.u.keyButtonPointer.rootY = newy;
|
|
motion.u.keyButtonPointer.time = lastEventTime;
|
|
motion.u.u.type = MotionNotify;
|
|
(*qvPointer->processInputProc) (&motion, qvPointer, 1);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
qvDisplayCursor( pScr, pCurs)
|
|
ScreenPtr pScr;
|
|
CursorPtr pCurs;
|
|
{
|
|
char buf[200];
|
|
int i, x, y;
|
|
|
|
/*
|
|
* load the cursor
|
|
*/
|
|
if ((hotX != (int)pCurs->bits->xhot) || (hotY != (int)pCurs->bits->yhot))
|
|
{
|
|
x = mouse->x + hotX;
|
|
y = mouse->y + hotY;
|
|
hotX = pCurs->bits->xhot;
|
|
hotY = pCurs->bits->yhot;
|
|
qvSetCursorPosition(pScr, x, y, FALSE);
|
|
qvConstrainCursor(pScr, &constraintBox);
|
|
}
|
|
#ifdef ULTRIX3_0
|
|
if (isSMdevice)
|
|
{
|
|
if ( ioctl (fdQVSS, QIOWCURSOR, (char *)((short *)pCurs->devPriv[ pScr->myNum]))
|
|
< 0)
|
|
{
|
|
ErrorF( "error writing cursor\n");
|
|
return FALSE;
|
|
}
|
|
#ifdef notdef
|
|
for ( i=0; i<16; i++)
|
|
smInfo->cursorbits[i] = ((short *)pCurs->devPriv[ pScr->myNum])[i];
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
for ( i=0; i<16; i++)
|
|
qvInfo->cursorbits[i] = ((short *)pCurs->devPriv[ pScr->myNum])[i];
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
qvPointerNonInterestBox( pScr, pBox)
|
|
ScreenPtr pScr;
|
|
BoxPtr pBox;
|
|
{
|
|
mbox->bottom = pBox->y2;
|
|
mbox->top = pBox->y1;
|
|
mbox->left = pBox->x1;
|
|
mbox->right = pBox->x2;
|
|
}
|
|
|
|
/* note that this driver does not support dealing with the minimums */
|
|
/* ARGSUSED */
|
|
static void
|
|
qvConstrainCursor( pScr, pBox)
|
|
ScreenPtr pScr;
|
|
BoxPtr pBox;
|
|
{
|
|
constraintBox = *pBox;
|
|
#ifdef ULTRIX3_0
|
|
if (isSMdevice && smInfo)
|
|
{
|
|
smInfo->min_cur_x = pBox->x1 - hotX;
|
|
smInfo->min_cur_y = pBox->y1 - hotY;
|
|
smInfo->max_cur_x = pBox->x2 - hotX - 1;
|
|
smInfo->max_cur_y = pBox->y2 - hotY - 1;
|
|
} else
|
|
#endif
|
|
if (qvInfo)
|
|
{
|
|
qvInfo->max_cur_x = pBox->x2 - hotX - 1;
|
|
qvInfo->max_cur_y = pBox->y2 - hotY - 1;
|
|
}
|
|
else
|
|
ErrorF( "qvConstrainCursor: info = %x\n", qvInfo);
|
|
}
|
|
|
|
/*
|
|
* qv cursor top-left corner cannot go to negative coordinates,
|
|
* but sm can.
|
|
*/
|
|
/* ARGSUSED */static void
|
|
qvCursorLimits( pScr, pCurs, pHotBox, pPhysBox)
|
|
ScreenPtr pScr;
|
|
CursorPtr pCurs;
|
|
BoxPtr pHotBox;
|
|
BoxPtr pPhysBox; /* return value */
|
|
{
|
|
#ifdef ULTRIX3_0
|
|
if (isSMdevice)
|
|
{
|
|
pPhysBox->x1 = pHotBox->x1;
|
|
pPhysBox->y1 = pHotBox->y1;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
pPhysBox->x1 = max( pHotBox->x1, (int)pCurs->bits->xhot);
|
|
pPhysBox->y1 = max( pHotBox->y1, (int)pCurs->bits->yhot);
|
|
}
|
|
pPhysBox->x2 = min( pHotBox->x2, 1024);
|
|
pPhysBox->y2 = min( pHotBox->y2, 864);
|
|
}
|
|
|
|
static Bool
|
|
qvRealizeCursor( pScr, pCurs)
|
|
ScreenPtr pScr;
|
|
CursorPtr pCurs; /* a SERVER-DEPENDENT cursor */
|
|
{
|
|
unsigned short red, green, blue;
|
|
int forecolor, backcolor;
|
|
register short *a, *b; /* hardware-defined */
|
|
register int * mask; /* server-defined */
|
|
register int * src; /* server-defined */
|
|
register int i;
|
|
int cursorBytes = 32*sizeof(short);
|
|
int lastRow = ((pCurs->bits->height < 16) ? pCurs->bits->height : 16);
|
|
register unsigned short widthmask = (1<<pCurs->bits->width)-1;
|
|
/* used to mask off beyond the edge of the
|
|
real mask and source bits
|
|
*/
|
|
|
|
red = pCurs->foreRed;
|
|
green = pCurs->foreGreen;
|
|
blue = pCurs->foreBlue;
|
|
mfbResolveColor(&red, &green, &blue, (VisualPtr)NULL);
|
|
forecolor = red;
|
|
red = pCurs->backRed;
|
|
green = pCurs->backGreen;
|
|
blue = pCurs->backBlue;
|
|
mfbResolveColor(&red, &green, &blue, (VisualPtr)NULL);
|
|
backcolor = red;
|
|
pCurs->devPriv[ pScr->myNum] = (pointer)xalloc(cursorBytes);
|
|
if (!pCurs->devPriv[ pScr->myNum])
|
|
return FALSE;
|
|
bzero((char *)pCurs->devPriv[ pScr->myNum], cursorBytes);
|
|
|
|
/*
|
|
* munge the SERVER-DEPENDENT, device-independent cursor bits into
|
|
* what the device wants, which is 32 contiguous shorts.
|
|
*
|
|
* cursor hardware has "A" and "B" bitmaps
|
|
* logic table is:
|
|
*
|
|
* A B cursor
|
|
*
|
|
* 0 0 transparent
|
|
* 1 0 xor (not used)
|
|
* 0 1 black
|
|
* 1 1 white
|
|
*/
|
|
|
|
/*
|
|
* "a" bitmap = image
|
|
*
|
|
* "b" bitmap can be same as "mask", providing "a" is never on when
|
|
* "b" is off.
|
|
*/
|
|
for ( i=0,
|
|
a = (short *)pCurs->devPriv[pScr->myNum],
|
|
b = ((short *)pCurs->devPriv[pScr->myNum]) + 16,
|
|
/* XXX assumes DIX pixmap pad is size of int,
|
|
and cursor is < 32 bits wide
|
|
*/
|
|
src = (int *)pCurs->bits->source,
|
|
mask = (int *)pCurs->bits->mask;
|
|
|
|
i < lastRow;
|
|
|
|
i++, a++, b++, src++, mask++)
|
|
{
|
|
#ifdef ULTRIX3_0
|
|
if (isSMdevice)
|
|
*a = (*src & forecolor) | ((*mask & ~*src) & backcolor);
|
|
else
|
|
#endif
|
|
*a = ((*src & backcolor) | (~*src & forecolor)) & *mask;
|
|
*b = *mask;
|
|
*a &= widthmask;
|
|
*b &= widthmask;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
qvUnrealizeCursor( pScr, pCurs)
|
|
ScreenPtr pScr;
|
|
CursorPtr pCurs;
|
|
{
|
|
xfree(pCurs->devPriv[ pScr->myNum]);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
qvQueryBestSize(class, pwidth, pheight)
|
|
int class;
|
|
short *pwidth;
|
|
short *pheight;
|
|
{
|
|
unsigned width, test;
|
|
|
|
switch(class)
|
|
{
|
|
case CursorShape:
|
|
*pwidth = 16;
|
|
*pheight = 16;
|
|
break;
|
|
case TileShape:
|
|
case StippleShape:
|
|
width = *pwidth;
|
|
if (width != 0) {
|
|
/* Return the closest power of two not less than width */
|
|
test = 0x80000000;
|
|
/* Find the highest 1 bit in the width given */
|
|
while(!(test & width))
|
|
test >>= 1;
|
|
/* If their number is greater than that, bump up to the next
|
|
* power of two */
|
|
if((test - 1) & width)
|
|
test <<= 1;
|
|
*pwidth = test;
|
|
}
|
|
/* We don't care what height they use */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
void
|
|
qvResolveColor(pred, pgreen, pblue, pVisual)
|
|
unsigned short *pred, *pgreen, *pblue;
|
|
VisualPtr pVisual;
|
|
{
|
|
/* Gets intensity from RGB. If intensity is >= half, pick white, else
|
|
* pick black. This may well be more trouble than it's worth. */
|
|
*pred = *pgreen = *pblue =
|
|
(((30L * *pred +
|
|
59L * *pgreen +
|
|
11L * *pblue) >> 8) >= (((1<<8)-1)*50)) ? ~0 : 0;
|
|
}
|
|
|
|
Bool
|
|
qvCreateColormap(pmap)
|
|
ColormapPtr pmap;
|
|
{
|
|
unsigned short red, green, blue;
|
|
unsigned long pix;
|
|
|
|
/* this is a monochrome colormap, it only has two entries, just fill
|
|
* them in by hand. If it were a more complex static map, it would be
|
|
* worth writing a for loop or three to initialize it */
|
|
pix = 0;
|
|
red = green = blue = 0;
|
|
if (AllocColor(pmap, &red, &green, &blue, &pix, 0) != Success)
|
|
return FALSE;
|
|
pix = 0;
|
|
red = green = blue = ~0;
|
|
if (AllocColor(pmap, &red, &green, &blue, &pix, 0) != Success)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
void
|
|
qvDestroyColormap(pmap)
|
|
ColormapPtr pmap;
|
|
{
|
|
}
|
|
|
|
/*
|
|
* DDX - specific abort routine. Called by AbortServer().
|
|
*/
|
|
void
|
|
AbortDDX()
|
|
{
|
|
}
|
|
|
|
/* Called by GiveUp(). */
|
|
void
|
|
ddxGiveUp()
|
|
{
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
int
|
|
ddxProcessArgument (argc, argv, i)
|
|
int argc;
|
|
char *argv[];
|
|
int i;
|
|
{
|
|
if(!strncmp(argv[i], "-bp:", 4) ||
|
|
!strncmp(argv[i], "-wp:", 4) ||
|
|
!strcmp(argv[i], "-bp") ||
|
|
!strcmp(argv[i], "-wp"))
|
|
return 2;
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
ddxUseMsg()
|
|
{
|
|
ErrorF("-bp<:screen> color BlackPixel for screen\n");
|
|
ErrorF("-wp<:screen> color WhitePixel for screen\n");
|
|
}
|