- fix#19592 : implemented updated continuous grab feature (fixing compilation issues)
- fix some 10.6 & 64bit warnings
This commit is contained in:
Damien Plisson
2009-10-19 10:49:45 +00:00
parent 55249e255a
commit b18eeed225
5 changed files with 146 additions and 196 deletions

View File

@@ -228,34 +228,7 @@ protected:
* @return Indication whether the event was handled.
*/
GHOST_TSuccess handleKeyEvent(void *eventPtr);
/**
* Handles all basic Mac application stuff for a mouse down event.
* @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
* @return Indication whether the event was handled.
*/
// bool handleMouseDown(void *eventPtr);
/**
* Handles a Mac menu command.
* @param menuResult A Mac menu/item identifier.
* @return Indication whether the event was handled.
*/
// bool handleMenuCommand(GHOST_TInt32 menuResult);
/* callback for blender generated events */
// static OSStatus blendEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData);
/**
* Callback for Mac Timer tasks that expire.
* @param tmTask Pointer to the timer task that expired.
*/
//static void s_timerCallback(TMTaskPtr tmTask);
/** Event handler reference. */
//EventHandlerRef m_handler;
/** Start time at initialization. */
GHOST_TUns64 m_start_time;
@@ -266,7 +239,12 @@ protected:
GHOST_TUns32 m_modifierMask;
/** Ignores window size messages (when window is dragged). */
bool m_ignoreWindowSizedMessages;
bool m_ignoreWindowSizedMessages;
/** Stores the mouse cursor delta due to setting a new cursor position
* Needed because cocoa event delta cursor move takes setCursorPosition changes too.
*/
GHOST_TInt32 m_cursorDelta_x, m_cursorDelta_y;
};
#endif // _GHOST_SYSTEM_COCOA_H_

View File

@@ -565,6 +565,8 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
{
m_modifierMask =0;
m_pressedMouseButtons =0;
m_cursorDelta_x=0;
m_cursorDelta_y=0;
m_displayManager = new GHOST_DisplayManagerCocoa ();
GHOST_ASSERT(m_displayManager, "GHOST_SystemCocoa::GHOST_SystemCocoa(): m_displayManager==0\n");
m_displayManager->initialize();
@@ -873,15 +875,6 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
if (timerMgr->fireTimers(getMilliSeconds())) {
anyProcessed = true;
}
if (getFullScreen()) {
// Check if the full-screen window is dirty
GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
if (((GHOST_WindowCarbon*)window)->getFullScreenDirty()) {
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
anyProcessed = true;
}
}*/
do {
@@ -999,6 +992,12 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
{
GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow();
//Discard quit event if we are in cursor grab sequence
if ((window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal))
return GHOST_kExitCancel;
//Check open windows if some changes are not saved
if (m_windowManager->getAnyModifiedState())
{
@@ -1129,27 +1128,78 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
//No tablet event included : do nothing
break;
}
case NSMouseMoved:
{
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]; //Strange Apple implementation (inverted coordinates for the 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));
window->setCursorWarpAccum(0, 0); //Mouse motion occured between two cursor warps, so we can reset the delta counter
switch (window->getCursorGrabMode()) {
case GHOST_kGrabHide: //Cursor hidden grab operation : no cursor move
{
GHOST_TInt32 x_warp, y_warp, x_accum, y_accum;
window->getCursorGrabInitPos(x_warp, y_warp);
window->getCursorGrabAccum(x_accum, y_accum);
x_accum += [event deltaX];
y_accum += -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ...
window->setCursorGrabAccum(x_accum, y_accum);
pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum));
}
break;
case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries
{
NSPoint mousePos = [event locationInWindow];
GHOST_TInt32 x_mouse= mousePos.x;
GHOST_TInt32 y_mouse= mousePos.y;
GHOST_TInt32 x_accum, y_accum, x_cur, y_cur;
GHOST_Rect bounds, windowBounds, correctedBounds;
/* fallback to window bounds */
if(window->getCursorGrabBounds(bounds)==GHOST_kFailure)
window->getClientBounds(bounds);
//Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates
window->getClientBounds(windowBounds);
bounds.m_b = (windowBounds.m_b - windowBounds.m_t) - bounds.m_b;
bounds.m_t = (windowBounds.m_b - windowBounds.m_t) - bounds.m_t;
window->screenToClient(bounds.m_l,bounds.m_b, correctedBounds.m_l, correctedBounds.m_t);
window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b);
//Update accumulation counts
window->getCursorGrabAccum(x_accum, y_accum);
x_accum += [event deltaX]-m_cursorDelta_x;
y_accum += -[event deltaY]-m_cursorDelta_y; //Strange Apple implementation (inverted coordinates for the deltaY) ...
window->setCursorGrabAccum(x_accum, y_accum);
//Warp mouse cursor if needed
x_mouse += [event deltaX]-m_cursorDelta_x;
y_mouse += -[event deltaY]-m_cursorDelta_y;
correctedBounds.wrapPoint(x_mouse, y_mouse, 2);
//Compensate for mouse moved event taking cursor position set into account
m_cursorDelta_x = x_mouse-mousePos.x;
m_cursorDelta_y = y_mouse-mousePos.y;
//Set new cursor position
window->clientToScreen(x_mouse, y_mouse, x_cur, y_cur);
setCursorPosition(x_cur, y_cur); /* wrap */
//Post event
window->getCursorGrabInitPos(x_cur, y_cur);
pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, x_cur + x_accum, y_cur + y_accum));
}
break;
default:
{
//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));
m_cursorDelta_x=0;
m_cursorDelta_y=0; //Mouse motion occured between two cursor warps, so we can reset the delta counter
}
break;
}
break;
}
case NSScrollWheel:
{
@@ -1323,74 +1373,3 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const
[pool drain];
}
#pragma mark Carbon stuff to remove
#ifdef WITH_CARBON
OSErr GHOST_SystemCarbon::sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
{
//GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
return noErr;
}
OSErr GHOST_SystemCarbon::sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
{
//GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
AEDescList docs;
SInt32 ndocs;
OSErr err;
err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docs);
if (err != noErr) return err;
err = AECountItems(&docs, &ndocs);
if (err==noErr) {
int i;
for (i=0; i<ndocs; i++) {
FSSpec fss;
AEKeyword kwd;
DescType actType;
Size actSize;
err = AEGetNthPtr(&docs, i+1, typeFSS, &kwd, &actType, &fss, sizeof(fss), &actSize);
if (err!=noErr)
break;
if (i==0) {
FSRef fsref;
if (FSpMakeFSRef(&fss, &fsref)!=noErr)
break;
if (FSRefMakePath(&fsref, (UInt8*) g_firstFileBuf, sizeof(g_firstFileBuf))!=noErr)
break;
g_hasFirstFile = true;
}
}
}
AEDisposeDesc(&docs);
return err;
}
OSErr GHOST_SystemCarbon::sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
{
//GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
return noErr;
}
OSErr GHOST_SystemCarbon::sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
{
GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
sys->pushEvent( new GHOST_Event(sys->getMilliSeconds(), GHOST_kEventQuit, NULL) );
return noErr;
}
#endif

