Blender V2.61 - r43446

GHOST_WindowCarbon.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00040 #include "GHOST_WindowCarbon.h"
00041 #include "GHOST_Debug.h"
00042 
00043 AGLContext GHOST_WindowCarbon::s_firstaglCtx = NULL;
00044 #ifdef GHOST_DRAW_CARBON_GUTTER
00045 const GHOST_TInt32 GHOST_WindowCarbon::s_sizeRectSize = 16;
00046 #endif //GHOST_DRAW_CARBON_GUTTER
00047 
00048 static const GLint sPreferredFormatWindow[10] = {
00049 AGL_RGBA,
00050 AGL_DOUBLEBUFFER,   
00051 AGL_ACCELERATED,
00052 AGL_DEPTH_SIZE,     32,
00053 AGL_NONE,
00054 };
00055 
00056 static const GLint sPreferredFormatFullScreen[11] = {
00057 AGL_RGBA,
00058 AGL_DOUBLEBUFFER,
00059 AGL_ACCELERATED,
00060 AGL_FULLSCREEN,
00061 AGL_DEPTH_SIZE,     32,
00062 AGL_NONE,
00063 };
00064 
00065 
00066 
00067 WindowRef ugly_hack=NULL;
00068 
00069 const EventTypeSpec kWEvents[] = {
00070     { kEventClassWindow, kEventWindowZoom },  /* for new zoom behaviour */ 
00071 };
00072 
00073 static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData)
00074 {
00075     WindowRef mywindow;
00076     GHOST_WindowCarbon *ghost_window;
00077     OSStatus err;
00078     int theState;
00079     
00080     if (::GetEventKind(event) == kEventWindowZoom) {
00081         err =  ::GetEventParameter (event,kEventParamDirectObject,typeWindowRef,NULL,sizeof(mywindow),NULL, &mywindow);
00082         ghost_window = (GHOST_WindowCarbon *) GetWRefCon(mywindow);
00083         theState = ghost_window->getMac_windowState();
00084         if (theState == 1) 
00085             ghost_window->setMac_windowState(2);
00086         else if (theState == 2)
00087             ghost_window->setMac_windowState(1);
00088 
00089     }
00090     return eventNotHandledErr;
00091 }
00092 
00093 GHOST_WindowCarbon::GHOST_WindowCarbon(
00094     const STR_String& title,
00095     GHOST_TInt32 left,
00096     GHOST_TInt32 top,
00097     GHOST_TUns32 width,
00098     GHOST_TUns32 height,
00099     GHOST_TWindowState state,
00100     GHOST_TDrawingContextType type,
00101     const bool stereoVisual,
00102     const GHOST_TUns16 numOfAASamples
00103 ) :
00104     GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone),
00105     m_windowRef(0),
00106     m_grafPtr(0),
00107     m_aglCtx(0),
00108     m_customCursor(0),
00109     m_fullScreenDirty(false)
00110 {
00111     Str255 title255;
00112     OSStatus err;
00113     
00114     //fprintf(stderr," main screen top %i left %i height %i width %i\n", top, left, height, width);
00115     
00116     if (state >= GHOST_kWindowState8Normal ) {
00117         if(state == GHOST_kWindowState8Normal) state= GHOST_kWindowStateNormal;
00118         else if(state == GHOST_kWindowState8Maximized) state= GHOST_kWindowStateMaximized;
00119         else if(state == GHOST_kWindowState8Minimized) state= GHOST_kWindowStateMinimized;
00120         else if(state == GHOST_kWindowState8FullScreen) state= GHOST_kWindowStateFullScreen;
00121         
00122         // state = state - 8;   this was the simple version of above code, doesnt work in gcc 4.0
00123         
00124         setMac_windowState(1);
00125     } else 
00126         setMac_windowState(0);
00127 
00128     if (state != GHOST_kWindowStateFullScreen) {
00129         Rect bnds = { top, left, top+height, left+width };
00130         // Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); /*unused*/
00131         gen2mac(title, title255);
00132         
00133         err =  ::CreateNewWindow( kDocumentWindowClass,
00134                                  kWindowStandardDocumentAttributes+kWindowLiveResizeAttribute,
00135                                  &bnds,
00136                                  &m_windowRef);
00137         
00138         if ( err != noErr) {
00139             fprintf(stderr," error creating window %i \n",(int)err);
00140         } else {
00141             
00142             ::SetWRefCon(m_windowRef,(SInt32)this);
00143             setTitle(title);
00144             err = InstallWindowEventHandler (m_windowRef, myWEventHandlerProc, GetEventTypeCount(kWEvents), kWEvents,NULL,NULL); 
00145             if ( err != noErr) {
00146                 fprintf(stderr," error creating handler %i \n",(int)err);
00147             } else {
00148                 //  ::TransitionWindow (m_windowRef,kWindowZoomTransitionEffect,kWindowShowTransitionAction,NULL);
00149                 ::ShowWindow(m_windowRef);
00150                 ::MoveWindow (m_windowRef, left, top,true);
00151                 
00152             }
00153         }
00154         if (m_windowRef) {
00155             m_grafPtr = ::GetWindowPort(m_windowRef);
00156             setDrawingContextType(type);
00157             updateDrawingContext();
00158             activateDrawingContext();
00159         }
00160         if(ugly_hack==NULL) {
00161             ugly_hack= m_windowRef;
00162             // when started from commandline, window remains in the back... also for play anim
00163             ProcessSerialNumber psn;
00164             GetCurrentProcess(&psn);
00165             SetFrontProcess(&psn);
00166         }
00167     }
00168     else {
00169     /*
00170         Rect bnds = { top, left, top+height, left+width };
00171         gen2mac("", title255);
00172         m_windowRef = ::NewCWindow(
00173             nil,                            // Storage 
00174             &bnds,                          // Bounding rectangle of the window
00175             title255,                       // Title of the window
00176             0,                              // Window initially visible
00177             plainDBox,                      // procID
00178             (WindowRef)-1L,                 // Put window before all other windows
00179             0,                              // Window has minimize box
00180             (SInt32)this);                  // Store a pointer to the class in the refCon
00181     */
00182         //GHOST_PRINT("GHOST_WindowCarbon::GHOST_WindowCarbon(): creating full-screen OpenGL context\n");
00183         setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);;installDrawingContext(GHOST_kDrawingContextTypeOpenGL);
00184         updateDrawingContext();
00185         activateDrawingContext();        
00186 
00187     m_tablet.Active = GHOST_kTabletModeNone;
00188     }
00189 }
00190 
00191 
00192 GHOST_WindowCarbon::~GHOST_WindowCarbon()
00193 {
00194     if (m_customCursor) delete m_customCursor;
00195 
00196     if(ugly_hack==m_windowRef) ugly_hack= NULL;
00197     
00198     // printf("GHOST_WindowCarbon::~GHOST_WindowCarbon(): removing drawing context\n");
00199     if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone);
00200     if (m_windowRef) {
00201         ::DisposeWindow(m_windowRef);
00202         m_windowRef = 0;
00203     }
00204 }
00205 
00206 bool GHOST_WindowCarbon::getValid() const
00207 {
00208     bool valid;
00209     if (!m_fullScreen) {
00210         valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef);
00211     }
00212     else {
00213         valid = true;
00214     }
00215     return valid;
00216 }
00217 
00218 
00219 void GHOST_WindowCarbon::setTitle(const STR_String& title)
00220 {
00221     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setTitle(): window invalid")
00222     Str255 title255;
00223     gen2mac(title, title255);
00224     ::SetWTitle(m_windowRef, title255);
00225 }
00226 
00227 
00228 void GHOST_WindowCarbon::getTitle(STR_String& title) const
00229 {
00230     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getTitle(): window invalid")
00231     Str255 title255;
00232     ::GetWTitle(m_windowRef, title255);
00233     mac2gen(title255, title);
00234 }
00235 
00236 
00237 void GHOST_WindowCarbon::getWindowBounds(GHOST_Rect& bounds) const
00238 {
00239     OSStatus success;
00240     Rect rect;
00241     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getWindowBounds(): window invalid")
00242     success = ::GetWindowBounds(m_windowRef, kWindowStructureRgn, &rect);
00243     bounds.m_b = rect.bottom;
00244     bounds.m_l = rect.left;
00245     bounds.m_r = rect.right;
00246     bounds.m_t = rect.top;
00247 }
00248 
00249 
00250 void GHOST_WindowCarbon::getClientBounds(GHOST_Rect& bounds) const
00251 {
00252     Rect rect;
00253     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getClientBounds(): window invalid")
00254     //::GetPortBounds(m_grafPtr, &rect);
00255     ::GetWindowBounds(m_windowRef, kWindowContentRgn, &rect);
00256 
00257     bounds.m_b = rect.bottom;
00258     bounds.m_l = rect.left;
00259     bounds.m_r = rect.right;
00260     bounds.m_t = rect.top;
00261 
00262     // Subtract gutter height from bottom
00263 #ifdef GHOST_DRAW_CARBON_GUTTER
00264     if ((bounds.m_b - bounds.m_t) > s_sizeRectSize)
00265     {
00266         bounds.m_b -= s_sizeRectSize;
00267     }
00268     else
00269     {
00270         bounds.m_t = bounds.m_b;
00271     }
00272 #endif //GHOST_DRAW_CARBON_GUTTER
00273 }
00274 
00275 
00276 GHOST_TSuccess GHOST_WindowCarbon::setClientWidth(GHOST_TUns32 width)
00277 {
00278     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientWidth(): window invalid")
00279     GHOST_Rect cBnds, wBnds;
00280     getClientBounds(cBnds);
00281     if (((GHOST_TUns32)cBnds.getWidth()) != width) {
00282         ::SizeWindow(m_windowRef, width, cBnds.getHeight(), true);
00283     }
00284     return GHOST_kSuccess;
00285 }
00286 
00287 
00288 GHOST_TSuccess GHOST_WindowCarbon::setClientHeight(GHOST_TUns32 height)
00289 {
00290     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientHeight(): window invalid")
00291     GHOST_Rect cBnds, wBnds;
00292     getClientBounds(cBnds);
00293 #ifdef GHOST_DRAW_CARBON_GUTTER
00294     if (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize) {
00295         ::SizeWindow(m_windowRef, cBnds.getWidth(), height+s_sizeRectSize, true);
00296     }
00297 #else //GHOST_DRAW_CARBON_GUTTER
00298     if (((GHOST_TUns32)cBnds.getHeight()) != height) {
00299         ::SizeWindow(m_windowRef, cBnds.getWidth(), height, true);
00300     }
00301 #endif //GHOST_DRAW_CARBON_GUTTER
00302     return GHOST_kSuccess;
00303 }
00304 
00305 
00306 GHOST_TSuccess GHOST_WindowCarbon::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
00307 {
00308     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientSize(): window invalid")
00309     GHOST_Rect cBnds, wBnds;
00310     getClientBounds(cBnds);
00311 #ifdef GHOST_DRAW_CARBON_GUTTER
00312     if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
00313         (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize)) {
00314         ::SizeWindow(m_windowRef, width, height+s_sizeRectSize, true);
00315     }
00316 #else //GHOST_DRAW_CARBON_GUTTER
00317     if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
00318         (((GHOST_TUns32)cBnds.getHeight()) != height)) {
00319         ::SizeWindow(m_windowRef, width, height, true);
00320     }
00321 #endif //GHOST_DRAW_CARBON_GUTTER
00322     return GHOST_kSuccess;
00323 }
00324 
00325 
00326 GHOST_TWindowState GHOST_WindowCarbon::getState() const
00327 {
00328     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getState(): window invalid")
00329     GHOST_TWindowState state;
00330     if (::IsWindowVisible(m_windowRef) == false) {
00331         state = GHOST_kWindowStateMinimized;
00332     }
00333     else if (::IsWindowInStandardState(m_windowRef, nil, nil)) {
00334         state = GHOST_kWindowStateMaximized;
00335     }
00336     else {
00337         state = GHOST_kWindowStateNormal;
00338     }
00339     return state;
00340 }
00341 
00342 
00343 void GHOST_WindowCarbon::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
00344 {
00345     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::screenToClient(): window invalid")
00346     Point point;
00347     point.h = inX;
00348     point.v = inY;
00349     GrafPtr oldPort;
00350     ::GetPort(&oldPort);
00351     ::SetPort(m_grafPtr);
00352     ::GlobalToLocal(&point);
00353     ::SetPort(oldPort);
00354     outX = point.h;
00355     outY = point.v;
00356 }
00357 
00358 
00359 void GHOST_WindowCarbon::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
00360 {
00361     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::clientToScreen(): window invalid")
00362     Point point;
00363     point.h = inX;
00364     point.v = inY;
00365     GrafPtr oldPort;
00366     ::GetPort(&oldPort);
00367     ::SetPort(m_grafPtr);
00368     ::LocalToGlobal(&point);
00369     ::SetPort(oldPort);
00370     outX = point.h;
00371     outY = point.v;
00372 }
00373 
00374 
00375 GHOST_TSuccess GHOST_WindowCarbon::setState(GHOST_TWindowState state)
00376 {
00377     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setState(): window invalid")
00378     switch (state) {
00379     case GHOST_kWindowStateMinimized:
00380             ::HideWindow(m_windowRef);
00381             break;
00382     case GHOST_kWindowStateModified:
00383         SetWindowModified(m_windowRef, 1);
00384         break;
00385     case GHOST_kWindowStateUnModified:
00386         SetWindowModified(m_windowRef, 0);
00387         break;
00388     case GHOST_kWindowStateMaximized:
00389     case GHOST_kWindowStateNormal:
00390         default:
00391             ::ShowWindow(m_windowRef);
00392             break;
00393     }
00394     return GHOST_kSuccess;
00395 }
00396 
00397 
00398 GHOST_TSuccess GHOST_WindowCarbon::setOrder(GHOST_TWindowOrder order)
00399 {
00400     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setOrder(): window invalid")
00401     if (order == GHOST_kWindowOrderTop) {
00402         //::BringToFront(m_windowRef); is wrong, front window should be active for input too
00403         ::SelectWindow(m_windowRef);
00404     }
00405     else {
00406         /* doesnt work if you do this with a mouseclick */
00407         ::SendBehind(m_windowRef, nil);
00408     }
00409     return GHOST_kSuccess;
00410 }
00411 
00412 /*#define  WAIT_FOR_VSYNC 1*/
00413 #ifdef WAIT_FOR_VSYNC
00414 #include <OpenGL/OpenGL.h>
00415 #endif
00416 
00417 GHOST_TSuccess GHOST_WindowCarbon::swapBuffers()
00418 {
00419 #ifdef WAIT_FOR_VSYNC
00420 /* wait for vsync, to avoid tearing artifacts */
00421 long VBL = 1;
00422 CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL);
00423 #endif
00424 
00425     GHOST_TSuccess succeeded = GHOST_kSuccess;
00426     if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
00427         if (m_aglCtx) {
00428             ::aglSwapBuffers(m_aglCtx);
00429         }
00430         else {
00431             succeeded = GHOST_kFailure;
00432         }
00433     }
00434     return succeeded;
00435 }
00436 
00437 GHOST_TSuccess GHOST_WindowCarbon::updateDrawingContext()
00438 {
00439     GHOST_TSuccess succeeded = GHOST_kSuccess;
00440     if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
00441         if (m_aglCtx) {
00442             ::aglUpdateContext(m_aglCtx);
00443         }
00444         else {
00445             succeeded = GHOST_kFailure;
00446         }
00447     }
00448     return succeeded;
00449 }
00450 
00451 GHOST_TSuccess GHOST_WindowCarbon::activateDrawingContext()
00452 {
00453     GHOST_TSuccess succeeded = GHOST_kSuccess;
00454     if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
00455         if (m_aglCtx) {
00456             ::aglSetCurrentContext(m_aglCtx);
00457 #ifdef GHOST_DRAW_CARBON_GUTTER
00458             // Restrict drawing to non-gutter area
00459             ::aglEnable(m_aglCtx, AGL_BUFFER_RECT);
00460             GHOST_Rect bnds;
00461             getClientBounds(bnds);
00462             GLint b[4] =
00463             {
00464                 bnds.m_l,
00465                 bnds.m_t+s_sizeRectSize,
00466                 bnds.m_r-bnds.m_l,
00467                 bnds.m_b-bnds.m_t
00468             };
00469             GLboolean result = ::aglSetInteger(m_aglCtx, AGL_BUFFER_RECT, b);
00470 #endif //GHOST_DRAW_CARBON_GUTTER
00471         }
00472         else {
00473             succeeded = GHOST_kFailure;
00474         }
00475     }
00476     return succeeded;
00477 }
00478 
00479 
00480 GHOST_TSuccess GHOST_WindowCarbon::installDrawingContext(GHOST_TDrawingContextType type)
00481 {
00482     GHOST_TSuccess success = GHOST_kFailure;
00483     switch (type) {
00484         case GHOST_kDrawingContextTypeOpenGL:
00485             {
00486             if (!getValid()) break;
00487             
00488             AGLPixelFormat pixelFormat;
00489             if (!m_fullScreen) {
00490                 pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatWindow);
00491                 m_aglCtx = ::aglCreateContext(pixelFormat, s_firstaglCtx);
00492                 if (!m_aglCtx) break;
00493                 if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx;
00494                  success = ::aglSetDrawable(m_aglCtx, m_grafPtr) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
00495             }
00496             else {
00497                 //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL\n");
00498 GDHandle device=::GetMainDevice();pixelFormat=::aglChoosePixelFormat(&device,1,sPreferredFormatFullScreen);
00499                 m_aglCtx = ::aglCreateContext(pixelFormat, 0);
00500                 if (!m_aglCtx) break;
00501                 if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx;
00502                 //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): created OpenGL context\n");
00503                 //::CGGetActiveDisplayList(0, NULL, &m_numDisplays)
00504                 success = ::aglSetFullScreen(m_aglCtx, m_fullScreenWidth, m_fullScreenHeight, 75, 0) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
00505                 /*
00506                 if (success == GHOST_kSuccess) {
00507                     GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL succeeded\n");
00508                 }
00509                 else {
00510                     GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL failed\n");
00511                 }
00512                 */
00513             }
00514             ::aglDestroyPixelFormat(pixelFormat);
00515             }
00516             break;
00517         
00518         case GHOST_kDrawingContextTypeNone:
00519             success = GHOST_kSuccess;
00520             break;
00521         
00522         default:
00523             break;
00524     }
00525     return success;
00526 }
00527 
00528 
00529 GHOST_TSuccess GHOST_WindowCarbon::removeDrawingContext()
00530 {
00531     GHOST_TSuccess success = GHOST_kFailure;
00532     switch (m_drawingContextType) {
00533         case GHOST_kDrawingContextTypeOpenGL:
00534             if (m_aglCtx) {
00535                 aglSetCurrentContext(NULL);
00536                 aglSetDrawable(m_aglCtx, NULL);
00537                 //aglDestroyContext(m_aglCtx);
00538                 if (s_firstaglCtx == m_aglCtx) s_firstaglCtx = NULL;
00539                 success = ::aglDestroyContext(m_aglCtx) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
00540                 m_aglCtx = 0;
00541             }
00542             break;
00543         case GHOST_kDrawingContextTypeNone:
00544             success = GHOST_kSuccess;
00545             break;
00546         default:
00547             break;
00548     }
00549     return success;
00550 }
00551 
00552 
00553 GHOST_TSuccess GHOST_WindowCarbon::invalidate()
00554 {
00555     GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::invalidate(): window invalid")
00556     if (!m_fullScreen) {
00557         Rect rect;
00558         ::GetPortBounds(m_grafPtr, &rect);
00559         ::InvalWindowRect(m_windowRef, &rect);
00560     }
00561     else {
00562         //EventRef event;
00563         //OSStatus status = ::CreateEvent(NULL, kEventClassWindow, kEventWindowUpdate, 0, 0, &event);
00564         //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): created event " << status << " \n");
00565         //status = ::SetEventParameter(event, kEventParamDirectObject, typeWindowRef, sizeof(WindowRef), this);
00566         //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): set event parameter " << status << " \n");
00567         //status = ::PostEventToQueue(::GetMainEventQueue(), event, kEventPriorityStandard);
00568         //status = ::SendEventToEventTarget(event, ::GetApplicationEventTarget());
00569         //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): added event to queue " << status << " \n");
00570         m_fullScreenDirty = true;
00571     }
00572     return GHOST_kSuccess;
00573 }
00574 
00575 
00576 void GHOST_WindowCarbon::gen2mac(const STR_String& in, Str255 out) const
00577 {
00578     STR_String tempStr  = in;
00579     int num = tempStr.Length();
00580     if (num > 255) num = 255;
00581     ::memcpy(out+1, tempStr.Ptr(), num);
00582     out[0] = num;
00583 }
00584 
00585 
00586 void GHOST_WindowCarbon::mac2gen(const Str255 in, STR_String& out) const
00587 {
00588     char tmp[256];
00589     ::memcpy(tmp, in+1, in[0]);
00590     tmp[in[0]] = '\0';
00591     out = tmp;
00592 }
00593 
00594 void GHOST_WindowCarbon::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
00595 {
00596     static bool systemCursorVisible = true;
00597     
00598     if (visible != systemCursorVisible) {
00599         if (visible) {
00600             ::ShowCursor();
00601             systemCursorVisible = true;
00602         }
00603         else {
00604             ::HideCursor();
00605             systemCursorVisible = false;
00606         }
00607     }
00608 
00609     if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
00610         ::SetCursor( m_customCursor );
00611     } else {
00612         int carbon_cursor;
00613     
00614 #define GCMAP(ghostCursor, carbonCursor)    case ghostCursor: carbon_cursor = carbonCursor; break
00615         switch (cursor) {
00616         default:
00617         GCMAP( GHOST_kStandardCursorDefault,                kThemeArrowCursor);
00618         GCMAP( GHOST_kStandardCursorRightArrow,             kThemeAliasArrowCursor);
00619         GCMAP( GHOST_kStandardCursorLeftArrow,              kThemeArrowCursor);
00620         GCMAP( GHOST_kStandardCursorInfo,                   kThemeArrowCursor);
00621         GCMAP( GHOST_kStandardCursorDestroy,                kThemeArrowCursor);
00622         GCMAP( GHOST_kStandardCursorHelp,                   kThemeArrowCursor);
00623         GCMAP( GHOST_kStandardCursorCycle,                  kThemeArrowCursor);
00624         GCMAP( GHOST_kStandardCursorSpray,                  kThemeArrowCursor);
00625         GCMAP( GHOST_kStandardCursorWait,                   kThemeWatchCursor);
00626         GCMAP( GHOST_kStandardCursorText,                   kThemeIBeamCursor);
00627         GCMAP( GHOST_kStandardCursorCrosshair,              kThemeCrossCursor);
00628         GCMAP( GHOST_kStandardCursorUpDown,                 kThemeClosedHandCursor);
00629         GCMAP( GHOST_kStandardCursorLeftRight,              kThemeClosedHandCursor);
00630         GCMAP( GHOST_kStandardCursorTopSide,                kThemeArrowCursor);
00631         GCMAP( GHOST_kStandardCursorBottomSide,             kThemeArrowCursor);
00632         GCMAP( GHOST_kStandardCursorLeftSide,               kThemeResizeLeftCursor);
00633         GCMAP( GHOST_kStandardCursorRightSide,              kThemeResizeRightCursor);
00634         GCMAP( GHOST_kStandardCursorTopLeftCorner,          kThemeArrowCursor);
00635         GCMAP( GHOST_kStandardCursorTopRightCorner,         kThemeArrowCursor);
00636         GCMAP( GHOST_kStandardCursorBottomRightCorner,      kThemeArrowCursor);
00637         GCMAP( GHOST_kStandardCursorBottomLeftCorner,       kThemeArrowCursor);
00638         GCMAP( GHOST_kStandardCursorCopy,                   kThemeCopyArrowCursor);
00639         };
00640 #undef GCMAP
00641 
00642         ::SetThemeCursor(carbon_cursor);
00643     }
00644 }
00645 
00646 
00647 bool GHOST_WindowCarbon::getFullScreenDirty()
00648 {
00649     return m_fullScreen && m_fullScreenDirty;
00650 }
00651 
00652 
00653 GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorVisibility(bool visible)
00654 {
00655     if (::FrontWindow() == m_windowRef) {
00656         loadCursor(visible, getCursorShape());
00657     }
00658     
00659     return GHOST_kSuccess;
00660 }
00661     
00662 GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorShape(GHOST_TStandardCursor shape)
00663 {
00664     if (m_customCursor) {
00665         delete m_customCursor;
00666         m_customCursor = 0;
00667     }
00668 
00669     if (::FrontWindow() == m_windowRef) {
00670         loadCursor(getCursorVisibility(), shape);
00671     }
00672     
00673     return GHOST_kSuccess;
00674 }
00675 
00676 #if 0
00677 
00678 static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
00679 {
00680     ch= ((ch>>1)&0x55) | ((ch<<1)&0xAA);
00681     ch= ((ch>>2)&0x33) | ((ch<<2)&0xCC);
00682     ch= ((ch>>4)&0x0F) | ((ch<<4)&0xF0);
00683     return ch;
00684 }
00685 #endif
00686 
00687 
00689 static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
00690 {
00691     shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA);
00692     shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC);
00693     shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0);
00694     shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00);
00695     return shrt;
00696 }
00697 
00698 GHOST_TSuccess GHOST_WindowCarbon::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
00699                     int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color)
00700 {
00701     int y;
00702     
00703     if (m_customCursor) {
00704         delete m_customCursor;
00705         m_customCursor = 0;
00706     }
00707     
00708     m_customCursor = new Cursor;
00709     if (!m_customCursor) return GHOST_kFailure;
00710     
00711     for (y=0; y<16; y++) {
00712 #if !defined(__LITTLE_ENDIAN__)
00713         m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
00714         m_customCursor->mask[y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8));
00715 #else
00716         m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
00717         m_customCursor->mask[y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8));
00718 #endif
00719             
00720     }
00721     
00722     m_customCursor->hotSpot.h = hotX;
00723     m_customCursor->hotSpot.v = hotY;
00724     
00725     if (::FrontWindow() == m_windowRef) {
00726         loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
00727     }
00728     
00729     return GHOST_kSuccess;
00730 }
00731 
00732 GHOST_TSuccess GHOST_WindowCarbon::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], 
00733                                                 GHOST_TUns8 mask[16][2], int hotX, int hotY)
00734 {
00735     return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*) mask, 16, 16, hotX, hotY, 0, 1);
00736 }
00737 
00738 
00739 void GHOST_WindowCarbon::setMac_windowState(short value)
00740 {
00741     mac_windowState = value;
00742 }
00743 
00744 short GHOST_WindowCarbon::getMac_windowState()
00745 {
00746     return mac_windowState;
00747 }