Blender V2.61 - r43446
|
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 }