447 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			447 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
Darwin event queue and event handling
 | 
						|
 | 
						|
Copyright 2007 Apple Inc.
 | 
						|
Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
 | 
						|
Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
 | 
						|
 | 
						|
This file is based on mieq.c by Keith Packard,
 | 
						|
which contains the following copyright:
 | 
						|
Copyright 1990, 1998  The Open Group
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | 
						|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | 
						|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of The Open Group shall not be
 | 
						|
used in advertising or otherwise to promote the sale, use or other dealings
 | 
						|
in this Software without prior written authorization from The Open Group.
 | 
						|
 */
 | 
						|
 | 
						|
#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>
 | 
						|
 | 
						|
/* Fake button press/release for scroll wheel move. */
 | 
						|
#define SCROLLWHEELUPFAKE   4
 | 
						|
#define SCROLLWHEELDOWNFAKE 5
 | 
						|
 | 
						|
#define QUEUE_SIZE 256
 | 
						|
 | 
						|
typedef struct _Event {
 | 
						|
    xEvent      event;
 | 
						|
    ScreenPtr   pScreen;
 | 
						|
} EventRec, *EventPtr;
 | 
						|
 | 
						|
int input_check_zero, input_check_flag;
 | 
						|
 | 
						|
static int old_flags = 0;  // last known modifier state
 | 
						|
 | 
						|
typedef struct _EventQueue {
 | 
						|
    HWEventQueueType    head, tail; /* long for SetInputCheck */
 | 
						|
    CARD32      lastEventTime;      /* to avoid time running backwards */
 | 
						|
    Bool        lastMotion;
 | 
						|
    EventRec    events[QUEUE_SIZE]; /* static allocation for signals */
 | 
						|
    DevicePtr   pKbd, pPtr;         /* device pointer, to get funcs */
 | 
						|
    ScreenPtr   pEnqueueScreen;     /* screen events are being delivered to */
 | 
						|
    ScreenPtr   pDequeueScreen;     /* screen events are being dispatched to */
 | 
						|
} EventQueueRec, *EventQueuePtr;
 | 
						|
 | 
						|
static EventQueueRec darwinEventQueue;
 | 
						|
xEvent *darwinEvents;
 | 
						|
 | 
						|
/*
 | 
						|
 * DarwinPressModifierMask
 | 
						|
 *  Press or release the given modifier key, specified by its mask.
 | 
						|
 */
 | 
						|
