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