void CSecondaryScreen::enter(SInt32 x, SInt32 y, KeyModifierMask mask) { CLock lock(&m_mutex); assert(m_active == false); LOG((CLOG_INFO "entering screen at %d,%d mask=%04x", x, y, mask)); getScreen()->syncDesktop(); // now active m_active = true; // subclass hook onPreEnter(); // update our keyboard state to reflect the local state updateKeys(); // remember toggle key state m_toggleKeys = getToggleState(); // toggle modifiers that don't match the desired state setToggleState(mask); // warp to requested location warpCursor(x, y); // show mouse hideWindow(); // subclass hook onPostEnter(); }
bool COSXScreen::onMouseMove(SInt32 mx, SInt32 my) { LOG((CLOG_DEBUG2 "mouse move %+d,%+d", mx, my)); SInt32 x = mx - m_xCursor; SInt32 y = my - m_yCursor; if ((x == 0 && y == 0) || (mx == m_xCenter && mx == m_yCenter)) { return true; } // save position to compute delta of next motion m_xCursor = mx; m_yCursor = my; if (m_isOnScreen) { // motion on primary screen sendEvent(m_events->forIPrimaryScreen().motionOnPrimary(), CMotionInfo::alloc(m_xCursor, m_yCursor)); } else { // motion on secondary screen. warp mouse back to // center. warpCursor(m_xCenter, m_yCenter); // examine the motion. if it's about the distance // from the center of the screen to an edge then // it's probably a bogus motion that we want to // ignore (see warpCursorNoFlush() for a further // description). static SInt32 bogusZoneSize = 10; if (-x + bogusZoneSize > m_xCenter - m_x || x + bogusZoneSize > m_x + m_w - m_xCenter || -y + bogusZoneSize > m_yCenter - m_y || y + bogusZoneSize > m_y + m_h - m_yCenter) { LOG((CLOG_DEBUG "dropped bogus motion %+d,%+d", x, y)); } else { // send motion sendEvent(m_events->forIPrimaryScreen().motionOnSecondary(), CMotionInfo::alloc(x, y)); } } return true; }
bool COSXScreen::leave() { if (m_isPrimary) { // warp to center warpCursor(m_xCenter, m_yCenter); // capture events HideWindow(m_hiddenWindow); ShowWindow(m_userInputWindow); RepositionWindow(m_userInputWindow, m_userInputWindow, kWindowCenterOnMainScreen); SetUserFocusWindow(m_userInputWindow); // The OS will coalesce some events if they are similar enough in a // short period of time this is bad for us since we need every event // to send it over to other machines. So disable it. SetMouseCoalescingEnabled(false, NULL); CGSetLocalEventsSuppressionInterval(0.0001); // disable global hotkeys //setGlobalHotKeysEnabled(false); } else { // hide cursor if (!m_cursorHidden) { // CGDisplayHideCursor(m_displayID); m_cursorHidden = true; } // warp the mouse to the cursor center fakeMouseMove(m_xCenter, m_yCenter); // FIXME -- prepare to show cursor if it moves // take keyboard focus // FIXME } // now off screen m_isOnScreen = false; return true; }
bool COSXScreen::onDisplayChange() { // screen resolution may have changed. save old shape. SInt32 xOld = m_x, yOld = m_y, wOld = m_w, hOld = m_h; // update shape updateScreenShape(); // do nothing if resolution hasn't changed if (xOld != m_x || yOld != m_y || wOld != m_w || hOld != m_h) { if (m_isPrimary) { // warp mouse to center if off screen if (!m_isOnScreen) { warpCursor(m_xCenter, m_yCenter); } } // send new screen info sendEvent(m_events->forIPrimaryScreen().shapeChanged()); } return true; }
bool COSXScreen::leave() { // hide cursor if (!m_cursorHidden) { hideCursor(); m_cursorHidden = true; } if (m_isPrimary) { // warp to center warpCursor(m_xCenter, m_yCenter); // This used to be necessary to get smooth mouse motion on other screens, // but now is just to avoid a hesitating cursor when transitioning to // the primary (this) screen. CGSetLocalEventsSuppressionInterval(0.0001); // disable global hotkeys //setGlobalHotKeysEnabled(false); } else { // warp the mouse to the cursor center fakeMouseMove(m_xCenter, m_yCenter); // FIXME -- prepare to show cursor if it moves // take keyboard focus // FIXME } // now off screen m_isOnScreen = false; return true; }
void CXWindowsPrimaryScreen::warpCursorToCenter() { warpCursor(m_xCenter, m_yCenter); }