View File

@@ -159,6 +159,7 @@ public:
*/
inline virtual bool getCursorVisibility() const;
inline virtual GHOST_TGrabCursorMode getCursorGrabMode() const;
inline virtual void getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
inline virtual void getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
inline virtual void setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y);
@@ -327,6 +328,12 @@ inline GHOST_TGrabCursorMode GHOST_Window::getCursorGrabMode() const
return m_cursorGrab;
}
inline void GHOST_Window::getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const
{
x = m_cursorGrabInitPos[0];
y = m_cursorGrabInitPos[1];
}
inline void GHOST_Window::getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const
{
x= m_cursorGrabAccumPos[0];

View File

@@ -236,18 +236,12 @@ protected:
*/
virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
/**
* Sets the cursor warp accumulator. Overriden for workaround due to Cocoa next event after cursor set giving delta values non zero
*/
inline virtual bool setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y);
/**
* 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);
virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
/**
* Sets the cursor shape on the window using
* native window system calls.

View File

@@ -50,14 +50,27 @@ static NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
};
#pragma mark Cocoa window delegate object
/* live resize ugly patch
extern "C" {
struct bContext;
typedef struct bContext bContext;
bContext* ghostC;
extern int wm_window_timer(const bContext *C);
extern void wm_window_process_events(const bContext *C);
extern void wm_event_do_handlers(bContext *C);
extern void wm_event_do_notifiers(bContext *C);
extern void wm_draw_update(bContext *C);
};*/
@interface CocoaWindowDelegate : NSObject
#ifdef MAC_OS_X_VERSION_10_6
<NSWindowDelegate>
#endif
{
GHOST_SystemCocoa *systemCocoa;
GHOST_WindowCocoa *associatedWindow;
}
- (void)setSystemAndWindowCocoa:(const GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
- (void)windowWillClose:(NSNotification *)notification;
- (void)windowDidBecomeKey:(NSNotification *)notification;
- (void)windowDidResignKey:(NSNotification *)notification;
@@ -97,7 +110,18 @@ static NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
- (void)windowDidResize:(NSNotification *)notification
{
systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow);
if (![[notification object] inLiveResize]) {
//Send event only once, at end of resize operation (when user has released mouse button)
systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow);
}
/* Live resize ugly patch. Needed because live resize runs in a modal loop, not letting main loop run
if ([[notification object] inLiveResize]) {
systemCocoa->dispatchEvents();
wm_window_timer(ghostC);
wm_event_do_handlers(ghostC);
wm_event_do_notifiers(ghostC);
wm_draw_update(ghostC);
}*/
}
@end
@@ -107,8 +131,6 @@ static NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
{
}
-(BOOL)canBecomeKeyWindow;
@end
@implementation CocoaWindow
@@ -125,7 +147,6 @@ static NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[] =
//We need to subclass it in order to give Cocoa the feeling key events are trapped
@interface CocoaOpenGLView : NSOpenGLView
{
}
@end
@implementation CocoaOpenGLView
@@ -515,6 +536,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
//Make window borderless and enlarge it
[m_window setStyleMask:NSBorderlessWindowMask];
[m_window setFrame:[[m_window screen] frame] display:YES];
[m_window makeFirstResponder:m_openGLView];
#else
//With 10.5, we need to create a new window to change its style to borderless
//Hide menu & dock if needed
@@ -572,6 +594,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
//Make window normal and resize it
[m_window setStyleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
[m_window setFrame:[[m_window screen] visibleFrame] display:YES];
[m_window makeFirstResponder:m_openGLView];
#else
//With 10.5, we need to create a new window to change its style to borderless
//Show menu & dock if needed
@@ -849,73 +872,42 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
}
//Override this method to provide set feature even if not in warp
inline bool GHOST_WindowCocoa::setCursorWarpAccum(GHOST_TInt32 x, GHOST_TInt32 y)
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
{
m_cursorWarpAccumPos[0]= x;
m_cursorWarpAccumPos[1]= y;
GHOST_TSuccess err = GHOST_kSuccess;
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(bool grab, bool warp, bool restore)
{
if (grab)
if (mode != GHOST_kGrabDisable)
{
//No need to perform grab without warp as it is always on in OS X
if(warp) {
if(mode != GHOST_kGrabNormal) {
GHOST_TInt32 x_old,y_old;
m_cursorWarp= true;
m_systemCocoa->getCursorPosition(x_old,y_old);
screenToClient(x_old, y_old, m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
screenToClient(x_old, y_old, m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
//Warp position is stored in client (window base) coordinates
setWindowCursorVisibility(false);
return CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
setCursorGrabAccum(0, 0);
if(mode == GHOST_kGrabHide) {
setWindowCursorVisibility(false);
}
//Dissociate cursor position even for warp mode, to allow mouse acceleration to work even when warping the cursor
err = CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
}
}
else {
if(m_cursorWarp)
{/* are we exiting warp */
if(m_cursorGrab==GHOST_kGrabHide)
{
//No need to set again cursor position, as it has not changed for Cocoa
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_cur, y_cur;
getClientBounds(bounds);
x_new= m_cursorWarpInitPos[0]+m_cursorWarpAccumPos[0];
y_new= m_cursorWarpInitPos[1]+m_cursorWarpAccumPos[1];
if(x_new < 0) x_new = 0;
if(y_new < 0) y_new = 0;
if(x_new > bounds.getWidth()) x_new = bounds.getWidth();
if(y_new > bounds.getHeight()) y_new = bounds.getHeight();
//get/set cursor position works in screen coordinates
clientToScreen(x_new, y_new, x_cur, y_cur);
m_systemCocoa->setCursorPosition(x_cur, y_cur);
//As Cocoa will give as first deltaX,deltaY this change in cursor position, we need to compensate for it
//Issue appearing in case of two transform operations conducted w/o mouse motion in between
x_new=m_cursorWarpAccumPos[0];
y_new=m_cursorWarpAccumPos[1];
setCursorWarpAccum(-x_new, -y_new);
}
else {
GHOST_TInt32 x_new, y_new;
//get/set cursor position works in screen coordinates
clientToScreen(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1], x_new, y_new);
m_systemCocoa->setCursorPosition(x_new, y_new);
setCursorWarpAccum(0, 0);
}
m_cursorWarp= false;
return CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
}
err = CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
setCursorGrabAccum(0, 0);
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
}
return GHOST_kSuccess;
return err;
}
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
@@ -979,7 +971,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
samplesPerPixel:2
hasAlpha:YES
isPlanar:YES
colorSpaceName:NSDeviceBlackColorSpace
colorSpaceName:NSDeviceWhiteColorSpace
bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0))
bitsPerPixel:1];
@@ -989,10 +981,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap
for (y=0; y<nbUns16; y++) {
#if !defined(__LITTLE_ENDIAN__)
cursorBitmap[y] = uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
cursorBitmap[y] = ~uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8));
#else
cursorBitmap[y] = uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
cursorBitmap[y] = ~uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8));
#endif