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