/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to reflect changing modifier flags (alt, control, meta, etc) */ void DarwinUpdateModKeys(int flags) { DarwinUpdateModifiers( KeyRelease, darwin_all_modifier_flags & ~flags & darwin_x11_modifier_mask); DarwinUpdateModifiers( KeyPress, ~darwin_all_modifier_flags & flags & darwin_x11_modifier_mask); darwin_all_modifier_flags = flags; }
/* * 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( xEvent *xe, // event template with time and // mouse position filled in int whichButton, // mouse button to be pressed int modifierMask) // modifiers used for the fake click { // first fool X into forgetting about the keys DarwinUpdateModifiers(xe, KeyRelease, modifierMask); // push the mouse button xe->u.u.type = ButtonPress; xe->u.u.detail = whichButton; (*darwinEventQueue.pPtr->processInputProc) (xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1); }
/* * 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 static int darwinFakeMouseButtonDown = 0; static int darwinFakeMouseButtonMask = 0; // 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; /* * 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: 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); } } /* fall through */ 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) { // Mimic multi-button mouse with modifier-clicks // If both sets of modifiers are pressed, // button 2 is clicked. 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) { // 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. xe.u.u.detail = darwinFakeMouseButtonDown; darwinFakeMouseButtonDown = 0; (*darwinEventQueue.pPtr->processInputProc) (&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1); // Bring modifiers back up to date 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: { // Update modifier state. // Any amount of modifiers may have changed. 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)) { // IOKit and X have different numbering for the // middle and right mouse buttons. 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: // Check for mode specific event DarwinModeProcessEvent(&xe); } } } miPointerUpdate(); }