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