static void DarwinPressModifierMask(
 | 
						|
    int pressed,				    
 | 
						|
    int mask)       // one of NX_*MASK constants
 | 
						|
{
 | 
						|
    int key = DarwinModifierNXMaskToNXKey(mask);
 | 
						|
 | 
						|
    if (key != -1) {
 | 
						|
        int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
 | 
						|
        if (keycode != 0)
 | 
						|
	  DarwinSendKeyboardEvents(pressed, keycode);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#ifdef NX_DEVICELCTLKEYMASK
 | 
						|
#define CONTROL_MASK(flags) (flags & (NX_DEVICELCTLKEYMASK|NX_DEVICERCTLKEYMASK))
 | 
						|
#else
 | 
						|
#define CONTROL_MASK(flags) (NX_CONTROLMASK)
 | 
						|
#endif /* NX_DEVICELCTLKEYMASK */
 | 
						|
 | 
						|
#ifdef NX_DEVICELSHIFTKEYMASK
 | 
						|
#define SHIFT_MASK(flags) (flags & (NX_DEVICELSHIFTKEYMASK|NX_DEVICERSHIFTKEYMASK))
 | 
						|
#else
 | 
						|
#define SHIFT_MASK(flags) (NX_SHIFTMASK)
 | 
						|
#endif /* NX_DEVICELSHIFTKEYMASK */
 | 
						|
 | 
						|
#ifdef NX_DEVICELCMDKEYMASK
 | 
						|
#define COMMAND_MASK(flags) (flags & (NX_DEVICELCMDKEYMASK|NX_DEVICERCMDKEYMASK))
 | 
						|
#else
 | 
						|
#define COMMAND_MASK(flags) (NX_COMMANDMASK)
 | 
						|
#endif /* NX_DEVICELCMDKEYMASK */
 | 
						|
 | 
						|
#ifdef NX_DEVICELALTKEYMASK
 | 
						|
#define ALTERNATE_MASK(flags) (flags & (NX_DEVICELALTKEYMASK|NX_DEVICERALTKEYMASK))
 | 
						|
#else
 | 
						|
#define ALTERNATE_MASK(flags) (NX_ALTERNATEMASK)
 | 
						|
#endif /* NX_DEVICELALTKEYMASK */
 | 
						|
 | 
						|
/*
 | 
						|
 * DarwinUpdateModifiers
 | 
						|
 *  Send events to update the modifier state.
 | 
						|
 */
 | 
						|
static void DarwinUpdateModifiers(
 | 
						|
    int pressed,        // KeyPress or KeyRelease
 | 
						|
    int flags )         // modifier flags that have changed
 | 
						|
{
 | 
						|
    if (flags & NX_ALPHASHIFTMASK) {
 | 
						|
        DarwinPressModifierMask(pressed, NX_ALPHASHIFTMASK);
 | 
						|
    }
 | 
						|
    if (flags & NX_COMMANDMASK) {
 | 
						|
        DarwinPressModifierMask(pressed, COMMAND_MASK(flags));
 | 
						|
    }
 | 
						|
    if (flags & NX_CONTROLMASK) {
 | 
						|
        DarwinPressModifierMask(pressed, CONTROL_MASK(flags));
 | 
						|
    }
 | 
						|
    if (flags & NX_ALTERNATEMASK) {
 | 
						|
        DarwinPressModifierMask(pressed, ALTERNATE_MASK(flags));
 | 
						|
    }
 | 
						|
    if (flags & NX_SHIFTMASK) {
 | 
						|
        DarwinPressModifierMask(pressed, SHIFT_MASK(flags));
 | 
						|
    }
 | 
						|
    if (flags & NX_SECONDARYFNMASK) {
 | 
						|
        DarwinPressModifierMask(pressed, NX_SECONDARYFNMASK);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * DarwinSimulateMouseClick
 | 
						|
 *  Send a mouse click to X when multiple mouse buttons are simulated
 | 
						|
 *  with modifier-clicks, such as command-click for button 2. The dix
 | 
						|
 *  layer is told that the previously pressed modifier key(s) are
 | 
						|
 *  released, the simulated click event is sent. After the mouse button
 | 
						|
 *  is released, the modifier keys are reverted to their actual state,
 | 
						|
 *  which may or may not be pressed at that point. This is usually
 | 
						|
 *  closest to what the user wants. Ie. the user typically wants to
 | 
						|
 *  simulate a button 2 press instead of Command-button 2.
 | 
						|
 */
 | 
						|
static void DarwinSimulateMouseClick(
 | 
						|
    int pointer_x,
 | 
						|
    int pointer_y,
 | 
						|
    int whichButton,    // mouse button to be pressed
 | 
						|
    int modifierMask)   // modifiers used for the fake click
 | 
						|
{
 | 
						|
    // first fool X into forgetting about the keys
 | 
						|
    DarwinUpdateModifiers(KeyRelease, modifierMask);
 | 
						|
 | 
						|
    // push the mouse button
 | 
						|
    DarwinSendPointerEvents(ButtonPress, whichButton, pointer_x, pointer_y);
 | 
						|
    DarwinSendPointerEvents(ButtonRelease, whichButton, pointer_x, pointer_y);
 | 
						|
 | 
						|
    // restore old modifiers
 | 
						|
    DarwinUpdateModifiers(KeyPress, modifierMask);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Bool DarwinEQInit(DevicePtr pKbd, DevicePtr pPtr) { 
 | 
						|
    darwinEvents = (xEvent *)malloc(sizeof(xEvent) * GetMaximumEventsNum());
 | 
						|
    mieqInit();
 | 
						|
    darwinEventQueue.head = darwinEventQueue.tail = 0;
 | 
						|
    darwinEventQueue.lastEventTime = GetTimeInMillis ();
 | 
						|
    darwinEventQueue.pKbd = pKbd;
 | 
						|
    darwinEventQueue.pPtr = pPtr;
 | 
						|
    darwinEventQueue.pEnqueueScreen = screenInfo.screens[0];
 | 
						|
    darwinEventQueue.pDequeueScreen = darwinEventQueue.pEnqueueScreen;
 | 
						|
    SetInputCheck(&input_check_zero, &input_check_flag);
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * DarwinEQEnqueue
 | 
						|
 *  Must be thread safe with ProcessInputEvents.
 | 
						|
 *    DarwinEQEnqueue    - called from event gathering thread
 | 
						|
 *    ProcessInputEvents - called from X server thread
 | 
						|
 *  DarwinEQEnqueue should never be called from more than one thread.
 | 
						|
 * 
 | 
						|
 * This should be deprecated in favor of miEQEnqueue -- BB
 | 
						|
 */
 | 
						|
void DarwinEQEnqueue(const xEvent *e) {
 | 
						|
    HWEventQueueType oldtail, newtail;
 | 
						|
    char byte = 0;
 | 
						|
 | 
						|
    oldtail = darwinEventQueue.tail;
 | 
						|
 | 
						|
    // mieqEnqueue() collapses successive motion events into one event.
 | 
						|
    // This is difficult to do in a thread-safe way and rarely useful.
 | 
						|
 | 
						|
    newtail = oldtail + 1;
 | 
						|
    if (newtail == QUEUE_SIZE) newtail = 0;
 | 
						|
    /* Toss events which come in late */
 | 
						|
    if (newtail == darwinEventQueue.head) return;
 | 
						|
 | 
						|
    darwinEventQueue.events[oldtail].event = *e;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Make sure that event times don't go backwards - this
 | 
						|
     * is "unnecessary", but very useful
 | 
						|
     */
 | 
						|
    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;
 | 
						|
 | 
						|
    // Update the tail after the event is prepared
 | 
						|
    darwinEventQueue.tail = newtail;
 | 
						|
 | 
						|
    // Signal there is an event ready to handle
 | 
						|
    DarwinPokeEQ();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * DarwinEQPointerPost
 | 
						|
 *  Post a pointer event. Used by the mipointer.c routines.
 | 
						|
 */
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * ProcessInputEvents
 | 
						|
 *  Read and process events from the event queue until it is empty.
 | 
						|
 */
 | 
						|
void ProcessInputEvents(void) {
 | 
						|
    EventRec *e;
 | 
						|
    int     x, y;
 | 
						|
    xEvent  xe;
 | 
						|
    static int  old_flags = 0;  // last known modifier state
 | 
						|
    // button number and modifier mask of currently pressed fake button
 | 
						|
    input_check_flag=0;
 | 
						|
 | 
						|
    //    ErrorF("calling mieqProcessInputEvents\n");
 | 
						|
    mieqProcessInputEvents();
 | 
						|
 | 
						|
    // Empty the signaling pipe
 | 
						|
    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;
 | 
						|
 | 
						|
        // Shift from global screen coordinates to coordinates relative to
 | 
						|
        // the origin of the current screen.
 | 
						|
        xe.u.keyButtonPointer.rootX -= darwinMainScreenX +
 | 
						|
                dixScreenOrigins[miPointerCurrentScreen()->myNum].x;
 | 
						|
        xe.u.keyButtonPointer.rootY -= darwinMainScreenY +
 | 
						|
                dixScreenOrigins[miPointerCurrentScreen()->myNum].y;
 | 
						|
	
 | 
						|
	/*	ErrorF("old rootX = (%d,%d) darwinMainScreen = (%d,%d) dixScreenOrigins[%d]=(%d,%d)\n",
 | 
						|
	       xe.u.keyButtonPointer.rootX, xe.u.keyButtonPointer.rootY,
 | 
						|
	       darwinMainScreenX, darwinMainScreenY,
 | 
						|
	       miPointerCurrentScreen()->myNum,
 | 
						|
	       dixScreenOrigins[miPointerCurrentScreen()->myNum].x,
 | 
						|
	       dixScreenOrigins[miPointerCurrentScreen()->myNum].y); */
 | 
						|
 | 
						|
	//Assumption - screen switching can only occur on motion events
 | 
						|
 | 
						|
        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:
 | 
						|
            case KeyRelease:
 | 
						|
	      ErrorF("Unexpected Keyboard event in DarwinProcessInputEvents\n");
 | 
						|
	      break;
 | 
						|
 | 
						|
            case ButtonPress:
 | 
						|
	      ErrorF("Unexpected ButtonPress event in DarwinProcessInputEvents\n");
 | 
						|
                break;
 | 
						|
 | 
						|
            case ButtonRelease:
 | 
						|
	      ErrorF("Unexpected ButtonRelease event in DarwinProcessInputEvents\n");
 | 
						|
                break;
 | 
						|
 | 
						|
            case MotionNotify:
 | 
						|
	      ErrorF("Unexpected ButtonRelease event in DarwinProcessInputEvents\n");
 | 
						|
                break;
 | 
						|
 | 
						|
            case kXDarwinUpdateModifiers:
 | 
						|
	      ErrorF("Unexpected ButtonRelease event in DarwinProcessInputEvents\n");
 | 
						|
	      break;
 | 
						|
 | 
						|
            case kXDarwinUpdateButtons:
 | 
						|
	      ErrorF("Unexpected XDarwinScrollWheel event in DarwinProcessInputEvents\n");
 | 
						|
	      break;
 | 
						|
 | 
						|
            case kXDarwinScrollWheel: 
 | 
						|
	      ErrorF("Unexpected XDarwinScrollWheel event in DarwinProcessInputEvents\n");
 | 
						|
	      break;
 | 
						|
 | 
						|
            default:
 | 
						|
                // Check for mode specific event
 | 
						|
                DarwinModeProcessEvent(&xe);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    //    miPointerUpdate();
 | 
						|
}
 | 
						|
 | 
						|
/* Sends a null byte down darwinEventWriteFD, which will cause the
 | 
						|
   Dispatch() event loop to check out event queue */
 | 
						|
void DarwinPokeEQ(void) {
 | 
						|
  char nullbyte=0;
 | 
						|
  input_check_flag++;
 | 
						|
  //  <daniels> bushing: oh, i ... er ... christ.
 | 
						|
  write(darwinEventWriteFD, &nullbyte, 1);
 | 
						|
}
 | 
						|
 | 
						|
void DarwinSendPointerEvents(int ev_type, int ev_button, int pointer_x, int pointer_y) {
 | 
						|
  static int darwinFakeMouseButtonDown = 0;
 | 
						|
  static int darwinFakeMouseButtonMask = 0;
 | 
						|
  int i, num_events;
 | 
						|
  int valuators[2] = {pointer_x, pointer_y};
 | 
						|
  if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
 | 
						|
    // Mimic multi-button mouse with modifier-clicks
 | 
						|
    // If both sets of modifiers are pressed,
 | 
						|
    // button 2 is clicked.
 | 
						|
    if ((old_flags & darwinFakeMouse2Mask) == darwinFakeMouse2Mask) {
 | 
						|
      DarwinSimulateMouseClick(pointer_x, pointer_y, 2, darwinFakeMouse2Mask);
 | 
						|
      darwinFakeMouseButtonDown = 2;
 | 
						|
      darwinFakeMouseButtonMask = darwinFakeMouse2Mask;
 | 
						|
    } else if ((old_flags & darwinFakeMouse3Mask) == darwinFakeMouse3Mask) {
 | 
						|
      DarwinSimulateMouseClick(pointer_x, pointer_y, 3, darwinFakeMouse3Mask);
 | 
						|
      darwinFakeMouseButtonDown = 3;
 | 
						|
      darwinFakeMouseButtonMask = darwinFakeMouse3Mask;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (ev_type == ButtonRelease && darwinFakeButtons && darwinFakeMouseButtonDown) {
 | 
						|
    // If last mousedown was a fake click, don't check for
 | 
						|
    // mouse modifiers here. The user may have released the
 | 
						|
    // modifiers before the mouse button.
 | 
						|
    ev_button = darwinFakeMouseButtonDown;
 | 
						|
    darwinFakeMouseButtonDown = 0;
 | 
						|
    // Bring modifiers back up to date
 | 
						|
    DarwinUpdateModifiers(KeyPress, darwinFakeMouseButtonMask & old_flags);
 | 
						|
    darwinFakeMouseButtonMask = 0;
 | 
						|
  } 
 | 
						|
 | 
						|
  num_events = GetPointerEvents(darwinEvents, darwinPointer, ev_type, ev_button, 
 | 
						|
				POINTER_ABSOLUTE, 0, 2, valuators);
 | 
						|
      
 | 
						|
  for(i=0; i<num_events; i++) mieqEnqueue (darwinPointer,&darwinEvents[i]);
 | 
						|
  DarwinPokeEQ();
 | 
						|
}
 | 
						|
 | 
						|
void DarwinSendKeyboardEvents(int ev_type, int keycode) {
 | 
						|
  int i, num_events;
 | 
						|
  if (old_flags == 0 && darwinSyncKeymap && darwinKeymapFile == NULL) {
 | 
						|
    /* See if keymap has changed. */
 | 
						|
 | 
						|
    static unsigned int last_seed;
 | 
						|
    unsigned int this_seed;
 | 
						|
 | 
						|
    this_seed = DarwinModeSystemKeymapSeed();
 | 
						|
    if (this_seed != last_seed) {
 | 
						|
      last_seed = this_seed;
 | 
						|
      DarwinKeyboardReload(darwinKeyboard);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
 | 
						|
  for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard,&darwinEvents[i]);
 | 
						|
  DarwinPokeEQ();
 | 
						|
}
 | 
						|
 | 
						|
/* Send the appropriate number of button 4 / 5 clicks to emulate scroll wheel */
 | 
						|
void DarwinSendScrollEvents(float count, int pointer_x, int pointer_y) {
 | 
						|
  int i;
 | 
						|
  int ev_button = count > 0.0f ? 4 : 5;
 | 
						|
  int valuators[2] = {pointer_x, pointer_y};
 | 
						|
 | 
						|
  for (count = fabs(count); count > 0.0; count = count - 1.0f) {
 | 
						|
    int num_events = GetPointerEvents(darwinEvents, darwinPointer, ButtonPress, ev_button, 
 | 
						|
				      POINTER_ABSOLUTE, 0, 2, valuators);
 | 
						|
    for(i=0; i<num_events; i++) mieqEnqueue(darwinPointer,&darwinEvents[i]);
 | 
						|
    num_events = GetPointerEvents(darwinEvents, darwinPointer, ButtonRelease, ev_button, 
 | 
						|
				      POINTER_ABSOLUTE, 0, 2, valuators);
 | 
						|
    for(i=0; i<num_events; i++) mieqEnqueue(darwinPointer,&darwinEvents[i]);
 | 
						|
  }
 | 
						|
  DarwinPokeEQ();
 | 
						|
}
 | 
						|
 | 
						|
/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
 | 
						|
   reflect changing modifier flags (alt, control, meta, etc) */
 | 
						|
void DarwinUpdateModKeys(int flags) {
 | 
						|
  DarwinUpdateModifiers(KeyRelease, old_flags & ~flags);
 | 
						|
  DarwinUpdateModifiers(KeyPress, ~old_flags & flags);
 | 
						|
  old_flags = flags;
 | 
						|
}
 |