Implement OS X support for Campbell's new continuous grab feature
This commit is contained in:
Damien Plisson
2009-10-09 14:42:36 +00:00
parent 8c96e2f4d2
commit 8f57b368ca
3 changed files with 79 additions and 5 deletions

View File

@@ -798,7 +798,7 @@ GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt3
{
NSPoint mouseLoc = [NSEvent mouseLocation];
// Convert the coordinates to screen coordinates
// Returns the mouse location in screen coordinates
x = (GHOST_TInt32)mouseLoc.x;
y = (GHOST_TInt32)mouseLoc.y;
return GHOST_kSuccess;
@@ -808,7 +808,10 @@ GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt3
GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const
{
float xf=(float)x, yf=(float)y;
//Quartz Display Services uses the old coordinates (top left origin)
yf = [[NSScreen mainScreen] frame].size.height -yf;
CGAssociateMouseAndMouseCursorPosition(false);
CGWarpMouseCursorPosition(CGPointMake(xf, yf));
CGAssociateMouseAndMouseCursorPosition(true);
@@ -1080,7 +1083,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventT
GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
{
NSEvent *event = (NSEvent *)eventPtr;
GHOST_IWindow* window = m_windowManager->getActiveWindow();
GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow();
if (!window) {
return GHOST_kFailure;
@@ -1141,8 +1144,22 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
}
case NSMouseMoved:
{
NSPoint mousePos = [event locationInWindow];
pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
if(window->getCursorWarp()) {
GHOST_TInt32 x_warp, y_warp, x_accum, y_accum;
window->getCursorWarpPos(x_warp, y_warp);
window->getCursorWarpAccum(x_accum, y_accum);
x_accum += [event deltaX];
y_accum += [event deltaY];
window->setCursorWarpAccum(x_accum, y_accum);
pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum));
}
else { //Normal cursor operation: send mouse position in window
NSPoint mousePos = [event locationInWindow];
pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
}
break;
}

View File

@@ -236,6 +236,13 @@ protected:
*/
virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
/**
* Sets the cursor grab on the window using
* native window system calls.
* @param warp Only used when grab is enabled, hides the mouse and allows gragging outside the screen.
*/
virtual GHOST_TSuccess setWindowCursorGrab(bool grab, bool warp, bool restore);
/**
* Sets the cursor shape on the window using
* native window system calls.

View File

@@ -711,6 +711,56 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(bool grab, bool warp, bool restore)
{
if (grab)
{
if(warp) {
m_systemCocoa->getCursorPosition(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
setCursorWarpAccum(0, 0);
setWindowCursorVisibility(false);
m_cursorWarp= true;
}
return CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
}
else {
if(m_cursorWarp)
{/* are we exiting warp */
setWindowCursorVisibility(true);
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
if(restore) {
GHOST_Rect bounds;
GHOST_TInt32 x_new, y_new, x_rel, y_rel;
getClientBounds(bounds);
printf("\ncursor ungrab with restore");
x_new= m_cursorWarpInitPos[0]+m_cursorWarpAccumPos[0];
y_new= m_cursorWarpInitPos[1]+m_cursorWarpAccumPos[1];
screenToClient(x_new, y_new, x_rel, y_rel);
if(x_rel < 0) x_new = (x_new-x_rel) + 2;
if(y_rel < 0) y_new = (y_new-y_rel) + 2;
if(x_rel > bounds.getWidth()) x_new -= (x_rel-bounds.getWidth()) + 2;
if(y_rel > bounds.getHeight()) y_new -= (y_rel-bounds.getHeight()) + 2;
clientToScreen(x_new, y_new, x_rel, y_rel);
m_systemCocoa->setCursorPosition(x_rel, y_rel);
}
else {
m_systemCocoa->setCursorPosition(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
}
setCursorWarpAccum(0, 0);
m_cursorWarp= false;
}
return CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
}
}
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
{