00001
00032 #if LL_DARWIN
00033
00034 #include "linden_common.h"
00035
00036 #include <Carbon/Carbon.h>
00037 #include <OpenGL/OpenGL.h>
00038
00039 #include "llwindowmacosx.h"
00040 #include "llkeyboardmacosx.h"
00041 #include "llerror.h"
00042 #include "llgl.h"
00043 #include "llstring.h"
00044 #include "lldir.h"
00045
00046 #include "llglheaders.h"
00047
00048 #include "indra_constants.h"
00049
00050 #include "llwindowmacosx-objc.h"
00051
00052 extern BOOL gDebugWindowProc;
00053
00054
00055
00056
00057
00058 const S32 WHEEL_DELTA = 1;
00059 const S32 BITS_PER_PIXEL = 32;
00060 const S32 MAX_NUM_RESOLUTIONS = 32;
00061
00062
00063
00064
00065
00066
00067
00068
00069 void show_window_creation_error(const char* title)
00070 {
00071 llwarns << title << llendl;
00072 shell_open( "help/window_creation_error.html");
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 }
00092
00093 BOOL check_for_card(const char* RENDERER, const char* bad_card)
00094 {
00095 if (!strnicmp(RENDERER, bad_card, strlen(bad_card)))
00096 {
00097 char buffer[1024];
00098 snprintf(buffer, sizeof(buffer),
00099 "Your video card appears to be a %s, which Second Life does not support.\n"
00100 "\n"
00101 "Second Life requires a video card with 32 Mb of memory or more, as well as\n"
00102 "multitexture support. We explicitly support nVidia GeForce 2 or better, \n"
00103 "and ATI Radeon 8500 or better.\n"
00104 "\n"
00105 "If you own a supported card and continue to receive this message, try \n"
00106 "updating to the latest video card drivers. Otherwise look in the\n"
00107 "secondlife.com support section or e-mail technical support\n"
00108 "\n"
00109 "You can try to run Second Life, but it will probably crash or run\n"
00110 "very slowly. Try anyway?",
00111 bad_card);
00112 S32 button = OSMessageBox(buffer, "Unsupported video card", OSMB_YESNO);
00113 if (OSBTN_YES == button)
00114 {
00115 return FALSE;
00116 }
00117 else
00118 {
00119 return TRUE;
00120 }
00121 }
00122
00123 return FALSE;
00124 }
00125
00126
00127
00128
00129
00130
00131 #define CAPTURE_ALL_DISPLAYS 0
00132 static double getDictDouble (CFDictionaryRef refDict, CFStringRef key);
00133 static long getDictLong (CFDictionaryRef refDict, CFStringRef key);
00134
00135
00136
00137
00138
00139 static EventTypeSpec WindowHandlerEventList[] =
00140 {
00141
00142
00143
00144
00145 { kEventClassWindow, kEventWindowActivated },
00146 { kEventClassWindow, kEventWindowDeactivated },
00147 { kEventClassWindow, kEventWindowShown },
00148 { kEventClassWindow, kEventWindowHidden },
00149 { kEventClassWindow, kEventWindowCollapsed },
00150 { kEventClassWindow, kEventWindowExpanded },
00151 { kEventClassWindow, kEventWindowGetClickActivation },
00152 { kEventClassWindow, kEventWindowClose },
00153 { kEventClassWindow, kEventWindowBoundsChanging },
00154 { kEventClassWindow, kEventWindowBoundsChanged },
00155
00156
00157
00158
00159 { kEventClassMouse, kEventMouseDown },
00160 { kEventClassMouse, kEventMouseUp },
00161 { kEventClassMouse, kEventMouseDragged },
00162 { kEventClassMouse, kEventMouseWheelMoved },
00163 { kEventClassMouse, kEventMouseMoved },
00164
00165
00166
00167
00168
00169
00170
00171 { kEventClassKeyboard, kEventRawKeyUp },
00172 { kEventClassKeyboard, kEventRawKeyModifiersChanged },
00173
00174
00175 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }
00176
00177 };
00178
00179 static EventTypeSpec GlobalHandlerEventList[] =
00180 {
00181
00182 { kEventClassMouse, kEventMouseDown },
00183 { kEventClassMouse, kEventMouseUp },
00184 { kEventClassMouse, kEventMouseDragged },
00185 { kEventClassMouse, kEventMouseWheelMoved },
00186 { kEventClassMouse, kEventMouseMoved },
00187
00188
00189
00190
00191
00192
00193
00194 { kEventClassKeyboard, kEventRawKeyUp },
00195 { kEventClassKeyboard, kEventRawKeyModifiersChanged },
00196
00197
00198 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }
00199 };
00200
00201 static EventTypeSpec CommandHandlerEventList[] =
00202 {
00203 { kEventClassCommand, kEventCommandProcess }
00204 };
00205
00206
00207
00208
00209
00210
00211 static LLWindowMacOSX *gWindowImplementation = NULL;
00212
00213
00214
00215 LLWindowMacOSX::LLWindowMacOSX(char *title, char *name, S32 x, S32 y, S32 width,
00216 S32 height, U32 flags,
00217 BOOL fullscreen, BOOL clearBg,
00218 BOOL disable_vsync, BOOL use_gl,
00219 BOOL ignore_pixel_depth)
00220 : LLWindow(fullscreen, flags)
00221 {
00222
00223 setupCocoa();
00224
00225
00226 gKeyboard = new LLKeyboardMacOSX();
00227
00228
00229 mWindow = NULL;
00230 mContext = NULL;
00231 mPixelFormat = NULL;
00232 mDisplay = CGMainDisplayID();
00233 mOldDisplayMode = NULL;
00234 mTimer = NULL;
00235 mSimulatedRightClick = FALSE;
00236 mLastModifiers = 0;
00237 mHandsOffEvents = FALSE;
00238 mCursorDecoupled = FALSE;
00239 mCursorLastEventDeltaX = 0;
00240 mCursorLastEventDeltaY = 0;
00241 mCursorIgnoreNextDelta = FALSE;
00242 mNeedsResize = FALSE;
00243 mOverrideAspectRatio = 0.f;
00244 mMinimized = FALSE;
00245 mTSMDocument = NULL;
00246 mLanguageTextInputAllowed = FALSE;
00247 mTSMScriptCode = 0;
00248 mTSMLangCode = 0;
00249
00250
00251
00252 mBounceTimer.stop();
00253
00254
00255 mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay);
00256
00257
00258 strcpy((char*)mWindowTitle + 1, title);
00259 mWindowTitle[0] = strlen(title);
00260
00261 mEventHandlerUPP = NewEventHandlerUPP(staticEventHandler);
00262 mGlobalHandlerRef = NULL;
00263 mWindowHandlerRef = NULL;
00264
00265
00266 SetRect( &mOldMouseClip, 0, 0, 0, 0 );
00267
00268
00269 InstallStandardEventHandler(GetApplicationEventTarget());
00270
00271
00272 gWindowImplementation = this;
00273
00274
00275 if(createContext(x, y, width, height, 32, fullscreen, disable_vsync))
00276 {
00277 if(mWindow != NULL)
00278 {
00279
00280
00281 ConstrainWindowToScreen(
00282 mWindow,
00283 kWindowStructureRgn,
00284 kWindowConstrainMayResize |
00285
00286 0,
00287 NULL,
00288 NULL);
00289
00290 MacShowWindow(mWindow);
00291 BringToFront(mWindow);
00292 }
00293
00294 if (!gGLManager.initGL())
00295 {
00296 setupFailure(
00297 "Second Life is unable to run because your video card drivers\n"
00298 "are out of date or unsupported. Please make sure you have\n"
00299 "the latest video card drivers installed.\n"
00300 "If you continue to receive this message, contact customer service.",
00301 "Error",
00302 OSMB_OK);
00303 return;
00304 }
00305
00306
00307 initCursors();
00308 setCursor( UI_CURSOR_ARROW );
00309 }
00310
00311 stop_glerror();
00312 }
00313
00314 BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync)
00315 {
00316 OSStatus err;
00317 BOOL glNeedsInit = FALSE;
00318
00319 if(mGlobalHandlerRef == NULL)
00320 {
00321 InstallApplicationEventHandler(mEventHandlerUPP, GetEventTypeCount (CommandHandlerEventList), CommandHandlerEventList, (void*)this, &mGlobalHandlerRef);
00322 }
00323
00324 mFullscreen = fullscreen;
00325
00326 if (mFullscreen && (mOldDisplayMode == NULL))
00327 {
00328 llinfos << "createContext: setting up fullscreen " << width << "x" << height << llendl;
00329
00330
00331 double refresh = getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate);
00332
00333
00334 if((width == 0) || (height == 0))
00335 {
00336
00337
00338
00339 S32 resolutionCount = 0;
00340 LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount);
00341
00342 if(resolutionList != NULL)
00343 {
00344 F32 closestAspect = 0;
00345 U32 closestHeight = 0;
00346 U32 closestWidth = 0;
00347 int i;
00348
00349 llinfos << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << llendl;
00350
00351 for(i=0; i < resolutionCount; i++)
00352 {
00353 F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight;
00354
00355 llinfos << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << llendl;
00356
00357 if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) &&
00358 (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio)))
00359 {
00360 llinfos << " (new closest mode) " << llendl;
00361
00362
00363 closestWidth = resolutionList[i].mWidth;
00364 closestHeight = resolutionList[i].mHeight;
00365 closestAspect = aspect;
00366 }
00367 }
00368
00369 width = closestWidth;
00370 height = closestHeight;
00371 }
00372 }
00373
00374 if((width == 0) || (height == 0))
00375 {
00376
00377 width = 1024;
00378 height = 768;
00379 }
00380
00381 if (true)
00382 {
00383
00384 CFDictionaryRef refDisplayMode = 0;
00385 boolean_t exactMatch = false;
00386
00387 #if CAPTURE_ALL_DISPLAYS
00388
00389 CGCaptureAllDisplays ();
00390 #else
00391
00392 CGDisplayCapture (mDisplay);
00393 #endif
00394
00395
00396 refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate(
00397 mDisplay,
00398 BITS_PER_PIXEL,
00399 width,
00400 height,
00401 refresh,
00402 &exactMatch);
00403
00404 if (refDisplayMode)
00405 {
00406 llinfos << "createContext: switching display resolution" << llendl;
00407 mOldDisplayMode = CGDisplayCurrentMode (mDisplay);
00408 CGDisplaySwitchToMode (mDisplay, refDisplayMode);
00409
00410
00411 AddEventTypesToHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList);
00412 }
00413
00414
00415 mFullscreen = TRUE;
00416 mFullscreenWidth = CGDisplayPixelsWide(mDisplay);
00417 mFullscreenHeight = CGDisplayPixelsHigh(mDisplay);
00418 mFullscreenBits = CGDisplayBitsPerPixel(mDisplay);
00419 mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate));
00420
00421 llinfos << "Running at " << mFullscreenWidth
00422 << "x" << mFullscreenHeight
00423 << "x" << mFullscreenBits
00424 << " @ " << mFullscreenRefresh
00425 << llendl;
00426 }
00427 else
00428 {
00429
00430 mFullscreen = FALSE;
00431 mFullscreenWidth = -1;
00432 mFullscreenHeight = -1;
00433 mFullscreenBits = -1;
00434 mFullscreenRefresh = -1;
00435
00436 char error[256];
00437 snprintf(error, sizeof(error), "Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
00438 OSMessageBox(error, "Error", OSMB_OK);
00439 }
00440 }
00441
00442 if(!mFullscreen && (mWindow == NULL))
00443 {
00444 Rect window_rect;
00445
00446
00447
00448
00449 llinfos << "createContext: creating window" << llendl;
00450
00451 window_rect.left = (long) x;
00452 window_rect.right = (long) x + width;
00453 window_rect.top = (long) y;
00454 window_rect.bottom = (long) y + height;
00455
00456
00457
00458
00459 mWindow = NewCWindow(
00460 NULL,
00461 &window_rect,
00462 mWindowTitle,
00463 false,
00464
00465 zoomDocProc,
00466
00467 kFirstWindowOfClass,
00468 true,
00469 (long)this);
00470
00471
00472 if (!mWindow)
00473 {
00474 setupFailure("Window creation error", "Error", OSMB_OK);
00475 return FALSE;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 InstallStandardEventHandler(GetWindowEventTarget(mWindow));
00485 InstallWindowEventHandler (mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef);
00486
00487 }
00488
00489 {
00490
00491
00492
00493 if (mTSMDocument)
00494 {
00495 DeactivateTSMDocument(mTSMDocument);
00496 DeleteTSMDocument(mTSMDocument);
00497 mTSMDocument = NULL;
00498 }
00499 static InterfaceTypeList types = { kUnicodeDocument };
00500 OSErr err = NewTSMDocument(1, types, &mTSMDocument, 0);
00501 if (err != noErr)
00502 {
00503 llwarns << "createContext: couldn't create a TSMDocument (" << err << ")" << llendl;
00504 }
00505 if (mTSMDocument)
00506 {
00507 UseInputWindow(mTSMDocument, TRUE);
00508 ActivateTSMDocument(mTSMDocument);
00509 }
00510 }
00511
00512 if(mContext == NULL)
00513 {
00514 AGLRendererInfo rendererInfo = NULL;
00515
00516
00517
00518
00519
00520 if(mPixelFormat == NULL)
00521 {
00522 if(mFullscreen)
00523 {
00524 GLint fullscreenAttrib[] =
00525 {
00526 AGL_RGBA,
00527 AGL_FULLSCREEN,
00528
00529 AGL_DOUBLEBUFFER,
00530 AGL_CLOSEST_POLICY,
00531 AGL_ACCELERATED,
00532 AGL_RED_SIZE, 8,
00533 AGL_GREEN_SIZE, 8,
00534 AGL_BLUE_SIZE, 8,
00535 AGL_ALPHA_SIZE, 8,
00536 AGL_DEPTH_SIZE, 24,
00537 AGL_STENCIL_SIZE, 8,
00538 AGL_NONE
00539 };
00540
00541 llinfos << "createContext: creating fullscreen pixelformat" << llendl;
00542
00543 GDHandle gdhDisplay = NULL;
00544 err = DMGetGDeviceByDisplayID ((DisplayIDType)mDisplay, &gdhDisplay, false);
00545
00546 mPixelFormat = aglChoosePixelFormat(&gdhDisplay, 1, fullscreenAttrib);
00547 rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1);
00548 }
00549 else
00550 {
00551 GLint windowedAttrib[] =
00552 {
00553 AGL_RGBA,
00554 AGL_DOUBLEBUFFER,
00555 AGL_CLOSEST_POLICY,
00556 AGL_ACCELERATED,
00557 AGL_RED_SIZE, 8,
00558 AGL_GREEN_SIZE, 8,
00559 AGL_BLUE_SIZE, 8,
00560 AGL_ALPHA_SIZE, 8,
00561 AGL_DEPTH_SIZE, 24,
00562 AGL_STENCIL_SIZE, 8,
00563 AGL_NONE
00564 };
00565
00566 llinfos << "createContext: creating windowed pixelformat" << llendl;
00567
00568 mPixelFormat = aglChoosePixelFormat(NULL, 0, windowedAttrib);
00569
00570 GDHandle gdhDisplay = GetMainDevice();
00571 rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1);
00572 }
00573
00574
00575
00576
00577 if(aglGetError() != AGL_NO_ERROR)
00578 {
00579 setupFailure("Can't find suitable pixel format", "Error", OSMB_OK);
00580 return FALSE;
00581 }
00582 }
00583
00584 if(mPixelFormat)
00585 {
00586 llinfos << "createContext: creating GL context" << llendl;
00587 mContext = aglCreateContext(mPixelFormat, NULL);
00588 }
00589
00590 if(mContext == NULL)
00591 {
00592 setupFailure("Can't make GL context", "Error", OSMB_OK);
00593 return FALSE;
00594 }
00595
00596 gGLManager.mVRAM = 0;
00597
00598 if(rendererInfo != NULL)
00599 {
00600 GLint result;
00601
00602 if(aglDescribeRenderer(rendererInfo, AGL_VIDEO_MEMORY, &result))
00603 {
00604
00605 gGLManager.mVRAM = result / (1024 * 1024);
00606 }
00607 else
00608 {
00609
00610 }
00611
00612
00613 if(aglDescribeRenderer(rendererInfo, AGL_TEXTURE_MEMORY, &result))
00614 {
00615
00616 }
00617 else
00618 {
00619
00620 }
00621
00622 aglDestroyRendererInfo(rendererInfo);
00623 }
00624
00625
00626 glNeedsInit = TRUE;
00627 }
00628
00629
00630 if (mFullscreen && (mOldDisplayMode != NULL))
00631 {
00632
00633
00634 llinfos << "createContext: attaching fullscreen drawable" << llendl;
00635
00636 #if CAPTURE_ALL_DISPLAYS
00637
00638 aglDisable (mContext, AGL_FS_CAPTURE_SINGLE);
00639 #else
00640
00641 aglEnable (mContext, AGL_FS_CAPTURE_SINGLE);
00642 #endif
00643
00644 if (!aglSetFullScreen (mContext, 0, 0, 0, 0))
00645 {
00646 setupFailure("Can't set GL fullscreen", "Error", OSMB_OK);
00647 return FALSE;
00648 }
00649 }
00650 else if(!mFullscreen && (mWindow != NULL))
00651 {
00652 llinfos << "createContext: attaching windowed drawable" << llendl;
00653
00654
00655 if(!aglSetDrawable(mContext, GetWindowPort (mWindow)))
00656 {
00657 setupFailure("Can't set GL drawable", "Error", OSMB_OK);
00658 return FALSE;
00659 }
00660 }
00661 else
00662 {
00663 setupFailure("Can't get fullscreen or windowed drawable.", "Error", OSMB_OK);
00664 return FALSE;
00665 }
00666
00667 if(mContext != NULL)
00668 {
00669 llinfos << "createContext: setting current context" << llendl;
00670
00671 if (!aglSetCurrentContext(mContext))
00672 {
00673 setupFailure("Can't activate GL rendering context", "Error", OSMB_OK);
00674 return FALSE;
00675 }
00676 }
00677
00678 if(glNeedsInit)
00679 {
00680
00681 const char* RENDERER = (const char*) glGetString(GL_RENDERER);
00682
00683 const char* CARD_LIST[] =
00684 { "RAGE 128",
00685 "RIVA TNT2",
00686 "Intel 810",
00687 "3Dfx/Voodoo3",
00688 "Radeon 7000",
00689 "Radeon 7200",
00690 "Radeon 7500",
00691 "Radeon DDR",
00692 "Radeon VE",
00693 "GDI Generic" };
00694 const S32 CARD_COUNT = sizeof(CARD_LIST)/sizeof(char*);
00695
00696
00697
00698
00699
00700 S32 i;
00701 for (i = 0; i < CARD_COUNT; i++)
00702 {
00703 if (check_for_card(RENDERER, CARD_LIST[i]))
00704 {
00705 close();
00706 shell_open( "help/unsupported_card.html" );
00707 return FALSE;
00708 }
00709 }
00710 }
00711
00712 GLint colorBits, alphaBits, depthBits, stencilBits;
00713
00714 if( !aglDescribePixelFormat(mPixelFormat, AGL_BUFFER_SIZE, &colorBits) ||
00715 !aglDescribePixelFormat(mPixelFormat, AGL_ALPHA_SIZE, &alphaBits) ||
00716 !aglDescribePixelFormat(mPixelFormat, AGL_DEPTH_SIZE, &depthBits) ||
00717 !aglDescribePixelFormat(mPixelFormat, AGL_STENCIL_SIZE, &stencilBits))
00718 {
00719 close();
00720 setupFailure("Can't get pixel format description", "Error", OSMB_OK);
00721 return FALSE;
00722 }
00723
00724 llinfos << "GL buffer: Color Bits " << S32(colorBits)
00725 << " Alpha Bits " << S32(alphaBits)
00726 << " Depth Bits " << S32(depthBits)
00727 << " Stencil Bits" << S32(stencilBits)
00728 << llendl;
00729
00730 if (colorBits < 32)
00731 {
00732 close();
00733 setupFailure(
00734 "Second Life requires True Color (32-bit) to run in a window.\n"
00735 "Please go to Control Panels -> Display -> Settings and\n"
00736 "set the screen to 32-bit color.\n"
00737 "Alternately, if you choose to run fullscreen, Second Life\n"
00738 "will automatically adjust the screen each time it runs.",
00739 "Error",
00740 OSMB_OK);
00741 return FALSE;
00742 }
00743
00744 if (alphaBits < 8)
00745 {
00746 close();
00747 setupFailure(
00748 "Second Life is unable to run because it can't get an 8 bit alpha\n"
00749 "channel. Usually this is due to video card driver issues.\n"
00750 "Please make sure you have the latest video card drivers installed.\n"
00751 "Also be sure your monitor is set to True Color (32-bit) in\n"
00752 "Control Panels -> Display -> Settings.\n"
00753 "If you continue to receive this message, contact customer service.",
00754 "Error",
00755 OSMB_OK);
00756 return FALSE;
00757 }
00758
00759
00760 GLint frames_per_swap = 0;
00761 if (disable_vsync)
00762 {
00763 llinfos << "Disabling vertical sync" << llendl;
00764 frames_per_swap = 0;
00765 }
00766 else
00767 {
00768 llinfos << "Keeping vertical sync" << llendl;
00769 frames_per_swap = 1;
00770 }
00771 aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap);
00772
00773 #if 0 // SJB: Got a compile error. Plus I don't want to test this along with everything else ; save it for later
00774
00775 CGLError cgl_err;
00776 CGLContextObj ctx = CGLGetCurrentContext();
00777
00778 cgl_err = CGLEnable( ctx, kCGLCEMPEngine);
00779
00780 if (cgl_err != kCGLNoError )
00781 {
00782 llinfos << "Multi-threaded OpenGL not available." << llendl;
00783 }
00784 else
00785 {
00786 llinfos << "Multi-threaded OpenGL enabled." << llendl;
00787 }
00788 #endif
00789
00790 return TRUE;
00791 }
00792
00793
00794
00795 BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, LLCoordScreen size, BOOL disable_vsync)
00796 {
00797 BOOL needsRebuild = FALSE;
00798 BOOL result = true;
00799
00800 if(fullscreen)
00801 {
00802 if(mFullscreen)
00803 {
00804
00805
00806 CFDictionaryRef refDisplayMode = 0;
00807 boolean_t exactMatch = false;
00808
00809
00810 refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate(
00811 mDisplay,
00812 BITS_PER_PIXEL,
00813 size.mX,
00814 size.mY,
00815 getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate),
00816 &exactMatch);
00817
00818 if (refDisplayMode)
00819 {
00820 CGDisplaySwitchToMode (mDisplay, refDisplayMode);
00821
00822 }
00823
00824 mFullscreenWidth = CGDisplayPixelsWide(mDisplay);
00825 mFullscreenHeight = CGDisplayPixelsHigh(mDisplay);
00826 mFullscreenBits = CGDisplayBitsPerPixel(mDisplay);
00827 mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate));
00828
00829 llinfos << "Switched resolution to " << mFullscreenWidth
00830 << "x" << mFullscreenHeight
00831 << "x" << mFullscreenBits
00832 << " @ " << mFullscreenRefresh
00833 << llendl;
00834
00835
00836 if (!aglUpdateContext(mContext))
00837 {
00838 setupFailure("Can't set GL fullscreen", "Error", OSMB_OK);
00839 result = FALSE;
00840 }
00841 }
00842 else
00843 {
00844
00845 needsRebuild = TRUE;
00846 }
00847 }
00848 else
00849 {
00850 if(mFullscreen)
00851 {
00852
00853 needsRebuild = TRUE;
00854 }
00855 else
00856 {
00857
00858
00859 if(mWindow != NULL)
00860 {
00861 ::SizeWindow(mWindow, size.mX, size.mY, true);
00862 }
00863 }
00864 }
00865
00866 stop_glerror();
00867 if(needsRebuild)
00868 {
00869 destroyContext();
00870 result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync);
00871 if (result)
00872 {
00873 if(mWindow != NULL)
00874 {
00875 MacShowWindow(mWindow);
00876 BringToFront(mWindow);
00877 }
00878
00879 llverify(gGLManager.initGL());
00880
00881
00882 initCursors();
00883 setCursor( UI_CURSOR_ARROW );
00884 }
00885 }
00886
00887 stop_glerror();
00888
00889 return result;
00890 }
00891
00892 void LLWindowMacOSX::destroyContext()
00893 {
00894 if (!mContext)
00895 {
00896
00897 return;
00898 }
00899
00900 if(mContext != NULL)
00901 {
00902 llinfos << "destroyContext: unhooking drawable " << llendl;
00903
00904 aglSetCurrentContext (NULL);
00905 aglSetDrawable(mContext, NULL);
00906 }
00907
00908
00909 if(mOldDisplayMode != NULL)
00910 {
00911 llinfos << "destroyContext: restoring display resolution " << llendl;
00912
00913 CGDisplaySwitchToMode (mDisplay, mOldDisplayMode);
00914
00915 #if CAPTURE_ALL_DISPLAYS
00916
00917 CGReleaseAllDisplays ();
00918 #else
00919
00920 CGDisplayRelease (mDisplay);
00921 #endif
00922
00923
00924
00925 mOldDisplayMode = NULL;
00926
00927
00928 RemoveEventTypesFromHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList);
00929 }
00930
00931
00932 gGLManager.shutdownGL();
00933
00934
00935 if(mPixelFormat != NULL)
00936 {
00937 llinfos << "destroyContext: destroying pixel format " << llendl;
00938 aglDestroyPixelFormat(mPixelFormat);
00939 mPixelFormat = NULL;
00940 }
00941
00942
00943 if(mGlobalHandlerRef != NULL)
00944 {
00945 llinfos << "destroyContext: removing global event handler" << llendl;
00946 RemoveEventHandler(mGlobalHandlerRef);
00947 mGlobalHandlerRef = NULL;
00948 }
00949
00950 if(mWindowHandlerRef != NULL)
00951 {
00952 llinfos << "destroyContext: removing window event handler" << llendl;
00953 RemoveEventHandler(mWindowHandlerRef);
00954 mWindowHandlerRef = NULL;
00955 }
00956
00957
00958 if(mTSMDocument != NULL)
00959 {
00960 llinfos << "destroyContext: deleting TSM document" << llendl;
00961 DeactivateTSMDocument(mTSMDocument);
00962 DeleteTSMDocument(mTSMDocument);
00963 mTSMDocument = NULL;
00964 }
00965
00966
00967 if(mWindow != NULL)
00968 {
00969 llinfos << "destroyContext: disposing window" << llendl;
00970 DisposeWindow(mWindow);
00971 mWindow = NULL;
00972 }
00973
00974
00975 if(mContext != NULL)
00976 {
00977 llinfos << "destroyContext: destroying GL context" << llendl;
00978 aglDestroyContext(mContext);
00979 mContext = NULL;
00980 }
00981
00982 }
00983
00984 LLWindowMacOSX::~LLWindowMacOSX()
00985 {
00986 destroyContext();
00987
00988 if(mSupportedResolutions != NULL)
00989 {
00990 delete []mSupportedResolutions;
00991 }
00992
00993 gWindowImplementation = NULL;
00994
00995 }
00996
00997
00998 void LLWindowMacOSX::show()
00999 {
01000 if(IsWindowCollapsed(mWindow))
01001 CollapseWindow(mWindow, false);
01002
01003 MacShowWindow(mWindow);
01004 BringToFront(mWindow);
01005 }
01006
01007 void LLWindowMacOSX::hide()
01008 {
01009 setMouseClipping(FALSE);
01010 HideWindow(mWindow);
01011 }
01012
01013 void LLWindowMacOSX::minimize()
01014 {
01015 setMouseClipping(FALSE);
01016 showCursor();
01017 CollapseWindow(mWindow, true);
01018 }
01019
01020 void LLWindowMacOSX::restore()
01021 {
01022 show();
01023 }
01024
01025
01026
01027
01028 void LLWindowMacOSX::close()
01029 {
01030
01031
01032
01033
01034
01035
01036
01037 setMouseClipping(FALSE);
01038 showCursor();
01039
01040 destroyContext();
01041 }
01042
01043 BOOL LLWindowMacOSX::isValid()
01044 {
01045 if(mFullscreen)
01046 {
01047 return(TRUE);
01048 }
01049
01050 return (mWindow != NULL);
01051 }
01052
01053 BOOL LLWindowMacOSX::getVisible()
01054 {
01055 BOOL result = FALSE;
01056
01057 if(mFullscreen)
01058 {
01059 result = TRUE;
01060 }if (mWindow)
01061 {
01062 if(MacIsWindowVisible(mWindow))
01063 result = TRUE;
01064 }
01065
01066 return(result);
01067 }
01068
01069 BOOL LLWindowMacOSX::getMinimized()
01070 {
01071 BOOL result = FALSE;
01072
01073
01074
01075 result = mMinimized;
01076
01077 return(result);
01078 }
01079
01080 BOOL LLWindowMacOSX::getMaximized()
01081 {
01082 BOOL result = FALSE;
01083
01084 if (mWindow)
01085 {
01086
01087 }
01088
01089 return(result);
01090 }
01091
01092 BOOL LLWindowMacOSX::maximize()
01093 {
01094
01095 return FALSE;
01096 }
01097
01098 BOOL LLWindowMacOSX::getFullscreen()
01099 {
01100 return mFullscreen;
01101 }
01102
01103 void LLWindowMacOSX::gatherInput()
01104 {
01105
01106 if (mBounceTimer.getStarted() && mBounceTimer.getElapsedTimeF32() > mBounceTime)
01107 {
01108 stopDockTileBounce();
01109 }
01110
01111
01112
01113
01114 EventRecord evt;
01115 while(WaitNextEvent(everyEvent, &evt, 0, NULL))
01116 {
01117
01118 switch(evt.what)
01119 {
01120 case mouseDown:
01121 {
01122 short part;
01123 WindowRef window;
01124 long selectResult;
01125 part = FindWindow(evt.where, &window);
01126 switch ( part )
01127 {
01128 case inMenuBar:
01129 selectResult = MenuSelect(evt.where);
01130
01131 HiliteMenu(0);
01132 break;
01133 }
01134 }
01135 break;
01136
01137 case kHighLevelEvent:
01138 AEProcessAppleEvent (&evt);
01139 break;
01140
01141 case updateEvt:
01142
01143 BeginUpdate((WindowRef)evt.message);
01144 EndUpdate((WindowRef)evt.message);
01145 break;
01146
01147 }
01148 }
01149 }
01150
01151 BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position)
01152 {
01153 Rect window_rect;
01154 OSStatus err = -1;
01155
01156 if(mFullscreen)
01157 {
01158 position->mX = 0;
01159 position->mY = 0;
01160 err = noErr;
01161 }
01162 else if(mWindow)
01163 {
01164 err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect);
01165
01166 position->mX = window_rect.left;
01167 position->mY = window_rect.top;
01168 }
01169 else
01170 {
01171 llerrs << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << llendl;
01172 }
01173
01174 return (err == noErr);
01175 }
01176
01177 BOOL LLWindowMacOSX::getSize(LLCoordScreen *size)
01178 {
01179 Rect window_rect;
01180 OSStatus err = -1;
01181
01182 if(mFullscreen)
01183 {
01184 size->mX = mFullscreenWidth;
01185 size->mY = mFullscreenHeight;
01186 err = noErr;
01187 }
01188 else if(mWindow)
01189 {
01190 err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect);
01191
01192 size->mX = window_rect.right - window_rect.left;
01193 size->mY = window_rect.bottom - window_rect.top;
01194 }
01195 else
01196 {
01197 llerrs << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << llendl;
01198 }
01199
01200 return (err == noErr);
01201 }
01202
01203 BOOL LLWindowMacOSX::getSize(LLCoordWindow *size)
01204 {
01205 Rect window_rect;
01206 OSStatus err = -1;
01207
01208 if(mFullscreen)
01209 {
01210 size->mX = mFullscreenWidth;
01211 size->mY = mFullscreenHeight;
01212 err = noErr;
01213 }
01214 else if(mWindow)
01215 {
01216 err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect);
01217
01218 size->mX = window_rect.right - window_rect.left;
01219 size->mY = window_rect.bottom - window_rect.top;
01220 }
01221 else
01222 {
01223 llerrs << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << llendl;
01224 }
01225
01226 return (err == noErr);
01227 }
01228
01229 BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position)
01230 {
01231 if(mWindow)
01232 {
01233 MacMoveWindow(mWindow, position.mX, position.mY, false);
01234 }
01235
01236 return TRUE;
01237 }
01238
01239 BOOL LLWindowMacOSX::setSize(const LLCoordScreen size)
01240 {
01241 if(mWindow)
01242 {
01243 SizeWindow(mWindow, size.mX, size.mY, true);
01244 }
01245
01246 return TRUE;
01247 }
01248
01249 void LLWindowMacOSX::swapBuffers()
01250 {
01251 aglSwapBuffers(mContext);
01252 }
01253
01254 F32 LLWindowMacOSX::getGamma()
01255 {
01256 F32 result = 1.8;
01257
01258 CGGammaValue redMin;
01259 CGGammaValue redMax;
01260 CGGammaValue redGamma;
01261 CGGammaValue greenMin;
01262 CGGammaValue greenMax;
01263 CGGammaValue greenGamma;
01264 CGGammaValue blueMin;
01265 CGGammaValue blueMax;
01266 CGGammaValue blueGamma;
01267
01268 if(CGGetDisplayTransferByFormula(
01269 mDisplay,
01270 &redMin,
01271 &redMax,
01272 &redGamma,
01273 &greenMin,
01274 &greenMax,
01275 &greenGamma,
01276 &blueMin,
01277 &blueMax,
01278 &blueGamma) == noErr)
01279 {
01280
01281
01282 result = greenGamma;
01283 }
01284
01285 return result;
01286 }
01287
01288 BOOL LLWindowMacOSX::restoreGamma()
01289 {
01290 CGDisplayRestoreColorSyncSettings();
01291 return true;
01292 }
01293
01294 BOOL LLWindowMacOSX::setGamma(const F32 gamma)
01295 {
01296 CGGammaValue redMin;
01297 CGGammaValue redMax;
01298 CGGammaValue redGamma;
01299 CGGammaValue greenMin;
01300 CGGammaValue greenMax;
01301 CGGammaValue greenGamma;
01302 CGGammaValue blueMin;
01303 CGGammaValue blueMax;
01304 CGGammaValue blueGamma;
01305
01306
01307
01308 if(CGGetDisplayTransferByFormula(
01309 mDisplay,
01310 &redMin,
01311 &redMax,
01312 &redGamma,
01313 &greenMin,
01314 &greenMax,
01315 &greenGamma,
01316 &blueMin,
01317 &blueMax,
01318 &blueGamma) != noErr)
01319 {
01320 return false;
01321 }
01322
01323 if(CGSetDisplayTransferByFormula(
01324 mDisplay,
01325 redMin,
01326 redMax,
01327 gamma,
01328 greenMin,
01329 greenMax,
01330 gamma,
01331 blueMin,
01332 blueMax,
01333 gamma) != noErr)
01334 {
01335 return false;
01336 }
01337
01338
01339 return true;
01340 }
01341
01342 BOOL LLWindowMacOSX::isCursorHidden()
01343 {
01344 return mCursorHidden;
01345 }
01346
01347
01348
01349
01350 void LLWindowMacOSX::setMouseClipping( BOOL b )
01351 {
01352
01353 mIsMouseClipping = b;
01354
01355 if(b)
01356 {
01357
01358 }
01359 else
01360 {
01361
01362 }
01363
01364 adjustCursorDecouple();
01365 }
01366
01367 BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
01368 {
01369 BOOL result = FALSE;
01370 LLCoordScreen screen_pos;
01371
01372 if (!convertCoords(position, &screen_pos))
01373 {
01374 return FALSE;
01375 }
01376
01377 CGPoint newPosition;
01378
01379
01380
01381 newPosition.x = screen_pos.mX;
01382 newPosition.y = screen_pos.mY;
01383
01384 CGSetLocalEventsSuppressionInterval(0.0);
01385 if(CGWarpMouseCursorPosition(newPosition) == noErr)
01386 {
01387 result = TRUE;
01388 }
01389
01390
01391 adjustCursorDecouple(true);
01392
01393 return result;
01394 }
01395
01396 static void fixOrigin(void)
01397 {
01398 GrafPtr port;
01399 Rect portrect;
01400
01401 ::GetPort(&port);
01402 ::GetPortBounds(port, &portrect);
01403 if((portrect.left != 0) || (portrect.top != 0))
01404 {
01405
01406 ::SetOrigin(0,0);
01407 }
01408 }
01409
01410 BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position)
01411 {
01412 Point cursor_point;
01413 LLCoordScreen screen_pos;
01414 GrafPtr save;
01415
01416 if(mWindow == NULL)
01417 return FALSE;
01418
01419 ::GetPort(&save);
01420 ::SetPort(GetWindowPort(mWindow));
01421 fixOrigin();
01422
01423
01424 ::GetMouse(&cursor_point);
01425
01426
01427
01428 ::SetPort(save);
01429
01430 if(mCursorDecoupled)
01431 {
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441 cursor_point.h += mCursorLastEventDeltaX;
01442 cursor_point.v += mCursorLastEventDeltaY;
01443 }
01444
01445 position->mX = cursor_point.h;
01446 position->mY = cursor_point.v;
01447
01448 return TRUE;
01449 }
01450
01451 void LLWindowMacOSX::adjustCursorDecouple(bool warpingMouse)
01452 {
01453 if(mIsMouseClipping && mCursorHidden)
01454 {
01455 if(warpingMouse)
01456 {
01457
01458 if(!mCursorDecoupled)
01459 {
01460
01461 CGAssociateMouseAndMouseCursorPosition(false);
01462 mCursorDecoupled = true;
01463 mCursorIgnoreNextDelta = TRUE;
01464 }
01465 }
01466 }
01467 else
01468 {
01469
01470 if(mCursorDecoupled)
01471 {
01472
01473 CGAssociateMouseAndMouseCursorPosition(true);
01474 mCursorDecoupled = false;
01475 }
01476 }
01477 }
01478
01479 F32 LLWindowMacOSX::getNativeAspectRatio()
01480 {
01481 if (mFullscreen)
01482 {
01483 return (F32)mFullscreenWidth / (F32)mFullscreenHeight;
01484 }
01485 else
01486 {
01487
01488
01489
01490 if (mOverrideAspectRatio > 0.f)
01491 {
01492 return mOverrideAspectRatio;
01493 }
01494
01495 return mOriginalAspectRatio;
01496 }
01497 }
01498
01499 F32 LLWindowMacOSX::getPixelAspectRatio()
01500 {
01501
01502 return 1.f;
01503 }
01504
01505
01506
01507
01508
01509 void LLWindowMacOSX::beforeDialog()
01510 {
01511 if(mFullscreen)
01512 {
01513
01514 #if CAPTURE_ALL_DISPLAYS
01515
01516 CGReleaseAllDisplays ();
01517 #else
01518
01519 CGDisplayRelease (mDisplay);
01520 #endif
01521
01522
01523
01524
01525
01526
01527 aglSetDrawable(mContext, NULL);
01528
01529
01530
01531 mHandsOffEvents = TRUE;
01532
01533 }
01534 }
01535
01536 void LLWindowMacOSX::afterDialog()
01537 {
01538 if(mFullscreen)
01539 {
01540 mHandsOffEvents = FALSE;
01541
01542
01543 aglSetFullScreen(mContext, 0, 0, 0, 0);
01544
01545
01546
01547 #if CAPTURE_ALL_DISPLAYS
01548
01549 CGCaptureAllDisplays ();
01550 #else
01551
01552 CGDisplayCapture (mDisplay);
01553 #endif
01554 }
01555 }
01556
01557
01558 S32 LLWindowMacOSX::stat(const char* file_name, struct stat* stat_info)
01559 {
01560 return ::stat( file_name, stat_info );
01561 }
01562
01563 void LLWindowMacOSX::flashIcon(F32 seconds)
01564 {
01565
01566 if(!mBounceTimer.getStarted())
01567 {
01568 OSErr err;
01569
01570 mBounceTime = seconds;
01571 memset(&mBounceRec, 0, sizeof(mBounceRec));
01572 mBounceRec.qType = nmType;
01573 mBounceRec.nmMark = 1;
01574 err = NMInstall(&mBounceRec);
01575 if(err == noErr)
01576 {
01577 mBounceTimer.start();
01578 }
01579 else
01580 {
01581
01582 llinfos << "NMInstall failed with error code " << err << llendl;
01583 }
01584 }
01585 }
01586
01587 BOOL LLWindowMacOSX::isClipboardTextAvailable()
01588 {
01589 OSStatus err;
01590 ScrapRef scrap;
01591 ScrapFlavorFlags flags;
01592 BOOL result = false;
01593
01594 err = GetCurrentScrap(&scrap);
01595
01596 if(err == noErr)
01597 {
01598 err = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &flags);
01599 }
01600
01601 if(err == noErr)
01602 result = true;
01603
01604 return result;
01605 }
01606
01607 BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst)
01608 {
01609 OSStatus err;
01610 ScrapRef scrap;
01611 Size len;
01612 BOOL result = false;
01613
01614 err = GetCurrentScrap(&scrap);
01615
01616 if(err == noErr)
01617 {
01618 err = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &len);
01619 }
01620
01621 if((err == noErr) && (len > 0))
01622 {
01623 int u16len = len / sizeof(U16);
01624 U16 *temp = new U16[u16len + 1];
01625 if (temp)
01626 {
01627 memset(temp, 0, (u16len + 1) * sizeof(temp[0]));
01628 err = GetScrapFlavorData(scrap, kScrapFlavorTypeUnicode, &len, temp);
01629 if (err == noErr)
01630 {
01631
01632 U16 *s, *d;
01633 for(s = d = temp; s[0] != '\0'; s++, d++)
01634 {
01635 if(s[0] == '\r')
01636 {
01637 if(s[1] == '\n')
01638 {
01639
01640 s++;
01641 }
01642
01643 d[0] = '\n';
01644 }
01645 else
01646 {
01647 d[0] = s[0];
01648 }
01649 }
01650
01651 d[0] = '\0';
01652
01653 dst = utf16str_to_wstring(temp);
01654
01655 result = true;
01656 }
01657 delete[] temp;
01658 }
01659 }
01660
01661 return result;
01662 }
01663
01664 BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s)
01665 {
01666 OSStatus err;
01667 ScrapRef scrap;
01668
01669
01670 BOOL result = false;
01671
01672 if (!s.empty())
01673 {
01674 err = GetCurrentScrap(&scrap);
01675 if (err == noErr)
01676 err = ClearScrap(&scrap);
01677
01678 if (err == noErr)
01679 {
01680 llutf16string utf16str = wstring_to_utf16str(s);
01681 size_t u16len = utf16str.length() * sizeof(U16);
01682 err = PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone, u16len, utf16str.data());
01683 if (err == noErr)
01684 result = true;
01685 }
01686 }
01687
01688 return result;
01689 }
01690
01691
01692 BOOL LLWindowMacOSX::sendEmail(const char* address, const char* subject, const char* body_text,
01693 const char* attachment, const char* attachment_displayed_name )
01694 {
01695
01696
01697 return false;
01698 }
01699
01700
01701
01702 BOOL LLWindowMacOSX::resetDisplayResolution()
01703 {
01704
01705 return true;
01706 }
01707
01708
01709 LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_resolutions)
01710 {
01711 if (!mSupportedResolutions)
01712 {
01713 CFArrayRef modes = CGDisplayAvailableModes(mDisplay);
01714
01715 if(modes != NULL)
01716 {
01717 CFIndex index, cnt;
01718
01719 mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
01720 mNumSupportedResolutions = 0;
01721
01722
01723 cnt = CFArrayGetCount( modes );
01724
01725 for ( index = 0; (index < cnt) && (mNumSupportedResolutions < MAX_NUM_RESOLUTIONS); index++ )
01726 {
01727
01728 CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex( modes, index );
01729 long width = getDictLong(mode, kCGDisplayWidth);
01730 long height = getDictLong(mode, kCGDisplayHeight);
01731 long bits = getDictLong(mode, kCGDisplayBitsPerPixel);
01732
01733 if(bits == BITS_PER_PIXEL && width >= 800 && height >= 600)
01734 {
01735 BOOL resolution_exists = FALSE;
01736 for(S32 i = 0; i < mNumSupportedResolutions; i++)
01737 {
01738 if (mSupportedResolutions[i].mWidth == width &&
01739 mSupportedResolutions[i].mHeight == height)
01740 {
01741 resolution_exists = TRUE;
01742 }
01743 }
01744 if (!resolution_exists)
01745 {
01746 mSupportedResolutions[mNumSupportedResolutions].mWidth = width;
01747 mSupportedResolutions[mNumSupportedResolutions].mHeight = height;
01748 mNumSupportedResolutions++;
01749 }
01750 }
01751 }
01752 }
01753 }
01754
01755 num_resolutions = mNumSupportedResolutions;
01756 return mSupportedResolutions;
01757 }
01758
01759 BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to)
01760 {
01761 S32 client_height;
01762 Rect client_rect;
01763
01764 if(mFullscreen)
01765 {
01766
01767 client_rect.left = 0;
01768 client_rect.top = 0;
01769 client_rect.right = mFullscreenWidth;
01770 client_rect.bottom = mFullscreenHeight;
01771 }
01772 else if (!mWindow ||
01773 (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) ||
01774 NULL == to)
01775 {
01776 return FALSE;
01777 }
01778
01779 to->mX = from.mX;
01780 client_height = client_rect.bottom - client_rect.top;
01781 to->mY = client_height - from.mY - 1;
01782
01783 return TRUE;
01784 }
01785
01786 BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to)
01787 {
01788 S32 client_height;
01789 Rect client_rect;
01790
01791 if(mFullscreen)
01792 {
01793
01794 client_rect.left = 0;
01795 client_rect.top = 0;
01796 client_rect.right = mFullscreenWidth;
01797 client_rect.bottom = mFullscreenHeight;
01798 }
01799 else if (!mWindow ||
01800 (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) ||
01801 NULL == to)
01802 {
01803 return FALSE;
01804 }
01805
01806 to->mX = from.mX;
01807 client_height = client_rect.bottom - client_rect.top;
01808 to->mY = client_height - from.mY - 1;
01809
01810 return TRUE;
01811 }
01812
01813 BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to)
01814 {
01815 if(mFullscreen)
01816 {
01817
01818 to->mX = from.mX;
01819 to->mY = from.mY;
01820 return TRUE;
01821 }
01822 else if(mWindow)
01823 {
01824 GrafPtr save;
01825 Point mouse_point;
01826
01827 mouse_point.h = from.mX;
01828 mouse_point.v = from.mY;
01829
01830 ::GetPort(&save);
01831 ::SetPort(GetWindowPort(mWindow));
01832 fixOrigin();
01833
01834 ::GlobalToLocal(&mouse_point);
01835
01836 to->mX = mouse_point.h;
01837 to->mY = mouse_point.v;
01838
01839 ::SetPort(save);
01840
01841 return TRUE;
01842 }
01843
01844 return FALSE;
01845 }
01846
01847 BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to)
01848 {
01849 if(mFullscreen)
01850 {
01851
01852 to->mX = from.mX;
01853 to->mY = from.mY;
01854 return TRUE;
01855 }
01856 else if(mWindow)
01857 {
01858 GrafPtr save;
01859 Point mouse_point;
01860
01861 mouse_point.h = from.mX;
01862 mouse_point.v = from.mY;
01863 ::GetPort(&save);
01864 ::SetPort(GetWindowPort(mWindow));
01865 fixOrigin();
01866
01867 LocalToGlobal(&mouse_point);
01868
01869 to->mX = mouse_point.h;
01870 to->mY = mouse_point.v;
01871
01872 ::SetPort(save);
01873
01874 return TRUE;
01875 }
01876
01877 return FALSE;
01878 }
01879
01880 BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to)
01881 {
01882 LLCoordWindow window_coord;
01883
01884 return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
01885 }
01886
01887 BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to)
01888 {
01889 LLCoordWindow window_coord;
01890
01891 return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
01892 }
01893
01894
01895
01896
01897 void LLWindowMacOSX::setupFailure(const char* text, const char* caption, U32 type)
01898 {
01899 destroyContext();
01900
01901 OSMessageBox(text, caption, type);
01902 }
01903
01904 pascal OSStatus LLWindowMacOSX::staticEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData)
01905 {
01906 LLWindowMacOSX *self = (LLWindowMacOSX*)userData;
01907
01908 return(self->eventHandler(myHandler, event));
01909 }
01910
01911 OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef event)
01912 {
01913 OSStatus result = eventNotHandledErr;
01914 UInt32 evtClass = GetEventClass (event);
01915 UInt32 evtKind = GetEventKind (event);
01916
01917
01918 if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
01919 {
01920 HICommand command;
01921 GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command);
01922
01923 switch(command.commandID)
01924 {
01925 case kHICommandQuit:
01926 if(mCallbacks->handleCloseRequest(this))
01927 {
01928
01929 mCallbacks->handleQuit(this);
01930
01931 }
01932 result = noErr;
01933 break;
01934
01935 default:
01936
01937 break;
01938 }
01939 }
01940
01941 if(mHandsOffEvents)
01942 {
01943 return(result);
01944 }
01945
01946 switch (evtClass)
01947 {
01948 case kEventClassTextInput:
01949 {
01950 switch (evtKind)
01951 {
01952 case kEventTextInputUnicodeForKeyEvent:
01953 {
01954 UInt32 modifiers = 0;
01955
01956
01957 {
01958 EventRef rawEvent;
01959
01960
01961 if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr)
01962 {
01963
01964 GetEventParameter (rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
01965
01966
01967 eventHandler (myHandler, rawEvent);
01968 }
01969 }
01970
01971 OSStatus err = noErr;
01972 EventParamType actualType = typeUnicodeText;
01973 UInt32 actualSize = 0;
01974 size_t actualCount = 0;
01975 U16 *buffer = NULL;
01976
01977
01978 err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, 0, &actualSize, NULL);
01979 if(err == noErr)
01980 {
01981
01982 actualCount = actualSize / sizeof(U16);
01983 buffer = new U16[actualCount];
01984 err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, actualSize, &actualSize, buffer);
01985 }
01986
01987 if(err == noErr)
01988 {
01989 if(modifiers & (cmdKey | controlKey))
01990 {
01991
01992 }
01993 else
01994 {
01995 MASK mask = 0;
01996 if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
01997 if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; }
01998 if(modifiers & optionKey) { mask |= MASK_ALT; }
01999
02000 llassert( actualType == typeUnicodeText );
02001
02002
02003
02004
02005 llutf16string utf16(buffer, actualCount);
02006 LLWString utf32 = utf16str_to_wstring(utf16);
02007 LLWString::iterator iter;
02008
02009 for(iter = utf32.begin(); iter != utf32.end(); iter++)
02010 {
02011 mCallbacks->handleUnicodeChar(*iter, mask);
02012 }
02013 }
02014 }
02015
02016 if(buffer != NULL)
02017 {
02018 delete[] buffer;
02019 }
02020
02021 result = err;
02022 }
02023 break;
02024 }
02025 }
02026 break;
02027
02028 case kEventClassKeyboard:
02029 {
02030 UInt32 keyCode = 0;
02031 char charCode = 0;
02032 UInt32 modifiers = 0;
02033
02034
02035 GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
02036 GetEventParameter (event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
02037
02038
02039
02040
02041 switch (evtKind)
02042 {
02043 case kEventRawKeyDown:
02044 case kEventRawKeyRepeat:
02045 if (gDebugWindowProc)
02046 {
02047 printf("key down, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n",
02048 (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers);
02049 fflush(stdout);
02050 }
02051 gKeyboard->handleKeyDown(keyCode, modifiers);
02052 result = eventNotHandledErr;
02053 break;
02054
02055 case kEventRawKeyUp:
02056 if (gDebugWindowProc)
02057 {
02058 printf("key up, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n",
02059 (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers);
02060 fflush(stdout);
02061 }
02062 gKeyboard->handleKeyUp(keyCode, modifiers);
02063 result = eventNotHandledErr;
02064 break;
02065
02066 case kEventRawKeyModifiersChanged:
02067
02068
02069
02070
02071 if((modifiers & shiftKey) && !(mLastModifiers & shiftKey))
02072 {
02073 if (gDebugWindowProc) printf("Shift key down event\n");
02074 gKeyboard->handleKeyDown(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000));
02075 }
02076 else if(!(modifiers & shiftKey) && (mLastModifiers & shiftKey))
02077 {
02078 if (gDebugWindowProc) printf("Shift key up event\n");
02079 gKeyboard->handleKeyUp(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000));
02080 }
02081
02082 if((modifiers & alphaLock) && !(mLastModifiers & alphaLock))
02083 {
02084 if (gDebugWindowProc) printf("Caps lock down event\n");
02085 gKeyboard->handleKeyDown(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000));
02086 }
02087 else if(!(modifiers & alphaLock) && (mLastModifiers & alphaLock))
02088 {
02089 if (gDebugWindowProc) printf("Caps lock up event\n");
02090 gKeyboard->handleKeyUp(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000));
02091 }
02092
02093 if((modifiers & controlKey) && !(mLastModifiers & controlKey))
02094 {
02095 if (gDebugWindowProc) printf("Control key down event\n");
02096 gKeyboard->handleKeyDown(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000));
02097 }
02098 else if(!(modifiers & controlKey) && (mLastModifiers & controlKey))
02099 {
02100 if (gDebugWindowProc) printf("Control key up event\n");
02101 gKeyboard->handleKeyUp(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000));
02102 }
02103
02104 if((modifiers & optionKey) && !(mLastModifiers & optionKey))
02105 {
02106 if (gDebugWindowProc) printf("Option key down event\n");
02107 gKeyboard->handleKeyDown(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000));
02108 }
02109 else if(!(modifiers & optionKey) && (mLastModifiers & optionKey))
02110 {
02111 if (gDebugWindowProc) printf("Option key up event\n");
02112 gKeyboard->handleKeyUp(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000));
02113 }
02114
02115
02116
02117
02118
02119
02120
02121 if((modifiers & kEventKeyModifierFnMask) != (mLastModifiers & kEventKeyModifierFnMask))
02122 {
02123 if (gDebugWindowProc) printf("Fn key state change event\n");
02124 gKeyboard->resetKeys();
02125 }
02126
02127 if (gDebugWindowProc) fflush(stdout);
02128
02129 mLastModifiers = modifiers;
02130 result = eventNotHandledErr;
02131 break;
02132 }
02133 }
02134 break;
02135
02136 case kEventClassMouse:
02137 {
02138 result = CallNextEventHandler(myHandler, event);
02139 if (eventNotHandledErr == result)
02140 {
02141 EventMouseButton button = kEventMouseButtonPrimary;
02142 HIPoint location = {0.0f, 0.0f};
02143 UInt32 modifiers = 0;
02144 UInt32 clickCount = 1;
02145 long wheelDelta = 0;
02146 LLCoordScreen inCoords;
02147 LLCoordGL outCoords;
02148 MASK mask = 0;
02149
02150 GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button);
02151 GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(location), NULL, &location);
02152 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
02153 GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(wheelDelta), NULL, &wheelDelta);
02154 GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount);
02155
02156 inCoords.mX = llround(location.x);
02157 inCoords.mY = llround(location.y);
02158
02159 if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
02160 if(modifiers & controlKey) { mask |= MASK_CONTROL; }
02161 if(modifiers & optionKey) { mask |= MASK_ALT; }
02162
02163 if(mCursorDecoupled)
02164 {
02165 CGMouseDelta x, y;
02166
02167
02168 CGGetLastMouseDelta( &x, &y );
02169 mCursorLastEventDeltaX = x;
02170 mCursorLastEventDeltaY = y;
02171
02172 if(mCursorIgnoreNextDelta)
02173 {
02174 mCursorLastEventDeltaX = 0;
02175 mCursorLastEventDeltaY = 0;
02176 mCursorIgnoreNextDelta = FALSE;
02177 }
02178 }
02179 else
02180 {
02181 mCursorLastEventDeltaX = 0;
02182 mCursorLastEventDeltaY = 0;
02183 }
02184
02185 inCoords.mX += mCursorLastEventDeltaX;
02186 inCoords.mY += mCursorLastEventDeltaY;
02187
02188 convertCoords(inCoords, &outCoords);
02189
02190
02191
02192
02193
02194 switch (evtKind)
02195 {
02196 case kEventMouseDown:
02197 switch(button)
02198 {
02199 case kEventMouseButtonPrimary:
02200 if(modifiers & cmdKey)
02201 {
02202
02203 mSimulatedRightClick = true;
02204 mCallbacks->handleRightMouseDown(this, outCoords, mask);
02205 }
02206 else if(clickCount == 2)
02207 {
02208
02209 mCallbacks->handleDoubleClick(this, outCoords, mask);
02210 }
02211 else
02212 {
02213 mCallbacks->handleMouseDown(this, outCoords, mask);
02214 }
02215 break;
02216 case kEventMouseButtonSecondary:
02217 mCallbacks->handleRightMouseDown(this, outCoords, mask);
02218 break;
02219
02220 case kEventMouseButtonTertiary:
02221 mCallbacks->handleMiddleMouseDown(this, outCoords, mask);
02222 break;
02223 }
02224 result = noErr;
02225 break;
02226 case kEventMouseUp:
02227
02228 switch(button)
02229 {
02230 case kEventMouseButtonPrimary:
02231 if(mSimulatedRightClick)
02232 {
02233
02234 mSimulatedRightClick = false;
02235 mCallbacks->handleRightMouseUp(this, outCoords, mask);
02236 }
02237 else
02238 {
02239 mCallbacks->handleMouseUp(this, outCoords, mask);
02240 }
02241 break;
02242 case kEventMouseButtonSecondary:
02243 mCallbacks->handleRightMouseUp(this, outCoords, mask);
02244 break;
02245
02246 case kEventMouseButtonTertiary:
02247 mCallbacks->handleMiddleMouseUp(this, outCoords, mask);
02248 break;
02249 }
02250 result = noErr;
02251 break;
02252
02253 case kEventMouseWheelMoved:
02254 {
02255 static S32 z_delta = 0;
02256
02257 z_delta += wheelDelta;
02258
02259 if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta)
02260 {
02261 mCallbacks->handleScrollWheel(this, -z_delta / WHEEL_DELTA);
02262 z_delta = 0;
02263 }
02264 }
02265 result = noErr;
02266 break;
02267
02268 case kEventMouseDragged:
02269 case kEventMouseMoved:
02270 mCallbacks->handleMouseMove(this, outCoords, mask);
02271 result = noErr;
02272 break;
02273
02274 }
02275 }
02276 }
02277 break;
02278
02279 case kEventClassWindow:
02280 switch(evtKind)
02281 {
02282 case kEventWindowActivated:
02283 if (mTSMDocument)
02284 {
02285 ActivateTSMDocument(mTSMDocument);
02286 }
02287 mCallbacks->handleFocus(this);
02288 break;
02289 case kEventWindowDeactivated:
02290 mCallbacks->handleFocusLost(this);
02291 break;
02292 case kEventWindowBoundsChanging:
02293 {
02294 Rect currentBounds;
02295 Rect previousBounds;
02296
02297 GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds);
02298 GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &previousBounds);
02299
02300
02301 if(0)
02302 {
02303 SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds);
02304 }
02305 }
02306 break;
02307
02308 case kEventWindowBoundsChanged:
02309 {
02310 Rect newBounds;
02311
02312 GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds);
02313 aglUpdateContext(mContext);
02314 mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top);
02315
02316
02317 }
02318 break;
02319
02320 case kEventWindowClose:
02321 if(mCallbacks->handleCloseRequest(this))
02322 {
02323
02324 mCallbacks->handleQuit(this);
02325
02326 }
02327 result = noErr;
02328 break;
02329
02330 case kEventWindowHidden:
02331
02332 mMinimized = TRUE;
02333 mCallbacks->handleActivate(this, false);
02334
02335 break;
02336
02337 case kEventWindowShown:
02338
02339 mMinimized = FALSE;
02340 mCallbacks->handleActivate(this, true);
02341
02342 break;
02343
02344 case kEventWindowCollapsed:
02345
02346 mMinimized = TRUE;
02347 mCallbacks->handleActivate(this, false);
02348
02349 break;
02350
02351 case kEventWindowExpanded:
02352
02353 mMinimized = FALSE;
02354 mCallbacks->handleActivate(this, true);
02355
02356 break;
02357
02358 case kEventWindowGetClickActivation:
02359
02360
02361 break;
02362 }
02363 break;
02364 }
02365 return result;
02366 }
02367
02368 const char* cursorIDToName(int id)
02369 {
02370 switch (id)
02371 {
02372 case UI_CURSOR_ARROW: return "UI_CURSOR_ARROW";
02373 case UI_CURSOR_WAIT: return "UI_CURSOR_WAIT";
02374 case UI_CURSOR_HAND: return "UI_CURSOR_HAND";
02375 case UI_CURSOR_IBEAM: return "UI_CURSOR_IBEAM";
02376 case UI_CURSOR_CROSS: return "UI_CURSOR_CROSS";
02377 case UI_CURSOR_SIZENWSE: return "UI_CURSOR_SIZENWSE";
02378 case UI_CURSOR_SIZENESW: return "UI_CURSOR_SIZENESW";
02379 case UI_CURSOR_SIZEWE: return "UI_CURSOR_SIZEWE";
02380 case UI_CURSOR_SIZENS: return "UI_CURSOR_SIZENS";
02381 case UI_CURSOR_NO: return "UI_CURSOR_NO";
02382 case UI_CURSOR_WORKING: return "UI_CURSOR_WORKING";
02383 case UI_CURSOR_TOOLGRAB: return "UI_CURSOR_TOOLGRAB";
02384 case UI_CURSOR_TOOLLAND: return "UI_CURSOR_TOOLLAND";
02385 case UI_CURSOR_TOOLFOCUS: return "UI_CURSOR_TOOLFOCUS";
02386 case UI_CURSOR_TOOLCREATE: return "UI_CURSOR_TOOLCREATE";
02387 case UI_CURSOR_ARROWDRAG: return "UI_CURSOR_ARROWDRAG";
02388 case UI_CURSOR_ARROWCOPY: return "UI_CURSOR_ARROWCOPY";
02389 case UI_CURSOR_ARROWDRAGMULTI: return "UI_CURSOR_ARROWDRAGMULTI";
02390 case UI_CURSOR_ARROWCOPYMULTI: return "UI_CURSOR_ARROWCOPYMULTI";
02391 case UI_CURSOR_NOLOCKED: return "UI_CURSOR_NOLOCKED";
02392 case UI_CURSOR_ARROWLOCKED: return "UI_CURSOR_ARROWLOCKED";
02393 case UI_CURSOR_GRABLOCKED: return "UI_CURSOR_GRABLOCKED";
02394 case UI_CURSOR_TOOLTRANSLATE: return "UI_CURSOR_TOOLTRANSLATE";
02395 case UI_CURSOR_TOOLROTATE: return "UI_CURSOR_TOOLROTATE";
02396 case UI_CURSOR_TOOLSCALE: return "UI_CURSOR_TOOLSCALE";
02397 case UI_CURSOR_TOOLCAMERA: return "UI_CURSOR_TOOLCAMERA";
02398 case UI_CURSOR_TOOLPAN: return "UI_CURSOR_TOOLPAN";
02399 case UI_CURSOR_TOOLZOOMIN: return "UI_CURSOR_TOOLZOOMIN";
02400 case UI_CURSOR_TOOLPICKOBJECT3: return "UI_CURSOR_TOOLPICKOBJECT3";
02401 case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT";
02402 case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY";
02403 case UI_CURSOR_TOOLPAY: return "UI_CURSOR_TOOLPAY";
02404 case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN";
02405 case UI_CURSOR_PIPETTE: return "UI_CURSOR_PIPETTE";
02406 }
02407
02408 llerrs << "cursorIDToName: unknown cursor id" << id << llendl;
02409
02410 return "UI_CURSOR_ARROW";
02411 }
02412
02413 static CursorRef gCursors[UI_CURSOR_COUNT];
02414
02415
02416 static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY)
02417 {
02418
02419 std::string fullpath = gDirUtilp->getAppRODataDir();
02420 fullpath += gDirUtilp->getDirDelimiter();
02421 fullpath += "cursors_mac";
02422 fullpath += gDirUtilp->getDirDelimiter();
02423 fullpath += cursorIDToName(cursorid);
02424 fullpath += ".tif";
02425
02426 gCursors[cursorid] = createImageCursor(fullpath.c_str(), hotspotX, hotspotY);
02427 }
02428
02429 void LLWindowMacOSX::setCursor(ECursorType cursor)
02430 {
02431 OSStatus result = noErr;
02432
02433 if (cursor == UI_CURSOR_ARROW
02434 && mBusyCount > 0)
02435 {
02436 cursor = UI_CURSOR_WORKING;
02437 }
02438
02439 if(mCurrentCursor == cursor)
02440 return;
02441
02442
02443 if (cursor == UI_CURSOR_ARROWDRAGMULTI)
02444 {
02445 cursor = UI_CURSOR_ARROWDRAG;
02446 }
02447 else if (cursor == UI_CURSOR_ARROWCOPYMULTI)
02448 {
02449 cursor = UI_CURSOR_ARROWCOPY;
02450 }
02451
02452 switch(cursor)
02453 {
02454 default:
02455 case UI_CURSOR_ARROW:
02456 InitCursor();
02457 if(mCursorHidden)
02458 {
02459
02460 ::HideCursor();
02461 }
02462 break;
02463
02464
02465
02466
02467
02468 case UI_CURSOR_WAIT: SetThemeCursor(kThemeWatchCursor); break;
02469 case UI_CURSOR_IBEAM: SetThemeCursor(kThemeIBeamCursor); break;
02470 case UI_CURSOR_CROSS: SetThemeCursor(kThemeCrossCursor); break;
02471 case UI_CURSOR_HAND: SetThemeCursor(kThemePointingHandCursor); break;
02472
02473 case UI_CURSOR_ARROWCOPY: SetThemeCursor(kThemeCopyArrowCursor); break;
02474
02475
02476 case UI_CURSOR_NO:
02477 case UI_CURSOR_SIZEWE:
02478 case UI_CURSOR_SIZENS:
02479 case UI_CURSOR_SIZENWSE:
02480 case UI_CURSOR_SIZENESW:
02481 case UI_CURSOR_WORKING:
02482 case UI_CURSOR_TOOLGRAB:
02483 case UI_CURSOR_TOOLLAND:
02484 case UI_CURSOR_TOOLFOCUS:
02485 case UI_CURSOR_TOOLCREATE:
02486 case UI_CURSOR_ARROWDRAG:
02487 case UI_CURSOR_NOLOCKED:
02488 case UI_CURSOR_ARROWLOCKED:
02489 case UI_CURSOR_GRABLOCKED:
02490 case UI_CURSOR_TOOLTRANSLATE:
02491 case UI_CURSOR_TOOLROTATE:
02492 case UI_CURSOR_TOOLSCALE:
02493 case UI_CURSOR_TOOLCAMERA:
02494 case UI_CURSOR_TOOLPAN:
02495 case UI_CURSOR_TOOLZOOMIN:
02496 case UI_CURSOR_TOOLPICKOBJECT3:
02497 case UI_CURSOR_TOOLSIT:
02498 case UI_CURSOR_TOOLBUY:
02499 case UI_CURSOR_TOOLPAY:
02500 case UI_CURSOR_TOOLOPEN:
02501 result = setImageCursor(gCursors[cursor]);
02502 break;
02503
02504 }
02505
02506 if(result != noErr)
02507 {
02508 InitCursor();
02509 }
02510
02511 mCurrentCursor = cursor;
02512 }
02513
02514 ECursorType LLWindowMacOSX::getCursor()
02515 {
02516 return mCurrentCursor;
02517 }
02518
02519 void LLWindowMacOSX::initCursors()
02520 {
02521 initPixmapCursor(UI_CURSOR_NO, 8, 8);
02522 initPixmapCursor(UI_CURSOR_WORKING, 1, 1);
02523 initPixmapCursor(UI_CURSOR_TOOLGRAB, 2, 14);
02524 initPixmapCursor(UI_CURSOR_TOOLLAND, 13, 8);
02525 initPixmapCursor(UI_CURSOR_TOOLFOCUS, 7, 6);
02526 initPixmapCursor(UI_CURSOR_TOOLCREATE, 7, 7);
02527 initPixmapCursor(UI_CURSOR_ARROWDRAG, 1, 1);
02528 initPixmapCursor(UI_CURSOR_ARROWCOPY, 1, 1);
02529 initPixmapCursor(UI_CURSOR_NOLOCKED, 8, 8);
02530 initPixmapCursor(UI_CURSOR_ARROWLOCKED, 1, 1);
02531 initPixmapCursor(UI_CURSOR_GRABLOCKED, 2, 14);
02532 initPixmapCursor(UI_CURSOR_TOOLTRANSLATE, 1, 1);
02533 initPixmapCursor(UI_CURSOR_TOOLROTATE, 1, 1);
02534 initPixmapCursor(UI_CURSOR_TOOLSCALE, 1, 1);
02535 initPixmapCursor(UI_CURSOR_TOOLCAMERA, 7, 6);
02536 initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6);
02537 initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6);
02538 initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1);
02539 initPixmapCursor(UI_CURSOR_TOOLSIT, 1, 1);
02540 initPixmapCursor(UI_CURSOR_TOOLBUY, 1, 1);
02541 initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1);
02542 initPixmapCursor(UI_CURSOR_TOOLOPEN, 1, 1);
02543
02544 initPixmapCursor(UI_CURSOR_SIZENWSE, 10, 10);
02545 initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10);
02546 initPixmapCursor(UI_CURSOR_SIZEWE, 10, 10);
02547 initPixmapCursor(UI_CURSOR_SIZENS, 10, 10);
02548
02549 }
02550
02551 void LLWindowMacOSX::captureMouse()
02552 {
02553
02554
02555 }
02556
02557 void LLWindowMacOSX::releaseMouse()
02558 {
02559
02560
02561 }
02562
02563 void LLWindowMacOSX::hideCursor()
02564 {
02565 if(!mCursorHidden)
02566 {
02567
02568 mCursorHidden = TRUE;
02569 mHideCursorPermanent = TRUE;
02570 ::HideCursor();
02571 }
02572 else
02573 {
02574
02575 }
02576
02577 adjustCursorDecouple();
02578 }
02579
02580 void LLWindowMacOSX::showCursor()
02581 {
02582 if(mCursorHidden)
02583 {
02584
02585 mCursorHidden = FALSE;
02586 mHideCursorPermanent = FALSE;
02587 ::ShowCursor();
02588 }
02589 else
02590 {
02591
02592 }
02593
02594 adjustCursorDecouple();
02595 }
02596
02597 void LLWindowMacOSX::showCursorFromMouseMove()
02598 {
02599 if (!mHideCursorPermanent)
02600 {
02601 showCursor();
02602 }
02603 }
02604
02605 void LLWindowMacOSX::hideCursorUntilMouseMove()
02606 {
02607 if (!mHideCursorPermanent)
02608 {
02609 hideCursor();
02610 mHideCursorPermanent = FALSE;
02611 }
02612 }
02613
02614
02615
02616
02617
02618
02619 LLSplashScreenMacOSX::LLSplashScreenMacOSX()
02620 {
02621 mWindow = NULL;
02622 }
02623
02624 LLSplashScreenMacOSX::~LLSplashScreenMacOSX()
02625 {
02626 }
02627
02628 void LLSplashScreenMacOSX::showImpl()
02629 {
02630
02631 #if 0
02632 IBNibRef nib = NULL;
02633 OSStatus err;
02634
02635 err = CreateNibReference(CFSTR("SecondLife"), &nib);
02636
02637 if(err == noErr)
02638 {
02639 CreateWindowFromNib(nib, CFSTR("Splash Screen"), &mWindow);
02640
02641 DisposeNibReference(nib);
02642 }
02643
02644 if(mWindow != NULL)
02645 {
02646 ShowWindow(mWindow);
02647 }
02648 #endif
02649 }
02650
02651 void LLSplashScreenMacOSX::updateImpl(const char* mesg)
02652 {
02653 if(mWindow != NULL)
02654 {
02655 CFStringRef string = NULL;
02656
02657 if(mesg != NULL)
02658 {
02659 string = CFStringCreateWithCString(NULL, mesg, kCFStringEncodingUTF8);
02660 }
02661 else
02662 {
02663 string = CFStringCreateWithCString(NULL, "", kCFStringEncodingUTF8);
02664 }
02665
02666 if(string != NULL)
02667 {
02668 ControlRef progressText = NULL;
02669 ControlID id;
02670 OSStatus err;
02671
02672 id.signature = 'what';
02673 id.id = 0;
02674
02675 err = GetControlByID(mWindow, &id, &progressText);
02676 if(err == noErr)
02677 {
02678 err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&string);
02679 Draw1Control(progressText);
02680 }
02681
02682 CFRelease(string);
02683 }
02684 }
02685 }
02686
02687
02688 void LLSplashScreenMacOSX::hideImpl()
02689 {
02690 if(mWindow != NULL)
02691 {
02692 DisposeWindow(mWindow);
02693 mWindow = NULL;
02694 }
02695 }
02696
02697
02698
02699 S32 OSMessageBoxMacOSX(const char* text, const char* caption, U32 type)
02700 {
02701 S32 result = OSBTN_CANCEL;
02702 SInt16 retval_mac = 1;
02703 AlertStdCFStringAlertParamRec params;
02704 CFStringRef errorString = NULL;
02705 CFStringRef explanationString = NULL;
02706 DialogRef alert = NULL;
02707 AlertType alertType = kAlertCautionAlert;
02708 OSStatus err;
02709
02710 if(text != NULL)
02711 {
02712 explanationString = CFStringCreateWithCString(NULL, text, kCFStringEncodingUTF8);
02713 }
02714 else
02715 {
02716 explanationString = CFStringCreateWithCString(NULL, "", kCFStringEncodingUTF8);
02717 }
02718
02719 if(caption != NULL)
02720 {
02721 errorString = CFStringCreateWithCString(NULL, caption, kCFStringEncodingUTF8);
02722 }
02723 else
02724 {
02725 errorString = CFStringCreateWithCString(NULL, "", kCFStringEncodingUTF8);
02726 }
02727
02728 params.version = kStdCFStringAlertVersionOne;
02729 params.movable = false;
02730 params.helpButton = false;
02731 params.defaultText = (CFStringRef)kAlertDefaultOKText;
02732 params.cancelText = 0;
02733 params.otherText = 0;
02734 params.defaultButton = 1;
02735 params.cancelButton = 0;
02736 params.position = kWindowDefaultPosition;
02737 params.flags = 0;
02738
02739 switch(type)
02740 {
02741 case OSMB_OK:
02742 default:
02743 break;
02744 case OSMB_OKCANCEL:
02745 params.cancelText = (CFStringRef)kAlertDefaultCancelText;
02746 params.cancelButton = 2;
02747 break;
02748 case OSMB_YESNO:
02749 alertType = kAlertNoteAlert;
02750 params.defaultText = CFSTR("Yes");
02751 params.cancelText = CFSTR("No");
02752 params.cancelButton = 2;
02753 break;
02754 }
02755
02756 if(gWindowImplementation != NULL)
02757 gWindowImplementation->beforeDialog();
02758
02759 err = CreateStandardAlert(
02760 alertType,
02761 errorString,
02762 explanationString,
02763 ¶ms,
02764 &alert);
02765
02766 if(err == noErr)
02767 {
02768 err = RunStandardAlert(
02769 alert,
02770 NULL,
02771 &retval_mac);
02772 }
02773
02774 if(gWindowImplementation != NULL)
02775 gWindowImplementation->afterDialog();
02776
02777 switch(type)
02778 {
02779 case OSMB_OK:
02780 case OSMB_OKCANCEL:
02781 default:
02782 if(retval_mac == 1)
02783 result = OSBTN_OK;
02784 else
02785 result = OSBTN_CANCEL;
02786 break;
02787 case OSMB_YESNO:
02788 if(retval_mac == 1)
02789 result = OSBTN_YES;
02790 else
02791 result = OSBTN_NO;
02792 break;
02793 }
02794
02795 if(errorString != NULL)
02796 {
02797 CFRelease(errorString);
02798 }
02799
02800 if(explanationString != NULL)
02801 {
02802 CFRelease(explanationString);
02803 }
02804
02805 return result;
02806 }
02807
02808
02809
02810 void spawn_web_browser(const char* escaped_url)
02811 {
02812 bool found = false;
02813 S32 i;
02814 for (i = 0; i < gURLProtocolWhitelistCount; i++)
02815 {
02816 S32 len = strlen(gURLProtocolWhitelist[i]);
02817 if (!strncmp(escaped_url, gURLProtocolWhitelist[i], len)
02818 && escaped_url[len] == ':')
02819 {
02820 found = true;
02821 break;
02822 }
02823 }
02824
02825 if (!found)
02826 {
02827 llwarns << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << llendl;
02828 return;
02829 }
02830
02831 OSStatus result = noErr;
02832 CFURLRef urlRef = NULL;
02833
02834 llinfos << "Opening URL " << escaped_url << llendl;
02835
02836 CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url, kCFStringEncodingUTF8);
02837 if (stringRef)
02838 {
02839
02840
02841 urlRef = CFURLCreateWithString(NULL, stringRef, NULL);
02842
02843
02844
02845 CFRelease(stringRef);
02846 }
02847
02848 if (urlRef)
02849 {
02850 result = LSOpenCFURLRef(urlRef, NULL);
02851
02852 if (result != noErr)
02853 {
02854 llinfos << "Error " << result << " on open." << llendl;
02855 }
02856
02857 CFRelease(urlRef);
02858 }
02859 else
02860 {
02861 llinfos << "Error: couldn't create URL." << llendl;
02862 }
02863 }
02864
02865 void shell_open( const char* file_path )
02866 {
02867 OSStatus result = noErr;
02868
02869 llinfos << "Opening " << file_path << llendl;
02870 CFURLRef urlRef = NULL;
02871
02872 CFStringRef stringRef = CFStringCreateWithCString(NULL, file_path, kCFStringEncodingUTF8);
02873 if (stringRef)
02874 {
02875
02876
02877 urlRef = CFURLCreateWithString(NULL, stringRef, NULL);
02878
02879 if(urlRef == NULL)
02880 {
02881
02882
02883
02884 urlRef = CFURLCreateWithFileSystemPath(NULL, stringRef, kCFURLPOSIXPathStyle, false);
02885 }
02886
02887 CFRelease(stringRef);
02888 }
02889
02890 if (urlRef)
02891 {
02892 result = LSOpenCFURLRef(urlRef, NULL);
02893
02894 if (result != noErr)
02895 {
02896 llinfos << "Error " << result << " on open." << llendl;
02897 }
02898 CFRelease(urlRef);
02899 }
02900 else
02901 {
02902 llinfos << "Error: couldn't create URL." << llendl;
02903 }
02904 }
02905
02906 BOOL LLWindowMacOSX::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
02907 {
02908 BOOL retval = FALSE;
02909 OSErr error = noErr;
02910 NColorPickerInfo info;
02911
02912 memset(&info, 0, sizeof(info));
02913 info.theColor.color.rgb.red = (UInt16)(*r * 65535.f);
02914 info.theColor.color.rgb.green = (UInt16)(*g * 65535.f);
02915 info.theColor.color.rgb.blue = (UInt16)(*b * 65535.f);
02916 info.placeWhere = kCenterOnMainScreen;
02917
02918 if(gWindowImplementation != NULL)
02919 gWindowImplementation->beforeDialog();
02920
02921 error = NPickColor(&info);
02922
02923 if(gWindowImplementation != NULL)
02924 gWindowImplementation->afterDialog();
02925
02926 if (error == noErr)
02927 {
02928 retval = info.newColorChosen;
02929 if (info.newColorChosen)
02930 {
02931 *r = ((float) info.theColor.color.rgb.red) / 65535.0;
02932 *g = ((float) info.theColor.color.rgb.green) / 65535.0;
02933 *b = ((float) info.theColor.color.rgb.blue) / 65535.0;
02934 }
02935 }
02936 return (retval);
02937 }
02938
02939 static WindowRef dummywindowref = NULL;
02940
02941 void *LLWindowMacOSX::getPlatformWindow()
02942 {
02943 if(mWindow != NULL)
02944 return (void*)mWindow;
02945
02946
02947
02948
02949
02950 if(dummywindowref == NULL)
02951 {
02952 Rect window_rect = {100, 100, 200, 200};
02953
02954 dummywindowref = NewCWindow(
02955 NULL,
02956 &window_rect,
02957 "\p",
02958 false,
02959 zoomDocProc,
02960 kLastWindowOfClass,
02961 false,
02962 0);
02963 }
02964
02965 return (void*)dummywindowref;
02966 }
02967
02968 void LLWindowMacOSX::stopDockTileBounce()
02969 {
02970 NMRemove(&mBounceRec);
02971 mBounceTimer.stop();
02972 }
02973
02974
02975 static double getDictDouble (CFDictionaryRef refDict, CFStringRef key)
02976 {
02977 double double_value;
02978 CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key);
02979 if (!number_value)
02980 return -1;
02981 if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &double_value))
02982 return -1;
02983 return double_value;
02984 }
02985
02986
02987 static long getDictLong (CFDictionaryRef refDict, CFStringRef key)
02988 {
02989 long int_value;
02990 CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key);
02991 if (!number_value)
02992 return -1;
02993 if (!CFNumberGetValue(number_value, kCFNumberLongType, &int_value))
02994 return -1;
02995 return int_value;
02996 }
02997
02998 void LLWindowMacOSX::allowLanguageTextInput(BOOL b)
02999 {
03000 ScriptLanguageRecord script_language;
03001
03002 if (b == mLanguageTextInputAllowed)
03003 {
03004 return;
03005 }
03006 mLanguageTextInputAllowed = b;
03007
03008 if (b)
03009 {
03010 if (mTSMScriptCode != smRoman)
03011 {
03012 script_language.fScript = mTSMScriptCode;
03013 script_language.fLanguage = mTSMLangCode;
03014 SetTextServiceLanguage(&script_language);
03015 }
03016 }
03017 else
03018 {
03019 GetTextServiceLanguage(&script_language);
03020 mTSMScriptCode = script_language.fScript;
03021 mTSMLangCode = script_language.fLanguage;
03022 if (mTSMScriptCode != smRoman)
03023 {
03024 script_language.fScript = smRoman;
03025 script_language.fLanguage = langEnglish;
03026 SetTextServiceLanguage(&script_language);
03027 }
03028 }
03029 }
03030
03031 #endif // LL_DARWIN