static int HandleMacEvents(void) { EventRecord theEvent; int eventFound = 0, needsUpdate = 0; Point currentMouse; WindowRef windowRef; Rect mouseRect; /* * Check for mouse moved events. These events aren't placed on the * system event queue unless we call WaitNextEvent. */ GetGlobalMouse(¤tMouse); if ((notifier.eventProcPtr != NULL) && !EqualPt(currentMouse, notifier.lastMousePosition)) { notifier.lastMousePosition = currentMouse; theEvent.what = nullEvent; if ((*notifier.eventProcPtr)(&theEvent) == true) { eventFound = 1; } } /* * Check for update events. Since update events aren't generated * until we call GetNextEvent, we may need to force a call to * GetNextEvent, even if the queue is empty. */ for (windowRef = FrontWindow(); windowRef != NULL; windowRef = GetNextWindow(windowRef)) { GetWindowUpdateRgn(windowRef, notifier.utilityRgn); if (!EmptyRgn(notifier.utilityRgn)) { needsUpdate = 1; break; } } /* * Process events from the OS event queue. */ while (needsUpdate || (GetEvQHdr()->qHead != NULL)) { GetGlobalMouse(¤tMouse); SetRect(&mouseRect, currentMouse.h, currentMouse.v, currentMouse.h + 1, currentMouse.v + 1); RectRgn(notifier.utilityRgn, &mouseRect); WaitNextEvent(everyEvent, &theEvent, 5, notifier.utilityRgn); needsUpdate = 0; if ((notifier.eventProcPtr != NULL) && ((*notifier.eventProcPtr)(&theEvent) == true)) { eventFound = 1; } } return eventFound; }
void enter_mouse( short type) { (void) (type); snapshot_delta_yaw= snapshot_delta_pitch= snapshot_delta_velocity= false; for(int i = 0; i < MAX_BUTTONS; i++) snapshot_button_state[i] = false; snapshot_delta_scrollwheel = 0; // JTP: Install our Carbon Event mouse handler and create the critical region for safe value sharing static EventTypeSpec mouseEvents[] = { {kEventClassMouse, kEventMouseDown}, {kEventClassMouse, kEventMouseUp}, {kEventClassMouse, kEventMouseWheelMoved}, {kEventClassMouse, kEventMouseMoved}, {kEventClassMouse, kEventMouseDragged} }; _CEMouseTrackerUPP = NewEventHandlerUPP(CEvtHandleApplicationMouseEvents); InstallApplicationEventHandler (_CEMouseTrackerUPP, 5, mouseEvents, NULL, &_CEMouseTracker); MPCreateCriticalRegion(&CE_MouseLock); // Fallback in case the lock cannot be allocated (possible with Classic): if (!CE_MouseLock) GetGlobalMouse(&PrevPosition); #ifndef __MACH__ LoadCGMouseFunctions(); #endif }
void wxGetMousePosition( int* x, int* y ) { Point pt; GetGlobalMouse(&pt); if ( x ) *x = pt.h; if ( y ) *y = pt.v; };
void COSXScreen::getCursorPos(SInt32& x, SInt32& y) const { Point mouse; GetGlobalMouse(&mouse); x = mouse.h; y = mouse.v; m_cursorPosValid = true; m_xCursor = x; m_yCursor = y; }
static PyObject *Evt_GetGlobalMouse(PyObject *_self, PyObject *_args) { PyObject *_res = NULL; Point globalMouse; #ifndef GetGlobalMouse PyMac_PRECHECK(GetGlobalMouse); #endif if (!PyArg_ParseTuple(_args, "")) return NULL; GetGlobalMouse(&globalMouse); _res = Py_BuildValue("O&", PyMac_BuildPoint, globalMouse); return _res; }
void COSXScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const { // OS X does not appear to have a fake relative mouse move function. // simulate it by getting the current mouse position and adding to // that. this can yield the wrong answer but there's not much else // we can do. // get current position Point oldPos; GetGlobalMouse(&oldPos); // synthesize event CGPoint pos; m_xCursor = static_cast<SInt32>(oldPos.h); m_yCursor = static_cast<SInt32>(oldPos.v); pos.x = oldPos.h + dx; pos.y = oldPos.v + dy; postMouseEvent(pos); // we now assume we don't know the current cursor position m_cursorPosValid = false; }
PsychError SCREENGetMouseHelper(void) { const char *valuatorInfo[]={"label", "min", "max", "resolution", "mode", "sourceID"}; int numValuatorStructFieldNames = 6; int numIValuators = 0; PsychGenericScriptType *valuatorStruct = NULL; #if PSYCH_SYSTEM == PSYCH_OSX Point mouseXY; UInt32 buttonState; double *buttonArray; int numButtons, i; psych_bool doButtonArray; PsychWindowRecordType *windowRecord; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //cap the numbers of inputs and outputs PsychErrorExit(PsychCapNumInputArgs(3)); //The maximum number of inputs PsychErrorExit(PsychCapNumOutputArgs(6)); //The maximum number of outputs //Buttons. // The only way I know to detect the number number of mouse buttons is directly via HID. The device reports //that information but OS X seems to ignore it above the level of the HID driver, that is, no OS X API above the HID driver //exposes it. So GetMouse.m function calls PsychHID detect the number of buttons and then passes that value to GetMouseHelper //which returns that number of button values in a vector. PsychCopyInIntegerArg(1, kPsychArgRequired, &numButtons); if(numButtons > 32) PsychErrorExitMsg(PsychErorr_argumentValueOutOfRange, "numButtons must not exceed 32"); // Special codes -10 to -15? --> Console keyboard queries: if(numButtons <= -10 && numButtons >= -15) { ConsoleInputHelper((int) numButtons); return(PsychError_none); } if(numButtons < 1) PsychErrorExitMsg(PsychErorr_argumentValueOutOfRange, "numButtons must exceed 1"); doButtonArray=PsychAllocOutDoubleMatArg(3, kPsychArgOptional, (int)1, (int)numButtons, (int)1, &buttonArray); if(doButtonArray){ buttonState=GetCurrentButtonState(); for(i=0;i<numButtons;i++) buttonArray[i]=(double)(buttonState & (1<<i)); } // Get cursor position: #ifndef __LP64__ // 32-Bit Carbon version: GetGlobalMouse(&mouseXY); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double)mouseXY.h); PsychCopyOutDoubleArg(2, kPsychArgOptional, (double)mouseXY.v); #else // 64-Bit HIToolbox version (OSX 10.5 and later): HIPoint outPoint; HIGetMousePosition(kHICoordSpaceScreenPixel, NULL, &outPoint); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) outPoint.x); PsychCopyOutDoubleArg(2, kPsychArgOptional, (double) outPoint.y); #endif // Return optional keyboard input focus status: if (numButtons > 0) { // Window provided? // We only have the function GetUserFocusWindow on 32-Bit Carbon. // We have a drop-in replacement in OSX/PsychCocoaGlue.c for 64-Bit Cocoa. if (PsychIsWindowIndexArg(2)) { // Yes: Check if it has focus. PsychAllocInWindowRecordArg(2, TRUE, &windowRecord); if (!PsychIsOnscreenWindow(windowRecord)) { PsychErrorExitMsg(PsychError_user, "Provided window handle isn't an onscreen window, as required."); } PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) (GetUserFocusWindow() == windowRecord->targetSpecific.windowHandle) ? 1 : 0); } else { // No. Just always return "has focus": PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) 1); } } // Return optional valuator values: Unimplemented on OS/X. Just return an empty matrix. // The buttonArray is just a dummy assignment without any meaning. PsychCopyOutDoubleMatArg(5, kPsychArgOptional, (int) 1, (int) 0, (int) 1, buttonArray); PsychCopyOutDoubleMatArg(6, kPsychArgOptional, (int) 1, (int) 0, (int) 1, buttonArray); #endif #if PSYCH_SYSTEM == PSYCH_WINDOWS static unsigned char disabledKeys[256]; static unsigned char firsttime = 1; int keysdown, i, priorityLevel; unsigned char keyState[256]; double* buttonArray; double numButtons, timestamp; PsychNativeBooleanType* buttonStates; POINT point; HANDLE currentProcess; DWORD oldPriority = NORMAL_PRIORITY_CLASS; const DWORD realtime_class = REALTIME_PRIORITY_CLASS; PsychWindowRecordType *windowRecord; PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; // Retrieve optional number of mouse buttons: numButtons = 0; PsychCopyInDoubleArg(1, FALSE, &numButtons); // Are we operating in 'GetMouseHelper' mode? numButtons>=0 indicates this. if (numButtons>=0) { // GetMouse-Mode: Return mouse button states and mouse cursor position: PsychAllocOutDoubleMatArg(3, kPsychArgOptional, (int)1, (int)3, (int)1, &buttonArray); // Query and return mouse button state: PsychGetMouseButtonState(buttonArray); // Query and return cursor position in global coordinates: GetCursorPos(&point); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) point.x); PsychCopyOutDoubleArg(2, kPsychArgOptional, (double) point.y); // Window provided? if (PsychIsWindowIndexArg(2)) { // Yes: Check if it has focus. PsychAllocInWindowRecordArg(2, TRUE, &windowRecord); if (!PsychIsOnscreenWindow(windowRecord)) { PsychErrorExitMsg(PsychError_user, "Provided window handle isn't an onscreen window, as required."); } PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) (GetForegroundWindow() == windowRecord->targetSpecific.windowHandle) ? 1 : 0); } else { // No. Just always return "has focus": PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) 1); } // Return optional valuator values: Unimplemented on Windows. Just return an empty matrix. // The ×tamp is just a dummy assignment without any meaning. PsychCopyOutDoubleMatArg(5, kPsychArgOptional, (int) 1, (int) 0, (int) 1, ×tamp); PsychCopyOutDoubleMatArg(6, kPsychArgOptional, (int) 1, (int) 0, (int) 1, buttonArray); } else { // 'KeyboardHelper' mode: We implement either KbCheck() or KbWait() via X11. // This is a hack to provide keyboard queries until a PsychHID() implementation // for Microsoft Windows is available... // Special codes -10 to -15? --> Console keyboard queries: if(numButtons <= -10 && numButtons >= -15) { ConsoleInputHelper((int) numButtons); return(PsychError_none); } if (firsttime) { // First time init: firsttime = 0; memset(keyState, 0, sizeof(keyState)); memset(disabledKeys, 0, sizeof(disabledKeys)); // These keycodes are always disabled: 0, 255: disabledKeys[0]=1; disabledKeys[255]=1; // Mouse buttone (left, right, middle) are also disabled by default: disabledKeys[1]=1; disabledKeys[2]=1; disabledKeys[4]=1; } if (numButtons==-1 || numButtons==-2) { // KbCheck()/KbWait() mode do { // Reset overall key state to "none pressed": keysdown=0; // Request current time of query: PsychGetAdjustedPrecisionTimerSeconds(×tamp); // Query state of all keys: for(i=1;i<255;i++){ keyState[i] = (GetAsyncKeyState(i) & -32768) ? 1 : 0; } // Disable all keys that are registered in disabledKeys. Check if // any non-disabled key is down. for (i=0; i<256; i++) { if (disabledKeys[i]>0) keyState[i] = 0; keysdown+=(unsigned int) keyState[i]; } // We repeat until any key pressed if in KbWait() mode, otherwise we // exit the loop after first iteration in KbCheck mode. if ((numButtons==-1) || ((numButtons==-2) && (keysdown>0))) break; // Sleep for a millisecond before next KbWait loop iteration: PsychWaitIntervalSeconds(0.001); } while(1); if (numButtons==-2) { // KbWait mode: Copy out time value. PsychCopyOutDoubleArg(1, kPsychArgOptional, timestamp); } else { // KbCheck mode: // Copy out overall keystate: PsychCopyOutDoubleArg(1, kPsychArgOptional, (keysdown>0) ? 1 : 0); // Copy out timestamp: PsychCopyOutDoubleArg(2, kPsychArgOptional, timestamp); // Copy out keyboard state: PsychAllocOutBooleanMatArg(3, kPsychArgOptional, 1, 256, 1, &buttonStates); // Build 256 elements return vector: for(i=0; i<255; i++) { buttonStates[i] = (PsychNativeBooleanType)((keyState[i+1]) ? 1 : 0); } // Special case: Null out last element: buttonStates[255] = (PsychNativeBooleanType) 0; } } if (numButtons==-3) { // Priority() - helper mode: The 2nd argument is the priority level: // Determine our processID: currentProcess = GetCurrentProcess(); // Get current scheduling policy: oldPriority = GetPriorityClass(currentProcess); // Map to PTB's scheme: switch(oldPriority) { case NORMAL_PRIORITY_CLASS: priorityLevel = 0; break; case HIGH_PRIORITY_CLASS: priorityLevel = 1; break; case REALTIME_PRIORITY_CLASS: priorityLevel = 2; break; default: priorityLevel = 0; } // Copy it out as optional return argument: PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) priorityLevel); // Query if a new level should be set: priorityLevel = -1; PsychCopyInIntegerArg(2, kPsychArgOptional, &priorityLevel); // Priority level provided? if (priorityLevel > -1) { // Map to new scheduling class: if (priorityLevel > 2) PsychErrorExitMsg(PsychErorr_argumentValueOutOfRange, "Invalid Priority level: Requested Priority() level must not exceed 2."); switch(priorityLevel) { case 0: // Standard scheduling: SetPriorityClass(currentProcess, NORMAL_PRIORITY_CLASS); // Disable any MMCSS scheduling for us: PsychSetThreadPriority((psych_thread*) 0x1, 0, 0); break; case 1: // High priority scheduling: SetPriorityClass(currentProcess, HIGH_PRIORITY_CLASS); // Additionally try to schedule us MMCSS: This will lift us roughly into the // same scheduling range as REALTIME_PRIORITY_CLASS, even if we are non-admin users // on Vista and Windows-7 and later, however with a scheduler safety net applied. PsychSetThreadPriority((psych_thread*) 0x1, 10, 0); break; case 2: // Realtime scheduling: // This can fail if Matlab is not running under a user account with proper permissions: if ((0 == SetPriorityClass(currentProcess, REALTIME_PRIORITY_CLASS)) || (REALTIME_PRIORITY_CLASS != GetPriorityClass(currentProcess))) { // Failed to get RT-Scheduling. Let's try at least high priority scheduling: SetPriorityClass(currentProcess, HIGH_PRIORITY_CLASS); // Additionally try to schedule us MMCSS: This will lift us roughly into the // same scheduling range as REALTIME_PRIORITY_CLASS, even if we are non-admin users // on Vista and Windows-7 and later, however with a scheduler safety net applied. PsychSetThreadPriority((psych_thread*) 0x1, 10, 0); } break; } } // End of Priority() helper for Win32. } } #endif #if PSYCH_SYSTEM == PSYCH_LINUX double myvaluators[100]; int numvaluators; unsigned char keys_return[32]; char* keystring; PsychGenericScriptType *kbNames; CGDirectDisplayID dpy; Window rootwin, childwin, mywin; int i, j, mx, my, dx, dy; double mxd, myd, dxd, dyd; unsigned int mask_return; double timestamp; int numButtons; double* buttonArray; PsychNativeBooleanType* buttonStates; int keysdown; XEvent event_return; XKeyPressedEvent keypressevent; int screenNumber; int priorityLevel; struct sched_param schedulingparam; PsychWindowRecordType *windowRecord; int mouseIndex; XIButtonState buttons_return; XIModifierState modifiers_return; XIGroupState group_return; PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychCopyInIntegerArg(1, kPsychArgRequired, &numButtons); // Retrieve optional screenNumber argument: if (numButtons!=-5) { screenNumber = 0; if (PsychIsScreenNumberArg(2)) { PsychCopyInScreenNumberArg(2, FALSE, &screenNumber); } // Map screenNumber to X11 display handle and screenid: PsychGetCGDisplayIDFromScreenNumber(&dpy, screenNumber); if (PsychIsWindowIndexArg(2)) { PsychAllocInWindowRecordArg(2, TRUE, &windowRecord); if (!PsychIsOnscreenWindow(windowRecord)) { PsychErrorExitMsg(PsychError_user, "Provided window handle isn't an onscreen window, as required."); } screenNumber = windowRecord->screenNumber; mywin = windowRecord->targetSpecific.xwindowHandle; // Map screenNumber to X11 display handle and screenid: PsychGetCGDisplayIDFromScreenNumber(&dpy, screenNumber); } else { mywin = RootWindow(dpy, PsychGetXScreenIdForScreen(screenNumber)); } } // Default to "old school" mouse query - System default mouse via X core protocol: mouseIndex = -1; PsychCopyInIntegerArg(3, FALSE, &mouseIndex); // Are we operating in 'GetMouseHelper' mode? numButtons>=0 indicates this. if (numButtons>=0) { // Mouse pointer query mode: numvaluators = 0; if (mouseIndex >= 0) { // XInput-2 query for handling of multiple mouse pointers: // Query input device list for screen: int nDevices; XIDeviceInfo* indevs = PsychGetInputDevicesForScreen(screenNumber, &nDevices); // Sanity check: if (NULL == indevs) PsychErrorExitMsg(PsychError_user, "Sorry, your system does not support individual mouse pointer queries."); if (mouseIndex >= nDevices) PsychErrorExitMsg(PsychError_user, "Invalid 'mouseIndex' provided. No such device."); if ((indevs[mouseIndex].use != XIMasterPointer) && (indevs[mouseIndex].use != XISlavePointer) && (indevs[mouseIndex].use != XIFloatingSlave)) { PsychErrorExitMsg(PsychError_user, "Invalid 'mouseIndex' provided. Not a pointer device."); } // We requery the device info struct to retrieve updated live device state: // Crucial for slave pointers to get any state at all, but also needed on // master pointers to get the state of additional valuators, e.g., pen pressure, // touch area, tilt etc. for digitizer tablets, touch pads etc. For master pointers, // the primary 2 axis for 2D (x,y) position and the button/modifier state will be // queried via a dedicated XIQueryPointer() call, so that info gets overriden. indevs = XIQueryDevice(dpy, indevs[mouseIndex].deviceid, &numButtons); modifiers_return.effective = 0; // Query real number of mouse buttons and the raw button and axis state // stored inside the device itself. This is done mostly because slave pointer // devices don't support XIQueryPointer() so we get their relevant info from the // XIDeviceInfo struct itself: numButtons = 0; numvaluators = 0; memset(myvaluators, 0, sizeof(myvaluators)); if (PsychIsArgPresent(PsychArgOut, 6)) { // Usercode wants valuator info structs: for (i = 0; i < indevs->num_classes; i++) if (indevs->classes[i]->type == XIValuatorClass) numIValuators++; PsychAllocOutStructArray(6, TRUE, numIValuators, numValuatorStructFieldNames, valuatorInfo, &valuatorStruct); } for (i = 0; i < indevs->num_classes; i++) { // printf("Class %i: Type %i\n", i, (int) indevs->classes[i]->type); if (indevs->classes[i]->type == XIButtonClass) { // Number of buttons: For all pointers. numButtons = ((XIButtonClassInfo*) indevs->classes[i])->num_buttons; // Button state for slave pointers. Will get overriden for master pointers: buttons_return.mask = ((XIButtonClassInfo*) indevs->classes[i])->state.mask; buttons_return.mask_len = ((XIButtonClassInfo*) indevs->classes[i])->state.mask_len; } // Axis state for slave pointers. First two axis (x,y) will get overriden for master pointers: if (indevs->classes[i]->type == XIValuatorClass) { XIValuatorClassInfo* axis = (XIValuatorClassInfo*) indevs->classes[i]; if (axis->number == 0) mxd = axis->value; // x-Axis. if (axis->number == 1) myd = axis->value; // y-Axis. // Additional axis, e.g., digitizer tablet, touchpads etc.: if (axis->number >= 0 && axis->number < 100) { myvaluators[axis->number] = axis->value; numvaluators = (numvaluators >= axis->number + 1) ? numvaluators : axis->number + 1; } // Assign valuator info struct, if requested: if (valuatorStruct) { if (axis->label != None) { char* atomlabel = XGetAtomName(dpy, axis->label); PsychSetStructArrayStringElement("label", axis->number, atomlabel, valuatorStruct); XFree(atomlabel); } else { PsychSetStructArrayStringElement("label", axis->number, "None", valuatorStruct); } PsychSetStructArrayDoubleElement("min", axis->number, (double) axis->min, valuatorStruct); PsychSetStructArrayDoubleElement("max", axis->number, (double) axis->max, valuatorStruct); PsychSetStructArrayDoubleElement("resolution", axis->number, (double) axis->resolution, valuatorStruct); PsychSetStructArrayDoubleElement("mode", axis->number, (double) axis->mode, valuatorStruct); PsychSetStructArrayDoubleElement("sourceID", axis->number, (double) axis->sourceid, valuatorStruct); } // printf("AXIS %i, LABEL = %s, MIN = %f, MAX = %f, VAL = %f\n", axis->number, (char*) "NONE", (float) axis->min, (float) axis->max, (float) axis->value); } } // Add 32 buttons for modifier key state vector: numButtons += 32; // A real master pointer: Use official query for mouse devices. if (indevs->use == XIMasterPointer) { // Query pointer location and state: XIQueryPointer(dpy, indevs->deviceid, RootWindow(dpy, PsychGetXScreenIdForScreen(screenNumber)), &rootwin, &childwin, &mxd, &myd, &dxd, &dyd, &buttons_return, &modifiers_return, &group_return); } // Copy out mouse x and y position: PsychCopyOutDoubleArg(1, kPsychArgOptional, mxd); PsychCopyOutDoubleArg(2, kPsychArgOptional, myd); // Copy out mouse button state: PsychAllocOutDoubleMatArg(3, kPsychArgOptional, (int)1, (int) numButtons, (int)1, &buttonArray); memset(buttonArray, 0, sizeof(double) * numButtons); if (numButtons > 0) { // Mouse buttons: const int buttonOffset = 1; // Buttons start at bit 1, not 0 for some strange reason? At least so on Ubuntu 10.10 and 11.10 with 2 mice and 1 joystick? for (i = buttonOffset; (i < numButtons - 32) && ((i / 8 ) < buttons_return.mask_len); i++) { buttonArray[i - buttonOffset] = (double) ((buttons_return.mask[i / 8] & (1 << (i % 8))) ? 1 : 0); } // Free mask if retrieved via XIQueryPointer(): if (indevs->use == XIMasterPointer) free(buttons_return.mask); // Append modifier key state from associated master keyboard. Last 32 entries: for (i = 0; i < 32; i++) { buttonArray[numButtons - 32 + i] = (double) ((modifiers_return.effective & (1 << i)) ? 1 : 0); } } // Release live state info structure: XIFreeDeviceInfo(indevs); } else { // Old school core protocol query of virtual core pointer: XQueryPointer(dpy, RootWindow(dpy, PsychGetXScreenIdForScreen(screenNumber)), &rootwin, &childwin, &mx, &my, &dx, &dy, &mask_return); // Copy out mouse x and y position: PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) mx); PsychCopyOutDoubleArg(2, kPsychArgOptional, (double) my); // Copy out mouse button state: PsychAllocOutDoubleMatArg(3, kPsychArgOptional, (int)1, (int)numButtons, (int)1, &buttonArray); // Bits 8, 9 and 10 of mask_return seem to correspond to mouse buttons // 1, 2 and 3 of a mouse for some weird reason. Bits 0-7 describe keyboard modifier keys // like Alt, Ctrl, Shift, ScrollLock, NumLock, CapsLock... // We remap here, so the first three returned entries correspond to the mouse buttons and // the rest is attached behind, if requested... // Mouse buttons: Left, Middle, Right == 0, 1, 2, aka 1,2,3 in Matlab space... for (i=0; i<numButtons && i<3; i++) { buttonArray[i] = (mask_return & (1<<(i+8))) ? 1 : 0; } // Modifier keys 0 to 7 appended: for (i=3; i<numButtons && i<3+8; i++) { buttonArray[i] = (mask_return & (1<<(i-3))) ? 1 : 0; } // Everything else appended: for (i=11; i<numButtons; i++) { buttonArray[i] = (mask_return & (1<<i)) ? 1 : 0; } } // Return optional 4th argument: Focus state. Returns 1 if our window has // keyboard input focus, zero otherwise: XGetInputFocus(dpy, &rootwin, &i); PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) (rootwin == mywin) ? 1 : 0); // Return optional valuator values: PsychCopyOutDoubleMatArg(5, kPsychArgOptional, (int) 1, (int) numvaluators, (int) 1, &myvaluators[0]); } else { // 'KeyboardHelper' mode: We implement either KbCheck() or KbWait() via X11. // This is a hack to provide keyboard queries until a PsychHID() implementation // for Linux is available... // Special codes -10 to -15? --> Console keyboard queries: if(numButtons <= -10 && numButtons >= -15) { ConsoleInputHelper((int) numButtons); return(PsychError_none); } if (numButtons==-1 || numButtons==-2) { // KbCheck()/KbWait() mode: // Switch X-Server into synchronous mode: We need this to get // a higher timing precision. XSynchronize(dpy, TRUE); do { // Reset overall key state to "none pressed": keysdown=0; // Request current keyboard state from X-Server: XQueryKeymap(dpy, keys_return); // Request current time of query: PsychGetAdjustedPrecisionTimerSeconds(×tamp); // Any key down? for (i=0; i<32; i++) keysdown+=(unsigned int) keys_return[i]; // We repeat until any key pressed if in KbWait() mode, otherwise we // exit the loop after first iteration in KbCheck mode. if ((numButtons==-1) || ((numButtons==-2) && (keysdown>0))) break; // Sleep for a few milliseconds before next KbWait loop iteration: PsychWaitIntervalSeconds(0.01); } while(1); if (numButtons==-2) { // Copy out time: PsychCopyOutDoubleArg(1, kPsychArgOptional, timestamp); } else { // KbCheck mode: // Copy out overall keystate: PsychCopyOutDoubleArg(1, kPsychArgOptional, (keysdown>0) ? 1 : 0); // copy out timestamp: PsychCopyOutDoubleArg(2, kPsychArgOptional, timestamp); // Copy keyboard state: PsychAllocOutBooleanMatArg(3, kPsychArgOptional, 1, 256, 1, &buttonStates); // Map 32 times 8 bitvector to 256 element return vector: for(i=0; i<32; i++) { for(j=0; j<8; j++) { buttonStates[i*8 + j] = (PsychNativeBooleanType)(keys_return[i] & (1<<j)) ? 1 : 0; } } } } else if (numButtons == -3) { // numButtons == -3 --> KbName mapping mode: // Return the full keyboard keycode to ASCII character code mapping table... PsychAllocOutCellVector(1, kPsychArgOptional, 256, &kbNames); for(i=0; i<256; i++) { // Map keyboard scan code to KeySym: keystring = XKeysymToString(XKeycodeToKeysym(dpy, i, 0)); if (keystring) { // Character found: Return its ASCII name string: PsychSetCellVectorStringElement(i, keystring, kbNames); } else { // No character for this keycode: PsychSetCellVectorStringElement(i, "", kbNames); } } } else if (numButtons == -4) { // GetChar() emulation. /* do { */ /* // Fetch next keypress event from queue, block if none is available... */ /* keystring = NULL; */ /* XNextEvent(dpy, &event_return); */ /* // Check for valid keypress event and extract character: */ /* if (event_return.type == KeyPress) { */ /* keypressevent = (XKeyPressedEvent) event_return; */ /* keystring = NULL; */ /* keystring = XKeysymToString(XKeycodeToKeysym(dpy, keypressevent.keycode, 0)); */ /* } */ /* // Repeat until a valid char is returned. */ /* } while (keystring == NULL); */ /* // Copy out character: */ /* PsychCopyOutCharArg(1, kPsychArgOptional, (char) keystring); */ /* // Copy out time: */ /* PsychCopyOutDoubleArg(2, kPsychArgOptional, (double) keypressevent.time); */ } else if (numButtons==-5) { // Priority() - helper mode: The 2nd argument is the priority level: // Query scheduling policy and priority: pthread_getschedparam(pthread_self(), &priorityLevel, &schedulingparam); // If scheduling mode is a realtime mode (RoundRobin realtime RR, or FIFO realtime), // then assign RT priority level (range 1-99) as current priorityLevel, otherwise // assign non realtime priority level zero: priorityLevel = (priorityLevel == SCHED_RR || priorityLevel == SCHED_FIFO) ? schedulingparam.sched_priority : 0; // Copy it out as optional return argument: PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) priorityLevel); // Query if a new level should be set: priorityLevel = -1; PsychCopyInIntegerArg(2, kPsychArgOptional, &priorityLevel); errno=0; // Priority level provided? if (priorityLevel > -1) { // Map to new scheduling class: if (priorityLevel > 99 || priorityLevel < 0) PsychErrorExitMsg(PsychErorr_argumentValueOutOfRange, "Invalid Priority level: Requested Priority() level must be between zero and 99!"); if (priorityLevel > 0) { // Realtime FIFO scheduling and all pages of Matlab/Octave locked into memory: schedulingparam.sched_priority = priorityLevel; priorityLevel = pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedulingparam); if (priorityLevel == -1) { // Failed! if(!PsychPrefStateGet_SuppressAllWarnings()) { printf("PTB-ERROR: Failed to enable realtime-scheduling with Priority(%i) [%s]!\n", schedulingparam.sched_priority, strerror(errno)); if (errno==EPERM) { printf("PTB-ERROR: You need to run Matlab/Octave with root-privileges, or run the script PsychLinuxConfiguration once for this to work.\n"); } } errno=0; } else { // RT-Scheduling active. Lock all current and future memory: priorityLevel = mlockall(MCL_CURRENT | MCL_FUTURE); if (priorityLevel!=0) { // Failed! Report problem as warning, but don't worry further. if(!PsychPrefStateGet_SuppressAllWarnings()) printf("PTB-WARNING: Failed to enable system memory locking with Priority(%i) [%s]!\n", schedulingparam.sched_priority, strerror(errno)); // Undo any possibly partial mlocks.... munlockall(); errno=0; } } } else { // Standard scheduling and no memory locking: schedulingparam.sched_priority = 0; priorityLevel = pthread_setschedparam(pthread_self(), SCHED_OTHER, &schedulingparam); if (priorityLevel == -1) { // Failed! if(!PsychPrefStateGet_SuppressAllWarnings()) { printf("PTB-ERROR: Failed to disable realtime-scheduling with Priority(%i) [%s]!\n", schedulingparam.sched_priority, strerror(errno)); if (errno==EPERM) { printf("PTB-ERROR: You need to run Matlab/Octave with root-privileges, or run the script PsychLinuxConfiguration once for this to work.\n"); } } errno=0; } munlockall(); errno=0; } // End of setup of new Priority... } // End of Priority() helper for Linux. } } // End of special functions handling for Linux... #endif return(PsychError_none); }
int Tcl_WaitForEvent( Tcl_Time *timePtr) /* Maximum block time. */ { int found; EventRecord macEvent; long sleepTime = 5; long ms; Point currentMouse; void * timerToken; Rect mouseRect; /* * Compute the next timeout value. */ if (!timePtr) { ms = INT_MAX; } else { ms = (timePtr->sec * 1000) + (timePtr->usec / 1000); } timerToken = TclMacStartTimer((long) ms); /* * Poll the Mac event sources. This loop repeats until something * happens: a timeout, a socket event, mouse motion, or some other * window event. Note that we don't call WaitNextEvent if another * event is found to avoid context switches. This effectively gives * events coming in via WaitNextEvent a slightly lower priority. */ found = 0; if (notifier.utilityRgn == NULL) { notifier.utilityRgn = NewRgn(); } while (!found) { /* * Check for generated and queued events. */ if (HandleMacEvents()) { found = 1; } /* * Check for time out. */ if (!found && TclMacTimerExpired(timerToken)) { found = 1; } /* * Check for window events. We may receive a NULL event for * various reasons. 1) the timer has expired, 2) a mouse moved * event is occuring or 3) the os is giving us time for idle * events. Note that we aren't sharing the processor very * well here. We really ought to do a better job of calling * WaitNextEvent for time slicing purposes. */ if (!found) { /* * Set up mouse region so we will wake if the mouse is moved. * We do this by defining the smallest possible region around * the current mouse position. */ GetGlobalMouse(¤tMouse); SetRect(&mouseRect, currentMouse.h, currentMouse.v, currentMouse.h + 1, currentMouse.v + 1); RectRgn(notifier.utilityRgn, &mouseRect); WaitNextEvent(everyEvent, &macEvent, sleepTime, notifier.utilityRgn); if (notifier.eventProcPtr != NULL) { if ((*notifier.eventProcPtr)(&macEvent) == true) { found = 1; } } } } TclMacRemoveTimer(timerToken); return 0; }
Bool XQueryPointer( Display* display, Window w, Window* root_return, Window* child_return, int* root_x_return, int* root_y_return, int* win_x_return, int* win_y_return, unsigned int* mask_return) { int getGlobal = (root_x_return && root_y_return); int getLocal = (win_x_return && win_y_return); if (getGlobal || getLocal) { Point where, local; OSStatus err = noErr; int gotMouseLoc = 0; EventRef ev = GetCurrentEvent(); if (ev && getLocal) { err = ChkErr(GetEventParameter, ev, kEventParamWindowMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &local); gotMouseLoc = (err == noErr); } if (getGlobal || !gotMouseLoc) { if (ev) { err = ChkErr(GetEventParameter, ev, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &where); } if (!ev || err != noErr) { GetGlobalMouse(&where); } } if (getLocal) { WindowRef whichWin; if (ev) { err = ChkErr(GetEventParameter, ev, kEventParamWindowRef, typeWindowRef, NULL, sizeof(WindowRef), NULL, &whichWin); } if (!ev || err != noErr) { FindWindow(where, &whichWin); } if (gotMouseLoc) { if (whichWin) { Rect widths; ChkErr(GetWindowStructureWidths, whichWin, &widths); local.h -= widths.left; local.v -= widths.top; } } else { local = where; if (whichWin) { QDGlobalToLocalPoint(GetWindowPort(whichWin), &local); } } } if (getGlobal) { *root_x_return = where.h; *root_y_return = where.v; } if (getLocal) { *win_x_return = local.h; *win_y_return = local.v; } } if (mask_return) { *mask_return = TkMacOSXButtonKeyState(); } return True; }
MODULE_SCOPE int TkMacOSXProcessMouseEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) { Tk_Window tkwin; Point where, where2; int result; TkDisplay * dispPtr; OSStatus err; MouseEventData mouseEventData, * medPtr = &mouseEventData; int isFrontProcess; switch (eventPtr->eKind) { case kEventMouseDown: case kEventMouseUp: case kEventMouseMoved: case kEventMouseDragged: case kEventMouseWheelMoved: break; default: return false; break; } err = ChkErr(GetEventParameter, eventPtr->eventRef, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(where), NULL, &where); if (err != noErr) { GetGlobalMouse(&where); } err = ChkErr(GetEventParameter, eventPtr->eventRef, kEventParamWindowRef, typeWindowRef, NULL, sizeof(WindowRef), NULL, &medPtr->whichWin); if (err == noErr) { err = ChkErr(GetEventParameter, eventPtr->eventRef, kEventParamWindowPartCode, typeWindowPartCode, NULL, sizeof(WindowPartCode), NULL, &medPtr->windowPart); } if (err != noErr) { medPtr->windowPart = FindWindow(where, &medPtr->whichWin); } medPtr->window = TkMacOSXGetXWindow(medPtr->whichWin); if (medPtr->whichWin != NULL && medPtr->window == None) { return false; } if (eventPtr->eKind == kEventMouseDown) { if (IsWindowActive(medPtr->whichWin) && IsWindowPathSelectEvent( medPtr->whichWin, eventPtr->eventRef)) { ChkErr(WindowPathSelect, medPtr->whichWin, NULL, NULL); return false; } if (medPtr->windowPart == inProxyIcon) { TkMacOSXTrackingLoop(1); err = ChkErr(TrackWindowProxyDrag, medPtr->whichWin, where); TkMacOSXTrackingLoop(0); if (err == errUserWantsToDragWindow) { medPtr->windowPart = inDrag; } else { return false; } } } isFrontProcess = Tk_MacOSXIsAppInFront(); if (isFrontProcess) { medPtr->state = ButtonModifiers2State(GetCurrentEventButtonState(), GetCurrentEventKeyModifiers()); } else { medPtr->state = ButtonModifiers2State(GetCurrentButtonState(), GetCurrentKeyModifiers()); } medPtr->global = where; err = ChkErr(GetEventParameter, eventPtr->eventRef, kEventParamWindowMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &medPtr->local); if (err == noErr) { if (medPtr->whichWin) { Rect widths; GetWindowStructureWidths(medPtr->whichWin, &widths); medPtr->local.h -= widths.left; medPtr->local.v -= widths.top; } } else { medPtr->local = where; if (medPtr->whichWin) { QDGlobalToLocalPoint(GetWindowPort(medPtr->whichWin), &medPtr->local); } } medPtr->activeNonFloating = ActiveNonFloatingWindow(); dispPtr = TkGetDisplayList(); tkwin = Tk_IdToWindow(dispPtr->display, medPtr->window); if (eventPtr->eKind != kEventMouseDown) { int res = false; switch (eventPtr->eKind) { case kEventMouseUp: /* * The window manager only needs to know about mouse down * events and sometimes we need to "eat" the mouse up. * Otherwise, we just pass the event to Tk. */ if (TkMacOSXGetEatButtonUp()) { TkMacOSXSetEatButtonUp(false); } else { res = GenerateButtonEvent(medPtr); } break; case kEventMouseWheelMoved: err = ChkErr(GetEventParameter, eventPtr->eventRef, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(long), NULL, &medPtr->delta); if (err != noErr ) { statusPtr->err = 1; } else { EventMouseWheelAxis axis; err = ChkErr(GetEventParameter, eventPtr->eventRef, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(EventMouseWheelAxis), NULL, &axis); if (err == noErr && axis == kEventMouseWheelAxisX) { medPtr->state |= ShiftMask; } res = GenerateMouseWheelEvent(medPtr); } break; case kEventMouseMoved: case kEventMouseDragged: res = GeneratePollingEvents(medPtr); break; default: Tcl_Panic("Unknown mouse event !"); } if (res) { statusPtr->stopProcessing = 1; } return res; } TkMacOSXSetEatButtonUp(false); if (medPtr->whichWin) { /* * We got a mouse down in a window * See if this is the activate click * This click moves the window forward. We don't want * the corresponding mouse-up to be reported to the application * or else it will mess up some Tk scripts. */ if (!(TkpIsWindowFloating(medPtr->whichWin)) && (medPtr->whichWin != medPtr->activeNonFloating || !isFrontProcess)) { int frontWindowOnly = 1; int cmdDragGrow = ((medPtr->windowPart == inDrag || medPtr->windowPart == inGrow) && medPtr->state & Mod1Mask); if (!cmdDragGrow) { Tk_Window grabWin = GetGrabWindowForWindow(tkwin); frontWindowOnly = !grabWin; if (grabWin && grabWin != tkwin) { TkMacOSXSetEatButtonUp(true); BringWindowForward(TkMacOSXDrawableWindow( ((TkWindow*)grabWin)->window), isFrontProcess, frontWindowOnly); return false; } } /* * Clicks in the titlebar widgets are handled without bringing the * window forward. */ if ((result = HandleWindowTitlebarMouseDown(medPtr, tkwin)) != -1) { statusPtr->stopProcessing = 1; return result; } else { /* * Only windows with the kWindowNoActivatesAttribute can * receive mouse events in the background. */ if (!(((TkWindow *)tkwin)->wmInfoPtr->attributes & kWindowNoActivatesAttribute)) { /* * Allow background window dragging & growing with Command * down. */ if (!cmdDragGrow) { TkMacOSXSetEatButtonUp(true); BringWindowForward(medPtr->whichWin, isFrontProcess, frontWindowOnly); } /* * Allow dragging & growing of windows that were/are in the * background. */ if (!(medPtr->windowPart == inDrag || medPtr->windowPart == inGrow)) { return false; } } } } else { if ((result = HandleWindowTitlebarMouseDown(medPtr, tkwin)) != -1) { statusPtr->stopProcessing = 1; return result; } } switch (medPtr->windowPart) { case inDrag: { WindowAttributes attributes; GetWindowAttributes(medPtr->whichWin, &attributes); if (!(attributes & kWindowAsyncDragAttribute)) { TkMacOSXTrackingLoop(1); DragWindow(medPtr->whichWin, where, NULL); TkMacOSXTrackingLoop(0); where2.h = where2.v = 0; QDLocalToGlobalPoint(GetWindowPort(medPtr->whichWin), &where2); if (EqualPt(where, where2)) { return false; } return true; } break; } case inGrow: /* * Generally the content region is the domain of Tk * sub-windows. However, one exception is the grow * region. A button down in this area will be handled * by the window manager. Note: this means that Tk * may not get button down events in this area! */ if (TkMacOSXGrowToplevel(medPtr->whichWin, where) == true) { statusPtr->stopProcessing = 1; return true; } else { return GenerateButtonEvent(medPtr); } break; case inContent: return GenerateButtonEvent(medPtr); break; default: return false; break; } } return false; }
CGPoint mouseLoc() { Point currLoc; GetGlobalMouse(&currLoc); CGPoint cgLoc = {.x = currLoc.h, .y = currLoc.v}; return cgLoc; } // btn: 0 = none, 1 = left, 2 = right, etc CGEventType mouseEventType(int btn, int btnState) { switch(btn) { case NO_MOUSE_BUTTON: return kCGEventMouseMoved; case LEFT_MOUSE: switch(btnState) { case MOUSE_UP: return kCGEventLeftMouseUp; case MOUSE_DRAGGED: return kCGEventLeftMouseDragged; default: return kCGEventLeftMouseDown; } case RIGHT_MOUSE: switch(btnState) { case MOUSE_UP: return kCGEventRightMouseUp; case MOUSE_DRAGGED: return kCGEventRightMouseDragged; default: return kCGEventRightMouseDown; } default: switch(btnState) { case MOUSE_UP: return kCGEventOtherMouseUp; case MOUSE_DRAGGED: return kCGEventOtherMouseDragged; default: return kCGEventOtherMouseDown; } } } void mouseEvent(int btn, int btnState, int clickType) { CGPoint currLoc; currLoc = mouseLoc(); CGEventType mouseType = mouseEventType(btn, btnState); CGMouseButton mb = (btn == LEFT_MOUSE) ? kCGMouseButtonLeft : (btn == RIGHT_MOUSE) ? kCGMouseButtonRight : kCGMouseButtonCenter; CGEventRef theEvent = CGEventCreateMouseEvent(NULL, mouseType, currLoc, mb); if (clickType) { CGEventSetIntegerValueField(theEvent, kCGMouseEventClickState, clickType); } CGEventPost(kCGHIDEventTap, theEvent); CFRelease(theEvent); }
int main( int argc, char ** argv) { CGSize mainScreenSize = CGDisplayScreenSize (CGMainDisplayID ()); CGDirectDisplayID currentDisplayID = CGMainDisplayID (); CGSize currentDisplaySize = mainScreenSize; CGRect displayRect; CGPoint newloc; Point pt; CGEventRef eventRef; InputEvent event; pInputEvent pEvent = &event; SOCKET s, s_accept; struct sockaddr_in s_add; //from anyone! struct sockaddr s_client; socklen_t s_client_size = sizeof( struct sockaddr ); int port = PORT; int recvsize; char reuse = 1;//SO_REUSEADDR int xDelta=0, yDelta=0; //network stuff //configure socket if ( ( s = socket( PF_INET, SOCK_STREAM, 0 ) ) == -1 ) { perror ( "Failed to create socket :(" ); exit( 2 ); } if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof( reuse ) ) == -1 ) { perror( "Failed to set reuseaddr! Trying to continue..." ); } memset( &s_add, 0, sizeof( struct sockaddr_in ) ); s_add.sin_family = AF_INET; s_add.sin_port = htons( port ); s_add.sin_addr.s_addr = INADDR_ANY; if ( bind( s, (struct sockaddr * )&s_add, sizeof( struct sockaddr_in ) ) == -1 ) { perror( "Failed to bind socket" ); exit( 2 ); } if( listen( s , 1 ) ) { perror( "Can't listen!" ); exit( 2 ); } while( 1 ) { s_accept = accept( s, &s_client, &s_client_size ); if ( s_accept == -1 ) { perror( "failed to accept!" ); return -1; } while( 1 ) { recvsize = recv( s_accept, pEvent, sizeof( InputEvent ), MSG_WAITALL ); if ( recvsize == sizeof( InputEvent ) )//got data { switch( pEvent->event_t ) { case EVENT_TYPE_MOUSE_MOVE: if(debug) printf("Mouse move\n"); GetGlobalMouse( &pt );//get cursor pos //update x/y newloc.x = pt.h + pEvent->move_info.dx * 2; newloc.y = pt.v + pEvent->move_info.dy * 2; CGDisplayCount displayCount = 0; //check if we've crossed outside the x bounds CGDirectDisplayID tempDisplayID; CGGetDisplaysWithPoint ( newloc, 1, &tempDisplayID, &displayCount); if (displayCount != 0) { currentDisplayID = tempDisplayID; } displayRect = CGDisplayBounds(currentDisplayID); if (newloc.x < displayRect.origin.x) { newloc.x = displayRect.origin.x; } else if (newloc.x > displayRect.origin.x + displayRect.size.width - 1) { newloc.x = displayRect.origin.x + displayRect.size.width - 1; } if (newloc.y < displayRect.origin.y) { newloc.y = displayRect.origin.y; } else if (newloc.y > displayRect.origin.y + displayRect.size.height - 1) { newloc.y = displayRect.origin.y + displayRect.size.height - 1; } if(debug) { printf("Current mouse location: {%d,%d}\n", pt.h, pt.v); printf("newloc: {%f,%f}\n", newloc.x, newloc.y); printf("Screen size: {%f,%f}\n", currentDisplaySize.width, currentDisplaySize.height); fflush( stdout ); } //CGPostMouseEvent( newloc, true /*yes move there*/, 0 , false); eventRef = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, newloc, kCGMouseButtonCenter); CGEventSetType(eventRef, kCGEventMouseMoved); // Apple bug... need to set the type manually CGEventPost(kCGSessionEventTap, eventRef); CFRelease(eventRef); break; case EVENT_TYPE_MOUSE_SCROLL_MOVE: if(debug) { printf( "Scrolling\n" ); fflush( stdout ); } xDelta += pEvent->move_info.dx; yDelta += pEvent->move_info.dy; //TODO: mac osx has a api to get the exact scroll amount, look into that if ( ( yDelta/SCROLL_AMT != 0 ) || ( xDelta/SCROLL_AMT != 0 ) ) {//if any clicks need to be made... //send the number of whole clicks.... CGPostScrollWheelEvent( 2, -yDelta/SCROLL_AMT, -xDelta/SCROLL_AMT ); //remove them from our counter xDelta %=SCROLL_AMT; yDelta %=SCROLL_AMT; } break; case EVENT_TYPE_MOUSE_DOWN: if(debug) printf("Mouse down\n"); GetGlobalMouse( &pt );//get cursor pos //update x/y if(debug) { printf("Current mouse location: {%d,%d}", pt.h, pt.v); fflush( stdout ); } //CGPostMouseEvent( newloc, true /*yes move there*/, 0 , false); newloc.x = pt.h; newloc.y = pt.v; eventRef = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown , newloc, kCGMouseButtonCenter); CGEventSetType(eventRef, kCGEventLeftMouseDown); // Apple bug... need to set the type manually CGEventPost(kCGSessionEventTap, eventRef); CFRelease(eventRef); break; case EVENT_TYPE_MOUSE_UP: if(debug) printf("Mouse up\n"); GetGlobalMouse( &pt );//get cursor pos //update x/y if(debug) { printf("Current mouse location: {%d,%d}", pt.h, pt.v); fflush( stdout ); } //CGPostMouseEvent( newloc, true /*yes move there*/, 0 , false); newloc.x = pt.h; newloc.y = pt.v; eventRef = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp , newloc, kCGMouseButtonCenter); CGEventSetType(eventRef, kCGEventLeftMouseUp); // Apple bug... need to set the type manually CGEventPost(kCGSessionEventTap, eventRef); CFRelease(eventRef); break; /* TODO: * so far this will only work for basic keycodes, and will probably fail on anything non-ascii, * and that has yet to be tested, etc. Right now I'm mostly interested in having the events properly * generated and support ascii keys. We will handle the rest later. */ case EVENT_TYPE_KEY_DOWN: if ( debug ) { printf( "Key down: %c\n", pEvent->key_info.keycode ); fflush( stdout ); } eventRef = CGEventCreateKeyboardEvent( NULL, (CGKeyCode)( pEvent->key_info.keycode - 1 ), true ); CGEventSetType( eventRef, kCGEventKeyDown ); CGEventPost( kCGSessionEventTap, eventRef ); CFRelease( eventRef ); break; case EVENT_TYPE_KEY_UP: if ( debug ) { printf( "Key Up: %c\n", pEvent->key_info.keycode ); fflush( stdout ); } eventRef = CGEventCreateKeyboardEvent( NULL, (CGKeyCode)( pEvent->key_info.keycode - 1 ), false ); CGEventSetType( eventRef, kCGEventKeyUp ); CGEventPost( kCGSessionEventTap, eventRef ); CFRelease( eventRef ); break; default: fprintf( stderr, "unknown message type: %d\n", pEvent->event_t ); fflush( stdout ); break; } //flush events, if needed in macosx } else if ( recvsize > 0 ) { fprintf( stderr, "partial recv!" ); } else if ( recvsize == 0 ) { //connection terminated close( s_accept ); break; //exit this while loop, wait for another connection } else { perror( "error in recv" ); } } } //shouldn't get here! return 0; }