#define NEED_EVENTS
#include <X11/X.h>
#include <X11/Xmd.h>
#include <X11/Xproto.h>
#include "misc.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "inputstr.h"
#include "mi.h"
#include "scrnintstr.h"
#include "mipointer.h"
#include "darwin.h"
#include "darwinKeyboard.h"
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <IOKit/hidsystem/IOLLEvent.h>
#define SCROLLWHEELUPFAKE 4
#define SCROLLWHEELDOWNFAKE 5
#define QUEUE_SIZE 256
typedef struct _Event {
xEvent event;
ScreenPtr pScreen;
} EventRec, *EventPtr;
typedef struct _EventQueue {
HWEventQueueType head, tail;
CARD32 lastEventTime;
Bool lastMotion;
EventRec events[QUEUE_SIZE];
DevicePtr pKbd, pPtr;
ScreenPtr pEnqueueScreen;
ScreenPtr pDequeueScreen;
} EventQueueRec, *EventQueuePtr;
static EventQueueRec darwinEventQueue;
static void DarwinPressModifierMask(
xEvent *xe, int mask) {
int key = DarwinModifierNXMaskToNXKey(mask);
if (key != -1) {
int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
if (keycode != 0) {
xe->u.u.detail = keycode + MIN_KEYCODE;
(*darwinEventQueue.pKbd->processInputProc)(xe,
(DeviceIntPtr)darwinEventQueue.pKbd, 1);
}
}
}
#ifdef NX_DEVICELCTLKEYMASK
#define CONTROL_MASK(flags) (flags & (NX_DEVICELCTLKEYMASK|NX_DEVICERCTLKEYMASK))
#else
#define CONTROL_MASK(flags) (NX_CONTROLMASK)
#endif
#ifdef NX_DEVICELSHIFTKEYMASK
#define SHIFT_MASK(flags) (flags & (NX_DEVICELSHIFTKEYMASK|NX_DEVICERSHIFTKEYMASK))
#else
#define SHIFT_MASK(flags) (NX_SHIFTMASK)
#endif
#ifdef NX_DEVICELCMDKEYMASK
#define COMMAND_MASK(flags) (flags & (NX_DEVICELCMDKEYMASK|NX_DEVICERCMDKEYMASK))
#else
#define COMMAND_MASK(flags) (NX_COMMANDMASK)
#endif
#ifdef NX_DEVICELALTKEYMASK
#define ALTERNATE_MASK(flags) (flags & (NX_DEVICELALTKEYMASK|NX_DEVICERALTKEYMASK))
#else
#define ALTERNATE_MASK(flags) (NX_ALTERNATEMASK)
#endif
static void DarwinUpdateModifiers(
xEvent *xe, int pressed, int flags ) {
xe->u.u.type = pressed;
if (flags & NX_COMMANDMASK) DarwinPressModifierMask(xe, COMMAND_MASK(flags));
if (flags & NX_CONTROLMASK) DarwinPressModifierMask(xe, CONTROL_MASK(flags));
if (flags & NX_ALTERNATEMASK) DarwinPressModifierMask(xe, ALTERNATE_MASK(flags));
if (flags & NX_SHIFTMASK) DarwinPressModifierMask(xe, SHIFT_MASK(flags));
if (flags & NX_SECONDARYFNMASK) DarwinPressModifierMask(xe, NX_SECONDARYFNMASK);
if (flags & NX_ALPHASHIFTMASK) {
xe->u.u.type = KeyPress;
DarwinPressModifierMask(xe, NX_ALPHASHIFTMASK);
xe->u.u.type = KeyRelease;
DarwinPressModifierMask(xe, NX_ALPHASHIFTMASK);
}
}
static void DarwinSimulateMouseClick(
xEvent *xe, int whichButton, int modifierMask) {
DarwinUpdateModifiers(xe, KeyRelease, modifierMask);
xe->u.u.type = ButtonPress;
xe->u.u.detail = whichButton;
(*darwinEventQueue.pPtr->processInputProc)
(xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
}
Bool
DarwinEQInit(
DevicePtr pKbd,
DevicePtr pPtr)
{
darwinEventQueue.head = darwinEventQueue.tail = 0;
darwinEventQueue.lastEventTime = GetTimeInMillis ();
darwinEventQueue.pKbd = pKbd;
darwinEventQueue.pPtr = pPtr;
darwinEventQueue.pEnqueueScreen = screenInfo.screens[0];
darwinEventQueue.pDequeueScreen = darwinEventQueue.pEnqueueScreen;
SetInputCheck (&darwinEventQueue.head, &darwinEventQueue.tail);
return TRUE;
}
void
DarwinEQEnqueue(
const xEvent *e)
{
HWEventQueueType oldtail, newtail;
char byte = 0;
oldtail = darwinEventQueue.tail;
newtail = oldtail + 1;
if (newtail == QUEUE_SIZE)
newtail = 0;
if (newtail == darwinEventQueue.head)
return;
darwinEventQueue.events[oldtail].event = *e;
if (e->u.keyButtonPointer.time < darwinEventQueue.lastEventTime &&
darwinEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
{
darwinEventQueue.events[oldtail].event.u.keyButtonPointer.time =
darwinEventQueue.lastEventTime;
}
darwinEventQueue.events[oldtail].pScreen = darwinEventQueue.pEnqueueScreen;
darwinEventQueue.tail = newtail;
write(darwinEventWriteFD, &byte, 1);
}
void
DarwinEQPointerPost(
xEvent *e)
{
(*darwinEventQueue.pPtr->processInputProc)
(e, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
}
void
DarwinEQSwitchScreen(
ScreenPtr pScreen,
Bool fromDIX)
{
darwinEventQueue.pEnqueueScreen = pScreen;
if (fromDIX)
darwinEventQueue.pDequeueScreen = pScreen;
}
void ProcessInputEvents(void)
{
EventRec *e;
int x, y;
xEvent xe;
static int old_flags = 0; static int darwinFakeMouseButtonDown = 0;
static int darwinFakeMouseButtonMask = 0;
x = sizeof(xe);
while (x == sizeof(xe)) {
x = read(darwinEventReadFD, &xe, sizeof(xe));
}
while (darwinEventQueue.head != darwinEventQueue.tail)
{
if (screenIsSaved == SCREEN_SAVER_ON)
SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset);
e = &darwinEventQueue.events[darwinEventQueue.head];
xe = e->event;
xe.u.keyButtonPointer.rootX -= darwinMainScreenX +
dixScreenOrigins[miPointerCurrentScreen()->myNum].x;
xe.u.keyButtonPointer.rootY -= darwinMainScreenY +
dixScreenOrigins[miPointerCurrentScreen()->myNum].y;
if (e->pScreen != darwinEventQueue.pDequeueScreen)
{
darwinEventQueue.pDequeueScreen = e->pScreen;
x = xe.u.keyButtonPointer.rootX;
y = xe.u.keyButtonPointer.rootY;
if (darwinEventQueue.head == QUEUE_SIZE - 1)
darwinEventQueue.head = 0;
else
++darwinEventQueue.head;
NewCurrentScreen (darwinEventQueue.pDequeueScreen, x, y);
}
else
{
if (darwinEventQueue.head == QUEUE_SIZE - 1)
darwinEventQueue.head = 0;
else
++darwinEventQueue.head;
switch (xe.u.u.type)
{
case KeyPress:
if (old_flags == 0
&& darwinSyncKeymap && darwinKeymapFile == NULL)
{
static unsigned int last_seed;
unsigned int this_seed;
this_seed = DarwinModeSystemKeymapSeed();
if (this_seed != last_seed)
{
last_seed = this_seed;
DarwinKeyboardReload(darwinKeyboard);
}
}
case KeyRelease:
xe.u.u.detail += MIN_KEYCODE;
(*darwinEventQueue.pKbd->processInputProc)
(&xe, (DeviceIntPtr)darwinEventQueue.pKbd, 1);
break;
case ButtonPress:
miPointerAbsoluteCursor(xe.u.keyButtonPointer.rootX,
xe.u.keyButtonPointer.rootY,
xe.u.keyButtonPointer.time);
if (darwinFakeButtons && xe.u.u.detail == 1) {
if ((old_flags & darwinFakeMouse2Mask) ==
darwinFakeMouse2Mask)
{
DarwinSimulateMouseClick(&xe, 2, darwinFakeMouse2Mask);
darwinFakeMouseButtonDown = 2;
darwinFakeMouseButtonMask = darwinFakeMouse2Mask;
break;
}
else if ((old_flags & darwinFakeMouse3Mask) ==
darwinFakeMouse3Mask)
{
DarwinSimulateMouseClick(&xe, 3, darwinFakeMouse3Mask);
darwinFakeMouseButtonDown = 3;
darwinFakeMouseButtonMask = darwinFakeMouse3Mask;
break;
}
}
(*darwinEventQueue.pPtr->processInputProc)
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
break;
case ButtonRelease:
miPointerAbsoluteCursor(xe.u.keyButtonPointer.rootX,
xe.u.keyButtonPointer.rootY,
xe.u.keyButtonPointer.time);
if (darwinFakeButtons && xe.u.u.detail == 1 &&
darwinFakeMouseButtonDown)
{
xe.u.u.detail = darwinFakeMouseButtonDown;
darwinFakeMouseButtonDown = 0;
(*darwinEventQueue.pPtr->processInputProc)
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
DarwinUpdateModifiers(&xe, KeyPress,
darwinFakeMouseButtonMask & old_flags);
darwinFakeMouseButtonMask = 0;
} else {
(*darwinEventQueue.pPtr->processInputProc)
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
}
break;
case MotionNotify:
miPointerAbsoluteCursor(xe.u.keyButtonPointer.rootX,
xe.u.keyButtonPointer.rootY,
xe.u.keyButtonPointer.time);
break;
case kXDarwinUpdateModifiers:
{
int flags = xe.u.clientMessage.u.l.longs0;
DarwinUpdateModifiers(&xe, KeyRelease,
old_flags & ~flags);
DarwinUpdateModifiers(&xe, KeyPress,
~old_flags & flags);
old_flags = flags;
break;
}
case kXDarwinUpdateButtons:
{
long hwDelta = xe.u.clientMessage.u.l.longs0;
long hwButtons = xe.u.clientMessage.u.l.longs1;
int i;
for (i = 1; i < 5; i++) {
if (hwDelta & (1 << i)) {
if (i == 1) {
xe.u.u.detail = 3;
} else if (i == 2) {
xe.u.u.detail = 2;
} else {
xe.u.u.detail = i + 1;
}
if (hwButtons & (1 << i)) {
xe.u.u.type = ButtonPress;
} else {
xe.u.u.type = ButtonRelease;
}
(*darwinEventQueue.pPtr->processInputProc)
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
}
}
break;
}
case kXDarwinScrollWheel:
{
short count = xe.u.clientMessage.u.s.shorts0;
if (count > 0) {
xe.u.u.detail = SCROLLWHEELUPFAKE;
} else {
xe.u.u.detail = SCROLLWHEELDOWNFAKE;
count = -count;
}
for (; count; --count) {
xe.u.u.type = ButtonPress;
(*darwinEventQueue.pPtr->processInputProc)
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
xe.u.u.type = ButtonRelease;
(*darwinEventQueue.pPtr->processInputProc)
(&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
}
break;
}
default:
DarwinModeProcessEvent(&xe);
}
}
}
miPointerUpdate();
}