Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/ghost/intern/GHOST_WindowCocoa.mm')
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm751
1 files changed, 751 insertions, 0 deletions
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
new file mode 100644
index 00000000000..092443814b0
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -0,0 +1,751 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/**
+ * Copyright (C) 2001 NaN Technologies B.V.
+ * @author Maarten Gribnau
+ * @date May 10, 2001
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Carbon/Carbon.h>
+
+#include "GHOST_WindowCocoa.h"
+#include "GHOST_Debug.h"
+
+AGLContext GHOST_WindowCocoa::s_firstaglCtx = NULL;
+#ifdef GHOST_DRAW_CARBON_GUTTER
+const GHOST_TInt32 GHOST_WindowCocoa::s_sizeRectSize = 16;
+#endif //GHOST_DRAW_CARBON_GUTTER
+
+static const GLint sPreferredFormatWindow[8] = {
+AGL_RGBA,
+AGL_DOUBLEBUFFER,
+AGL_ACCELERATED,
+AGL_DEPTH_SIZE, 32,
+AGL_NONE,
+};
+
+static const GLint sPreferredFormatFullScreen[9] = {
+AGL_RGBA,
+AGL_DOUBLEBUFFER,
+AGL_ACCELERATED,
+AGL_FULLSCREEN,
+AGL_DEPTH_SIZE, 32,
+AGL_NONE,
+};
+
+
+
+WindowRef ugly_hack=NULL;
+
+const EventTypeSpec kWEvents[] = {
+ { kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */
+};
+
+static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) {
+ WindowRef mywindow;
+ GHOST_WindowCocoa *ghost_window;
+ OSStatus err;
+ int theState;
+
+ if (::GetEventKind(event) == kEventWindowZoom) {
+ err = ::GetEventParameter (event,kEventParamDirectObject,typeWindowRef,NULL,sizeof(mywindow),NULL, &mywindow);
+ ghost_window = (GHOST_WindowCocoa *) GetWRefCon(mywindow);
+ theState = ghost_window->getMac_windowState();
+ if (theState == 1)
+ ghost_window->setMac_windowState(2);
+ else if (theState == 2)
+ ghost_window->setMac_windowState(1);
+
+ }
+ return eventNotHandledErr;
+}
+
+GHOST_WindowCocoa::GHOST_WindowCocoa(
+ const STR_String& title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ const bool stereoVisual
+) :
+ GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone),
+ m_windowRef(0),
+ m_grafPtr(0),
+ m_aglCtx(0),
+ m_customCursor(0),
+ m_fullScreenDirty(false)
+{
+ Str255 title255;
+ OSStatus err;
+
+ //fprintf(stderr," main screen top %i left %i height %i width %i\n", top, left, height, width);
+
+ if (state >= GHOST_kWindowState8Normal ) {
+ if(state == GHOST_kWindowState8Normal) state= GHOST_kWindowStateNormal;
+ else if(state == GHOST_kWindowState8Maximized) state= GHOST_kWindowStateMaximized;
+ else if(state == GHOST_kWindowState8Minimized) state= GHOST_kWindowStateMinimized;
+ else if(state == GHOST_kWindowState8FullScreen) state= GHOST_kWindowStateFullScreen;
+
+ // state = state - 8; this was the simple version of above code, doesnt work in gcc 4.0
+
+ setMac_windowState(1);
+ } else
+ setMac_windowState(0);
+
+ if (state != GHOST_kWindowStateFullScreen) {
+ Rect bnds = { top, left, top+height, left+width };
+ // Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); /*unused*/
+ gen2mac(title, title255);
+
+ err = ::CreateNewWindow( kDocumentWindowClass,
+ kWindowStandardDocumentAttributes+kWindowLiveResizeAttribute,
+ &bnds,
+ &m_windowRef);
+
+ if ( err != noErr) {
+ fprintf(stderr," error creating window %i \n",err);
+ } else {
+
+ ::SetWRefCon(m_windowRef,(SInt32)this);
+ setTitle(title);
+ err = InstallWindowEventHandler (m_windowRef, myWEventHandlerProc, GetEventTypeCount(kWEvents), kWEvents,NULL,NULL);
+ if ( err != noErr) {
+ fprintf(stderr," error creating handler %i \n",err);
+ } else {
+ // ::TransitionWindow (m_windowRef,kWindowZoomTransitionEffect,kWindowShowTransitionAction,NULL);
+ ::ShowWindow(m_windowRef);
+ ::MoveWindow (m_windowRef, left, top,true);
+
+ }
+ }
+ if (m_windowRef) {
+ m_grafPtr = ::GetWindowPort(m_windowRef);
+ setDrawingContextType(type);
+ updateDrawingContext();
+ activateDrawingContext();
+ }
+ if(ugly_hack==NULL) {
+ ugly_hack= m_windowRef;
+ // when started from commandline, window remains in the back... also for play anim
+ ProcessSerialNumber psn;
+ GetCurrentProcess(&psn);
+ SetFrontProcess(&psn);
+ }
+ }
+ else {
+ /*
+ Rect bnds = { top, left, top+height, left+width };
+ gen2mac("", title255);
+ m_windowRef = ::NewCWindow(
+ nil, // Storage
+ &bnds, // Bounding rectangle of the window
+ title255, // Title of the window
+ 0, // Window initially visible
+ plainDBox, // procID
+ (WindowRef)-1L, // Put window before all other windows
+ 0, // Window has minimize box
+ (SInt32)this); // Store a pointer to the class in the refCon
+ */
+ //GHOST_PRINT("GHOST_WindowCocoa::GHOST_WindowCocoa(): creating full-screen OpenGL context\n");
+ setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);;installDrawingContext(GHOST_kDrawingContextTypeOpenGL);
+ updateDrawingContext();
+ activateDrawingContext();
+
+ m_tablet.Active = GHOST_kTabletModeNone;
+ }
+}
+
+
+GHOST_WindowCocoa::~GHOST_WindowCocoa()
+{
+ if (m_customCursor) delete m_customCursor;
+
+ if(ugly_hack==m_windowRef) ugly_hack= NULL;
+
+ // printf("GHOST_WindowCocoa::~GHOST_WindowCocoa(): removing drawing context\n");
+ if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone);
+ if (m_windowRef) {
+ ::DisposeWindow(m_windowRef);
+ m_windowRef = 0;
+ }
+}
+
+bool GHOST_WindowCocoa::getValid() const
+{
+ bool valid;
+ if (!m_fullScreen) {
+ valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef);
+ }
+ else {
+ valid = true;
+ }
+ return valid;
+}
+
+
+void GHOST_WindowCocoa::setTitle(const STR_String& title)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid")
+ Str255 title255;
+ gen2mac(title, title255);
+ ::SetWTitle(m_windowRef, title255);
+}
+
+
+void GHOST_WindowCocoa::getTitle(STR_String& title) const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid")
+ Str255 title255;
+ ::GetWTitle(m_windowRef, title255);
+ mac2gen(title255, title);
+}
+
+
+void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const
+{
+ OSStatus success;
+ Rect rect;
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid")
+ success = ::GetWindowBounds(m_windowRef, kWindowStructureRgn, &rect);
+ bounds.m_b = rect.bottom;
+ bounds.m_l = rect.left;
+ bounds.m_r = rect.right;
+ bounds.m_t = rect.top;
+}
+
+
+void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
+{
+ Rect rect;
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid")
+ //::GetPortBounds(m_grafPtr, &rect);
+ ::GetWindowBounds(m_windowRef, kWindowContentRgn, &rect);
+
+ bounds.m_b = rect.bottom;
+ bounds.m_l = rect.left;
+ bounds.m_r = rect.right;
+ bounds.m_t = rect.top;
+
+ // Subtract gutter height from bottom
+#ifdef GHOST_DRAW_CARBON_GUTTER
+ if ((bounds.m_b - bounds.m_t) > s_sizeRectSize)
+ {
+ bounds.m_b -= s_sizeRectSize;
+ }
+ else
+ {
+ bounds.m_t = bounds.m_b;
+ }
+#endif //GHOST_DRAW_CARBON_GUTTER
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid")
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+ if (((GHOST_TUns32)cBnds.getWidth()) != width) {
+ ::SizeWindow(m_windowRef, width, cBnds.getHeight(), true);
+ }
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid")
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+#ifdef GHOST_DRAW_CARBON_GUTTER
+ if (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize) {
+ ::SizeWindow(m_windowRef, cBnds.getWidth(), height+s_sizeRectSize, true);
+ }
+#else //GHOST_DRAW_CARBON_GUTTER
+ if (((GHOST_TUns32)cBnds.getHeight()) != height) {
+ ::SizeWindow(m_windowRef, cBnds.getWidth(), height, true);
+ }
+#endif //GHOST_DRAW_CARBON_GUTTER
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid")
+ GHOST_Rect cBnds, wBnds;
+ getClientBounds(cBnds);
+#ifdef GHOST_DRAW_CARBON_GUTTER
+ if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
+ (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize)) {
+ ::SizeWindow(m_windowRef, width, height+s_sizeRectSize, true);
+ }
+#else //GHOST_DRAW_CARBON_GUTTER
+ if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
+ (((GHOST_TUns32)cBnds.getHeight()) != height)) {
+ ::SizeWindow(m_windowRef, width, height, true);
+ }
+#endif //GHOST_DRAW_CARBON_GUTTER
+ return GHOST_kSuccess;
+}
+
+
+GHOST_TWindowState GHOST_WindowCocoa::getState() const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid")
+ GHOST_TWindowState state;
+ if (::IsWindowVisible(m_windowRef) == false) {
+ state = GHOST_kWindowStateMinimized;
+ }
+ else if (::IsWindowInStandardState(m_windowRef, nil, nil)) {
+ state = GHOST_kWindowStateMaximized;
+ }
+ else {
+ state = GHOST_kWindowStateNormal;
+ }
+ return state;
+}
+
+
+void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid")
+ Point point;
+ point.h = inX;
+ point.v = inY;
+ GrafPtr oldPort;
+ ::GetPort(&oldPort);
+ ::SetPort(m_grafPtr);
+ ::GlobalToLocal(&point);
+ ::SetPort(oldPort);
+ outX = point.h;
+ outY = point.v;
+}
+
+
+void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid")
+ Point point;
+ point.h = inX;
+ point.v = inY;
+ GrafPtr oldPort;
+ ::GetPort(&oldPort);
+ ::SetPort(m_grafPtr);
+ ::LocalToGlobal(&point);
+ ::SetPort(oldPort);
+ outX = point.h;
+ outY = point.v;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid")
+ switch (state) {
+ case GHOST_kWindowStateMinimized:
+ ::HideWindow(m_windowRef);
+ break;
+ case GHOST_kWindowStateMaximized:
+ case GHOST_kWindowStateNormal:
+ default:
+ ::ShowWindow(m_windowRef);
+ break;
+ }
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges)
+{
+ if (isUnsavedChanges) {
+ SetWindowModified(m_windowRef, 1);
+ } else {
+ SetWindowModified(m_windowRef, 0);
+ }
+
+ return GHOST_Window::setModifiedState(isUnsavedChanges);
+}
+
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid")
+ if (order == GHOST_kWindowOrderTop) {
+ //::BringToFront(m_windowRef); is wrong, front window should be active for input too
+ ::SelectWindow(m_windowRef);
+ }
+ else {
+ /* doesnt work if you do this with a mouseclick */
+ ::SendBehind(m_windowRef, nil);
+ }
+ return GHOST_kSuccess;
+}
+
+/*#define WAIT_FOR_VSYNC 1*/
+#ifdef WAIT_FOR_VSYNC
+#include <OpenGL/OpenGL.h>
+#endif
+
+GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()
+{
+#ifdef WAIT_FOR_VSYNC
+/* wait for vsync, to avoid tearing artifacts */
+long VBL = 1;
+CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL);
+#endif
+
+ GHOST_TSuccess succeeded = GHOST_kSuccess;
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_aglCtx) {
+ ::aglSwapBuffers(m_aglCtx);
+ }
+ else {
+ succeeded = GHOST_kFailure;
+ }
+ }
+ return succeeded;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()
+{
+ GHOST_TSuccess succeeded = GHOST_kSuccess;
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_aglCtx) {
+ ::aglUpdateContext(m_aglCtx);
+ }
+ else {
+ succeeded = GHOST_kFailure;
+ }
+ }
+ return succeeded;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
+{
+ GHOST_TSuccess succeeded = GHOST_kSuccess;
+ if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
+ if (m_aglCtx) {
+ ::aglSetCurrentContext(m_aglCtx);
+#ifdef GHOST_DRAW_CARBON_GUTTER
+ // Restrict drawing to non-gutter area
+ ::aglEnable(m_aglCtx, AGL_BUFFER_RECT);
+ GHOST_Rect bnds;
+ getClientBounds(bnds);
+ GLint b[4] =
+ {
+ bnds.m_l,
+ bnds.m_t+s_sizeRectSize,
+ bnds.m_r-bnds.m_l,
+ bnds.m_b-bnds.m_t
+ };
+ GLboolean result = ::aglSetInteger(m_aglCtx, AGL_BUFFER_RECT, b);
+#endif //GHOST_DRAW_CARBON_GUTTER
+ }
+ else {
+ succeeded = GHOST_kFailure;
+ }
+ }
+ return succeeded;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ switch (type) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ {
+ if (!getValid()) break;
+
+ AGLPixelFormat pixelFormat;
+ if (!m_fullScreen) {
+ pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatWindow);
+ m_aglCtx = ::aglCreateContext(pixelFormat, s_firstaglCtx);
+ if (!m_aglCtx) break;
+ if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx;
+ success = ::aglSetDrawable(m_aglCtx, m_grafPtr) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ //GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL\n");
+GDHandle device=::GetMainDevice();pixelFormat=::aglChoosePixelFormat(&device,1,sPreferredFormatFullScreen);
+ m_aglCtx = ::aglCreateContext(pixelFormat, 0);
+ if (!m_aglCtx) break;
+ if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx;
+ //GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): created OpenGL context\n");
+ //::CGGetActiveDisplayList(0, NULL, &m_numDisplays)
+ success = ::aglSetFullScreen(m_aglCtx, m_fullScreenWidth, m_fullScreenHeight, 75, 0) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ /*
+ if (success == GHOST_kSuccess) {
+ GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL succeeded\n");
+ }
+ else {
+ GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL failed\n");
+ }
+ */
+ }
+ ::aglDestroyPixelFormat(pixelFormat);
+ }
+ break;
+
+ case GHOST_kDrawingContextTypeNone:
+ success = GHOST_kSuccess;
+ break;
+
+ default:
+ break;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext()
+{
+ GHOST_TSuccess success = GHOST_kFailure;
+ switch (m_drawingContextType) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ if (m_aglCtx) {
+ aglSetCurrentContext(NULL);
+ aglSetDrawable(m_aglCtx, NULL);
+ //aglDestroyContext(m_aglCtx);
+ if (s_firstaglCtx == m_aglCtx) s_firstaglCtx = NULL;
+ success = ::aglDestroyContext(m_aglCtx) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
+ m_aglCtx = 0;
+ }
+ break;
+ case GHOST_kDrawingContextTypeNone:
+ success = GHOST_kSuccess;
+ break;
+ default:
+ break;
+ }
+ return success;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::invalidate()
+{
+ GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid")
+ if (!m_fullScreen) {
+ Rect rect;
+ ::GetPortBounds(m_grafPtr, &rect);
+ ::InvalWindowRect(m_windowRef, &rect);
+ }
+ else {
+ //EventRef event;
+ //OSStatus status = ::CreateEvent(NULL, kEventClassWindow, kEventWindowUpdate, 0, 0, &event);
+ //GHOST_PRINT("GHOST_WindowCocoa::invalidate(): created event " << status << " \n");
+ //status = ::SetEventParameter(event, kEventParamDirectObject, typeWindowRef, sizeof(WindowRef), this);
+ //GHOST_PRINT("GHOST_WindowCocoa::invalidate(): set event parameter " << status << " \n");
+ //status = ::PostEventToQueue(::GetMainEventQueue(), event, kEventPriorityStandard);
+ //status = ::SendEventToEventTarget(event, ::GetApplicationEventTarget());
+ //GHOST_PRINT("GHOST_WindowCocoa::invalidate(): added event to queue " << status << " \n");
+ m_fullScreenDirty = true;
+ }
+ return GHOST_kSuccess;
+}
+
+
+void GHOST_WindowCocoa::gen2mac(const STR_String& in, Str255 out) const
+{
+ STR_String tempStr = in;
+ int num = tempStr.Length();
+ if (num > 255) num = 255;
+ ::memcpy(out+1, tempStr.Ptr(), num);
+ out[0] = num;
+}
+
+
+void GHOST_WindowCocoa::mac2gen(const Str255 in, STR_String& out) const
+{
+ char tmp[256];
+ ::memcpy(tmp, in+1, in[0]);
+ tmp[in[0]] = '\0';
+ out = tmp;
+}
+
+void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
+{
+ static bool systemCursorVisible = true;
+
+ if (visible != systemCursorVisible) {
+ if (visible) {
+ ::ShowCursor();
+ systemCursorVisible = true;
+ }
+ else {
+ ::HideCursor();
+ systemCursorVisible = false;
+ }
+ }
+
+ if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
+ ::SetCursor( m_customCursor );
+ } else {
+ int carbon_cursor;
+
+#define GCMAP(ghostCursor, carbonCursor) case ghostCursor: carbon_cursor = carbonCursor; break
+ switch (cursor) {
+ default:
+ GCMAP( GHOST_kStandardCursorDefault, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorRightArrow, kThemeAliasArrowCursor);
+ GCMAP( GHOST_kStandardCursorLeftArrow, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorInfo, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorDestroy, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorHelp, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorCycle, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorSpray, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorWait, kThemeWatchCursor);
+ GCMAP( GHOST_kStandardCursorText, kThemeIBeamCursor);
+ GCMAP( GHOST_kStandardCursorCrosshair, kThemeCrossCursor);
+ GCMAP( GHOST_kStandardCursorUpDown, kThemeClosedHandCursor);
+ GCMAP( GHOST_kStandardCursorLeftRight, kThemeClosedHandCursor);
+ GCMAP( GHOST_kStandardCursorTopSide, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorBottomSide, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorLeftSide, kThemeResizeLeftCursor);
+ GCMAP( GHOST_kStandardCursorRightSide, kThemeResizeRightCursor);
+ GCMAP( GHOST_kStandardCursorTopLeftCorner, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorTopRightCorner, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorBottomRightCorner, kThemeArrowCursor);
+ GCMAP( GHOST_kStandardCursorBottomLeftCorner, kThemeArrowCursor);
+ };
+#undef GCMAP
+
+ ::SetThemeCursor(carbon_cursor);
+ }
+}
+
+
+bool GHOST_WindowCocoa::getFullScreenDirty()
+{
+ return m_fullScreen && m_fullScreenDirty;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
+{
+ if (::FrontWindow() == m_windowRef) {
+ loadCursor(visible, getCursorShape());
+ }
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
+{
+ if (m_customCursor) {
+ delete m_customCursor;
+ m_customCursor = 0;
+ }
+
+ if (::FrontWindow() == m_windowRef) {
+ loadCursor(getCursorVisibility(), shape);
+ }
+
+ return GHOST_kSuccess;
+}
+
+#if 0
+/** Reverse the bits in a GHOST_TUns8 */
+static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
+{
+ ch= ((ch>>1)&0x55) | ((ch<<1)&0xAA);
+ ch= ((ch>>2)&0x33) | ((ch<<2)&0xCC);
+ ch= ((ch>>4)&0x0F) | ((ch<<4)&0xF0);
+ return ch;
+}
+#endif
+
+
+/** Reverse the bits in a GHOST_TUns16 */
+static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
+{
+ shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA);
+ shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC);
+ shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0);
+ shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00);
+ return shrt;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
+ int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color)
+{
+ int y;
+
+ if (m_customCursor) {
+ delete m_customCursor;
+ m_customCursor = 0;
+ }
+
+ m_customCursor = new Cursor;
+ if (!m_customCursor) return GHOST_kFailure;
+
+ for (y=0; y<16; y++) {
+#if !defined(__LITTLE_ENDIAN__)
+ m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
+ m_customCursor->mask[y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8));
+#else
+ m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
+ m_customCursor->mask[y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8));
+#endif
+
+ }
+
+ m_customCursor->hotSpot.h = hotX;
+ m_customCursor->hotSpot.v = hotY;
+
+ if (::FrontWindow() == m_windowRef) {
+ loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
+ }
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
+ GHOST_TUns8 mask[16][2], int hotX, int hotY)
+{
+ return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*) mask, 16, 16, hotX, hotY, 0, 1);
+}
+
+
+void GHOST_WindowCocoa::setMac_windowState(short value)
+{
+ mac_windowState = value;
+}
+
+short GHOST_WindowCocoa::getMac_windowState()
+{
+ return mac_windowState;
+}