diff options
author | Monty Brandenberg <monty@lindenlab.com> | 2013-09-19 13:13:37 -0400 |
---|---|---|
committer | Monty Brandenberg <monty@lindenlab.com> | 2013-09-19 13:13:37 -0400 |
commit | eaef5e63d5f5e3177fbd13de41aea12340f2fa30 (patch) | |
tree | 4da9c9af2741b2d33eb05cebe0291e50aada88ba /indra/llwindow/llwindowmacosx.cpp | |
parent | 195d319f65239238577ae15c22188da3839ae5cf (diff) | |
parent | ad777b46d0fe5d790e43efb1771e9f64f3ad3dfb (diff) |
Merge. Pull in viewer-release after materials viewer release.
Diffstat (limited to 'indra/llwindow/llwindowmacosx.cpp')
-rwxr-xr-x | indra/llwindow/llwindowmacosx.cpp | 2754 |
1 files changed, 487 insertions, 2267 deletions
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 97637c937f..56472e6b45 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -30,7 +30,6 @@ #include "llkeyboardmacosx.h" #include "llwindowcallbacks.h" -#include "llwindowmacosx-objc.h" #include "llpreeditor.h" #include "llerror.h" @@ -39,8 +38,8 @@ #include "lldir.h" #include "indra_constants.h" -#include <Carbon/Carbon.h> #include <OpenGL/OpenGL.h> +#include <CoreServices/CoreServices.h> extern BOOL gDebugWindowProc; @@ -58,7 +57,6 @@ const S32 MAX_NUM_RESOLUTIONS = 32; // BOOL LLWindowMacOSX::sUseMultGL = FALSE; -WindowRef LLWindowMacOSX::sMediaWindow = NULL; // Cross-platform bits: @@ -98,105 +96,9 @@ BOOL check_for_card(const char* RENDERER, const char* bad_card) // We may want to base this on the setting of _DEBUG... #define CAPTURE_ALL_DISPLAYS 0 -static double getDictDouble (CFDictionaryRef refDict, CFStringRef key); +//static double getDictDouble (CFDictionaryRef refDict, CFStringRef key); static long getDictLong (CFDictionaryRef refDict, CFStringRef key); - - - -// CarbonEvents we're interested in. -static EventTypeSpec WindowHandlerEventList[] = -{ - // Window-related events - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - { kEventClassWindow, kEventWindowShown }, - { kEventClassWindow, kEventWindowHidden }, - { kEventClassWindow, kEventWindowCollapsed }, - { kEventClassWindow, kEventWindowExpanded }, - { kEventClassWindow, kEventWindowGetClickActivation }, - { kEventClassWindow, kEventWindowClose }, - { kEventClassWindow, kEventWindowBoundsChanging }, - { kEventClassWindow, kEventWindowBoundsChanged }, - { kEventClassWindow, kEventWindowGetIdealSize }, - - // Mouse events - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseMoved }, - - // Keyboard events - // No longer handle raw key down events directly. - // When text input events come in, extract the raw key events from them and process at that point. - // This allows input methods to eat keystrokes the way they're supposed to. -// { kEventClassKeyboard, kEventRawKeyDown }, -// { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - // Text input events - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputShowHideBottomWindow }, - { kEventClassTextInput, kEventTextInputGetSelectedText }, - { kEventClassTextInput, kEventTextInputFilterText }, - - // TSM Document Access events (advanced input method support) - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument } -}; - -static EventTypeSpec GlobalHandlerEventList[] = -{ - // Mouse events - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseMoved }, - - // Keyboard events - // No longer handle raw key down events directly. - // When text input events come in, extract the raw key events from them and process at that point. - // This allows input methods to eat keystrokes the way they're supposed to. -// { kEventClassKeyboard, kEventRawKeyDown }, -// { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - // Text input events - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputShowHideBottomWindow }, - { kEventClassTextInput, kEventTextInputGetSelectedText }, - { kEventClassTextInput, kEventTextInputFilterText }, - - // TSM Document Access events (advanced input method support) - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument } -}; - -static EventTypeSpec CommandHandlerEventList[] = -{ - { kEventClassCommand, kEventCommandProcess } -}; - // MBW -- HACK ALERT // On the Mac, to put up an OS dialog in full screen mode, we must first switch OUT of full screen mode. // The proper way to do this is to bracket the dialog with calls to beforeDialog() and afterDialog(), but these @@ -204,8 +106,6 @@ static EventTypeSpec CommandHandlerEventList[] = // This assumes that there will be only one object of this class at any time. Hopefully this is true. static LLWindowMacOSX *gWindowImplementation = NULL; - - LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, @@ -233,8 +133,6 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mContext = NULL; mPixelFormat = NULL; mDisplay = CGMainDisplayID(); - mOldDisplayMode = NULL; - mTimer = NULL; mSimulatedRightClick = FALSE; mLastModifiers = 0; mHandsOffEvents = FALSE; @@ -246,60 +144,31 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mOverrideAspectRatio = 0.f; mMaximized = FALSE; mMinimized = FALSE; - mTSMDocument = NULL; // Just in case. mLanguageTextInputAllowed = FALSE; - mTSMScriptCode = 0; - mTSMLangCode = 0; mPreeditor = NULL; - mRawKeyEvent = NULL; mFSAASamples = fsaa_samples; mForceRebuild = FALSE; - // For reasons that aren't clear to me, LLTimers seem to be created in the "started" state. - // Since the started state of this one is used to track whether the NMRec has been installed, it wants to start out in the "stopped" state. - mBounceTimer.stop(); - // Get the original aspect ratio of the main device. mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay); // Stash the window title - strcpy((char*)mWindowTitle + 1, title.c_str()); /* Flawfinder: ignore */ - mWindowTitle[0] = title.length(); - - mEventHandlerUPP = NewEventHandlerUPP(staticEventHandler); - mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator); - mGlobalHandlerRef = NULL; - mWindowHandlerRef = NULL; + mWindowTitle = title; + //mWindowTitle[0] = title.length(); mDragOverrideCursor = -1; - // We're not clipping yet - SetRect( &mOldMouseClip, 0, 0, 0, 0 ); - // Set up global event handlers (the fullscreen case needs this) - InstallStandardEventHandler(GetApplicationEventTarget()); + //InstallStandardEventHandler(GetApplicationEventTarget()); // Stash an object pointer for OSMessageBox() gWindowImplementation = this; - // Create the GL context and set it up for windowed or fullscreen, as appropriate. if(createContext(x, y, width, height, 32, fullscreen, disable_vsync)) { if(mWindow != NULL) { - // MBW -- XXX -- I think we can now do this here? - // Constrain the window to the screen it's mostly on, resizing if necessary. - ConstrainWindowToScreen( - mWindow, - kWindowStructureRgn, - kWindowConstrainMayResize | - // kWindowConstrainStandardOptions | - 0, - NULL, - NULL); - - MacShowWindow(mWindow); - BringToFront(mWindow); + makeWindowOrderFront(mWindow); } if (!gGLManager.initGL()) @@ -317,480 +186,390 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, //start with arrow cursor initCursors(); setCursor( UI_CURSOR_ARROW ); + + allowLanguageTextInput(NULL, FALSE); } mCallbacks = callbacks; stop_glerror(); + + } -BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync) +// These functions are used as wrappers for our internal event handling callbacks. +// It's a good idea to wrap these to avoid reworking more code than we need to within LLWindow. + +bool callKeyUp(unsigned short key, unsigned int mask) { - OSStatus err; - BOOL glNeedsInit = FALSE; + return gKeyboard->handleKeyUp(key, mask); +} - if(mGlobalHandlerRef == NULL) - { - InstallApplicationEventHandler(mEventHandlerUPP, GetEventTypeCount (CommandHandlerEventList), CommandHandlerEventList, (void*)this, &mGlobalHandlerRef); - } +bool callKeyDown(unsigned short key, unsigned int mask) +{ + return gKeyboard->handleKeyDown(key, mask); +} - mFullscreen = fullscreen; +void callResetKeys() +{ + gKeyboard->resetKeys(); +} - if (mFullscreen && (mOldDisplayMode == NULL)) - { - LL_INFOS("Window") << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL; +bool callUnicodeCallback(wchar_t character, unsigned int mask) +{ + return gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask); +} - // NOTE: The refresh rate will be REPORTED AS 0 for many DVI and notebook displays. Plan accordingly. - double refresh = getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate); +void callFocus() +{ + if (gWindowImplementation) + { + gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); + } +} - // If the requested width or height is 0, find the best default for the monitor. - if((width == 0) || (height == 0)) - { - // Scan through the list of modes, looking for one which has: - // height between 700 and 800 - // aspect ratio closest to the user's original mode - S32 resolutionCount = 0; - LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount); +void callFocusLost() +{ + gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); +} - if(resolutionList != NULL) - { - F32 closestAspect = 0; - U32 closestHeight = 0; - U32 closestWidth = 0; - int i; +void callRightMouseDown(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleRightMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - LL_DEBUGS("Window") << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL; +void callRightMouseUp(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleRightMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - for(i=0; i < resolutionCount; i++) - { - F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight; +void callLeftMouseDown(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - LL_DEBUGS("Window") << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL; +void callLeftMouseUp(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); + +} - if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) && - (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio))) - { - LL_DEBUGS("Window") << " (new closest mode) " << LL_ENDL; +void callDoubleClick(float *pos, MASK mask) +{ + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleDoubleClick(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - // This is the closest mode we've seen yet. - closestWidth = resolutionList[i].mWidth; - closestHeight = resolutionList[i].mHeight; - closestAspect = aspect; - } - } +void callResize(unsigned int width, unsigned int height) +{ + if (gWindowImplementation != NULL) + { + gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height); + } +} - width = closestWidth; - height = closestHeight; - } - } +void callMouseMoved(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + float deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); + //gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0); +} - if((width == 0) || (height == 0)) - { - // Mode search failed for some reason. Use the old-school default. - width = 1024; - height = 768; - } +void callScrollMoved(float delta) +{ + gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, delta); +} - if (true) - { - // Fullscreen support - CFDictionaryRef refDisplayMode = 0; - boolean_t exactMatch = false; - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - CGCaptureAllDisplays (); -#else - // Capture only the main display (useful for debugging) - CGDisplayCapture (mDisplay); -#endif +void callMouseExit() +{ + gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation); +} - // Switch the display to the desired resolution and refresh - refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate( - mDisplay, - BITS_PER_PIXEL, - width, - height, - refresh, - &exactMatch); +void callWindowFocus() +{ + gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); +} - if (refDisplayMode) - { - LL_DEBUGS("Window") << "createContext: switching display resolution" << LL_ENDL; - mOldDisplayMode = CGDisplayCurrentMode (mDisplay); - CGDisplaySwitchToMode (mDisplay, refDisplayMode); - // CFRelease(refDisplayMode); +void callWindowUnfocus() +{ + gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); +} - AddEventTypesToHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList); - } +void callDeltaUpdate(float *delta, MASK mask) +{ + gWindowImplementation->updateMouseDeltas(delta); +} +void callMiddleMouseDown(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + float deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMiddleMouseDown(gWindowImplementation, outCoords, mask); +} - mFullscreen = TRUE; - mFullscreenWidth = CGDisplayPixelsWide(mDisplay); - mFullscreenHeight = CGDisplayPixelsHigh(mDisplay); - mFullscreenBits = CGDisplayBitsPerPixel(mDisplay); - mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate)); +void callMiddleMouseUp(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + float deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask); +} - LL_INFOS("Window") << "Running at " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; - } - else - { - // No fullscreen support - mFullscreen = FALSE; - mFullscreenWidth = -1; - mFullscreenHeight = -1; - mFullscreenBits = -1; - mFullscreenRefresh = -1; - - std::string error= llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height); - OSMessageBox(error, "Error", OSMB_OK); - } - } +void callModifier(MASK mask) +{ + gKeyboard->handleModifier(mask); +} - if(!mFullscreen && (mWindow == NULL)) - { - //int displayWidth = CGDisplayPixelsWide(mDisplay); - //int displayHeight = CGDisplayPixelsHigh(mDisplay); - //const int menuBarPlusTitleBar = 44; // Ugly magic number. +void callHandleDragEntered(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING); +} - LL_DEBUGS("Window") << "createContext: creating window" << LL_ENDL; +void callHandleDragExited(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING); +} - mPreviousWindowRect.left = (long) x; - mPreviousWindowRect.right = (long) x + width; - mPreviousWindowRect.top = (long) y; - mPreviousWindowRect.bottom = (long) y + height; +void callHandleDragUpdated(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK); +} - //----------------------------------------------------------------------- - // Create the window - //----------------------------------------------------------------------- - mWindow = NewCWindow( - NULL, - &mPreviousWindowRect, - mWindowTitle, - false, // Create the window invisible. Whoever calls createContext() should show it after any moving/resizing. - // noGrowDocProc, // Window with no grow box and no zoom box - zoomDocProc, // Window with a grow box and a zoom box - // zoomNoGrow, // Window with a zoom box but no grow box - kFirstWindowOfClass, - true, - (long)this); +void callHandleDragDropped(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED); +} - if (!mWindow) +void callQuitHandler() +{ + if (gWindowImplementation) + { + if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation)) { - setupFailure("Window creation error", "Error", OSMB_OK); - return FALSE; + gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation); } - - // Turn on live resize. - // For this to work correctly, we need to be able to call LLViewerWindow::draw from - // the event handler for kEventWindowBoundsChanged. It's not clear that we have access from here. - // err = ChangeWindowAttributes(mWindow, kWindowLiveResizeAttribute, 0); - - // Set up window event handlers (some window-related events ONLY go to window handlers.) - InstallStandardEventHandler(GetWindowEventTarget(mWindow)); - InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler -#if LL_OS_DRAGDROP_ENABLED - InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this ); - InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this ); -#endif // LL_OS_DRAGDROP_ENABLED } +} +void getPreeditSelectionRange(int *position, int *length) +{ + if (gWindowImplementation->getPreeditor()) { - // Create and initialize our TSM document for language text input. - // If an error occured, we can do nothing better than simply ignore it. - // mTSMDocument will be kept NULL in case. - if (mTSMDocument) - { - DeactivateTSMDocument(mTSMDocument); - DeleteTSMDocument(mTSMDocument); - mTSMDocument = NULL; - } - static InterfaceTypeList types = { kUnicodeDocument }; - err = NewTSMDocument(1, types, &mTSMDocument, 0); - if (err != noErr) - { - LL_WARNS("Window") << "createContext: couldn't create a TSMDocument (" << err << ")" << LL_ENDL; - } - if (mTSMDocument) - { - ActivateTSMDocument(mTSMDocument); - allowLanguageTextInput(NULL, FALSE); - } + gWindowImplementation->getPreeditor()->getSelectionRange(position, length); } +} - if(mContext == NULL) +void getPreeditMarkedRange(int *position, int *length) +{ + if (gWindowImplementation->getPreeditor()) { - AGLRendererInfo rendererInfo = NULL; - - //----------------------------------------------------------------------- - // Create GL drawing context - //----------------------------------------------------------------------- - - if(mPixelFormat == NULL) - { - if(mFullscreen) - { - GLint fullscreenAttrib[] = - { - AGL_RGBA, - AGL_FULLSCREEN, - AGL_NO_RECOVERY, - AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, - AGL_SAMPLES_ARB, mFSAASamples, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, - AGL_ACCELERATED, - AGL_RED_SIZE, 8, - AGL_GREEN_SIZE, 8, - AGL_BLUE_SIZE, 8, - AGL_ALPHA_SIZE, 8, - AGL_DEPTH_SIZE, 24, - AGL_STENCIL_SIZE, 8, - AGL_NONE - }; - - LL_DEBUGS("Window") << "createContext: creating fullscreen pixelformat" << LL_ENDL; - - GDHandle gdhDisplay = NULL; - err = DMGetGDeviceByDisplayID ((DisplayIDType)mDisplay, &gdhDisplay, false); - - mPixelFormat = aglChoosePixelFormat(&gdhDisplay, 1, fullscreenAttrib); - rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1); - } - else - { - // NOTE from Leslie: - // - // AGL_NO_RECOVERY, when combined with AGL_ACCELERATED prevents software rendering - // fallback which means we won't hvae shaders that compile and link but then don't - // work. The drawback is that our shader compilation will be a bit more finicky though. - - GLint windowedAttrib[] = - { - AGL_RGBA, - AGL_NO_RECOVERY, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, - AGL_ACCELERATED, - AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, - AGL_SAMPLES_ARB, mFSAASamples, - AGL_RED_SIZE, 8, - AGL_GREEN_SIZE, 8, - AGL_BLUE_SIZE, 8, - AGL_ALPHA_SIZE, 8, - AGL_DEPTH_SIZE, 24, - AGL_STENCIL_SIZE, 8, - AGL_NONE - }; - - LL_DEBUGS("Window") << "createContext: creating windowed pixelformat" << LL_ENDL; - - mPixelFormat = aglChoosePixelFormat(NULL, 0, windowedAttrib); - - GDHandle gdhDisplay = GetMainDevice(); - rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1); - } - - // May want to get the real error text like this: - // (char *) aglErrorString(aglGetError()); - - if(aglGetError() != AGL_NO_ERROR) - { - setupFailure("Can't find suitable pixel format", "Error", OSMB_OK); - return FALSE; - } - } - - if(mPixelFormat) - { - LL_DEBUGS("Window") << "createContext: creating GL context" << LL_ENDL; - mContext = aglCreateContext(mPixelFormat, NULL); - } - - if(mContext == NULL) - { - setupFailure("Can't make GL context", "Error", OSMB_OK); - return FALSE; - } - - gGLManager.mVRAM = 0; - - if(rendererInfo != NULL) - { - GLint result; - - if(aglDescribeRenderer(rendererInfo, AGL_VIDEO_MEMORY, &result)) - { - // llinfos << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) returned " << result << llendl; - gGLManager.mVRAM = result / (1024 * 1024); - } - else - { - // llinfos << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) failed." << llendl; - } - - // This could be useful at some point, if it takes into account the memory already used by screen buffers, etc... - if(aglDescribeRenderer(rendererInfo, AGL_TEXTURE_MEMORY, &result)) - { - // llinfos << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) returned " << result << llendl; - } - else - { - // llinfos << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) failed." << llendl; - } - - aglDestroyRendererInfo(rendererInfo); - } - - // Since we just created the context, it needs to be set up. - glNeedsInit = TRUE; + gWindowImplementation->getPreeditor()->getPreeditRange(position, length); } +} - // Hook up the context to a drawable - if (mFullscreen && (mOldDisplayMode != NULL)) +void setPreeditMarkedRange(int position, int length) +{ + if (gWindowImplementation->getPreeditor()) { - // We successfully captured the display. Use a fullscreen drawable - - LL_DEBUGS("Window") << "createContext: attaching fullscreen drawable" << LL_ENDL; - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - aglDisable (mContext, AGL_FS_CAPTURE_SINGLE); -#else - // Capture only the main display (useful for debugging) - aglEnable (mContext, AGL_FS_CAPTURE_SINGLE); -#endif - - if (!aglSetFullScreen (mContext, 0, 0, 0, 0)) - { - setupFailure("Can't set GL fullscreen", "Error", OSMB_OK); - return FALSE; - } + gWindowImplementation->getPreeditor()->markAsPreedit(position, length); } - else if(!mFullscreen && (mWindow != NULL)) - { - LL_DEBUGS("Window") << "createContext: attaching windowed drawable" << LL_ENDL; +} - // We created a window. Use it as the drawable. - if(!aglSetDrawable(mContext, GetWindowPort (mWindow))) - { - setupFailure("Can't set GL drawable", "Error", OSMB_OK); - return FALSE; - } - } - else +bool handleUnicodeCharacter(wchar_t c) +{ + bool success = false; + if (gWindowImplementation->getPreeditor()) { - setupFailure("Can't get fullscreen or windowed drawable.", "Error", OSMB_OK); - return FALSE; + success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); } + + return success; +} - if(mContext != NULL) +void resetPreedit() +{ + if (gWindowImplementation->getPreeditor()) { - LL_DEBUGS("Window") << "createContext: setting current context" << LL_ENDL; + gWindowImplementation->getPreeditor()->resetPreedit(); + } +} - if (!aglSetCurrentContext(mContext)) +// For reasons of convenience, handle IME updates here. +// This largely mirrors the old implementation, only sans the carbon parameters. +void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments) +{ + if (gWindowImplementation->getPreeditor()) + { + LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); + preeditor->resetPreedit(); + // This should be a viable replacement for the kEventParamTextInputSendReplaceRange parameter. + if (replacementRange[0] < replacementRange[1]) { - setupFailure("Can't activate GL rendering context", "Error", OSMB_OK); - return FALSE; + const LLWString& text = preeditor->getPreeditString(); + const S32 location = wstring_wstring_length_from_utf16_length(text, 0, replacementRange[0]); + const S32 length = wstring_wstring_length_from_utf16_length(text, location, replacementRange[1]); + preeditor->markAsPreedit(location, length); } + + LLWString fix_str = utf16str_to_wstring(llutf16string(unitext, text_len)); + + S32 caret_position = fix_str.length(); + + preeditor->updatePreedit(fix_str, segments.seg_lengths, segments.seg_standouts, caret_position); } +} - if(glNeedsInit) +void getPreeditLocation(float *location, unsigned int length) +{ + if (gWindowImplementation->getPreeditor()) { - // Check for some explicitly unsupported cards. - const char* RENDERER = (const char*) glGetString(GL_RENDERER); - - const char* CARD_LIST[] = - { "RAGE 128", - "RIVA TNT2", - "Intel 810", - "3Dfx/Voodoo3", - "Radeon 7000", - "Radeon 7200", - "Radeon 7500", - "Radeon DDR", - "Radeon VE", - "GDI Generic" }; - const S32 CARD_COUNT = LL_ARRAY_SIZE(CARD_LIST); - - // Future candidates: - // ProSavage/Twister - // SuperSavage + LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); + LLCoordGL coord; + LLCoordScreen screen; + LLRect rect; + + preeditor->getPreeditLocation(length, &coord, &rect, NULL); + + float c[4] = {coord.mX, coord.mY, 0, 0}; + + convertRectToScreen(gWindowImplementation->getWindow(), c); + + location[0] = c[0]; + location[1] = c[1]; + } +} - S32 i; - for (i = 0; i < CARD_COUNT; i++) +void LLWindowMacOSX::updateMouseDeltas(float* deltas) +{ + if (mCursorDecoupled) + { + mCursorLastEventDeltaX = llround(deltas[0]); + mCursorLastEventDeltaY = llround(-deltas[1]); + + if (mCursorIgnoreNextDelta) { - if (check_for_card(RENDERER, CARD_LIST[i])) - { - close(); - return FALSE; - } + mCursorLastEventDeltaX = 0; + mCursorLastEventDeltaY = 0; + mCursorIgnoreNextDelta = FALSE; } + } else { + mCursorLastEventDeltaX = 0; + mCursorLastEventDeltaY = 0; } +} + +void LLWindowMacOSX::getMouseDeltas(float* delta) +{ + delta[0] = mCursorLastEventDeltaX; + delta[1] = mCursorLastEventDeltaY; +} - GLint colorBits, alphaBits, depthBits, stencilBits; +BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync) +{ + BOOL glNeedsInit = FALSE; - if( !aglDescribePixelFormat(mPixelFormat, AGL_BUFFER_SIZE, &colorBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_ALPHA_SIZE, &alphaBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_DEPTH_SIZE, &depthBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_STENCIL_SIZE, &stencilBits)) + mFullscreen = fullscreen; + + if (mWindow == NULL) { - close(); - setupFailure("Can't get pixel format description", "Error", OSMB_OK); - return FALSE; + mWindow = getMainAppWindow(); } - LL_INFOS("GLInit") << "GL buffer: Color Bits " << S32(colorBits) - << " Alpha Bits " << S32(alphaBits) - << " Depth Bits " << S32(depthBits) - << " Stencil Bits" << S32(stencilBits) - << LL_ENDL; - - if (colorBits < 32) + if(mContext == NULL) { - close(); - setupFailure( - "Second Life requires True Color (32-bit) to run in a window.\n" - "Please go to Control Panels -> Display -> Settings and\n" - "set the screen to 32-bit color.\n" - "Alternately, if you choose to run fullscreen, Second Life\n" - "will automatically adjust the screen each time it runs.", - "Error", - OSMB_OK); - return FALSE; + // Our OpenGL view is already defined within SecondLife.xib. + // Get the view instead. + mGLView = createOpenGLView(mWindow, mFSAASamples, !disable_vsync); + mContext = getCGLContextObj(mGLView); + + // Since we just created the context, it needs to be set up. + glNeedsInit = TRUE; + + gGLManager.mVRAM = getVramSize(mGLView); } + + // This sets up our view to recieve text from our non-inline text input window. + setupInputWindow(mWindow, mGLView); + + // Hook up the context to a drawable - if (alphaBits < 8) + if(mContext != NULL) { - close(); - setupFailure( - "Second Life is unable to run because it can't get an 8 bit alpha\n" - "channel. Usually this is due to video card driver issues.\n" - "Please make sure you have the latest video card drivers installed.\n" - "Also be sure your monitor is set to True Color (32-bit) in\n" - "Control Panels -> Display -> Settings.\n" - "If you continue to receive this message, contact customer service.", - "Error", - OSMB_OK); - return FALSE; + + + U32 err = CGLSetCurrentContext(mContext); + if (err != kCGLNoError) + { + setupFailure("Can't activate GL rendering context", "Error", OSMB_OK); + return FALSE; + } } // Disable vertical sync for swap GLint frames_per_swap = 0; if (disable_vsync) { - LL_DEBUGS("GLInit") << "Disabling vertical sync" << LL_ENDL; frames_per_swap = 0; } else { - LL_DEBUGS("GLinit") << "Keeping vertical sync" << LL_ENDL; frames_per_swap = 1; } - aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap); + + CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap); //enable multi-threaded OpenGL if (sUseMultGL) @@ -809,109 +588,17 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL; } } - - // Don't need to get the current gamma, since there's a call that restores it to the system defaults. + makeFirstResponder(mWindow, mGLView); + return TRUE; } -// changing fullscreen resolution, or switching between windowed and fullscreen mode. +// We only support OS X 10.7's fullscreen app mode which is literally a full screen window that fills a virtual desktop. +// This makes this method obsolete. BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp) { - BOOL needsRebuild = FALSE; - BOOL result = true; - - if(fullscreen) - { - if(mFullscreen) - { - // Switching resolutions in fullscreen mode. Don't need to rebuild for this. - // Fullscreen support - CFDictionaryRef refDisplayMode = 0; - boolean_t exactMatch = false; - - // Switch the display to the desired resolution and refresh - refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate( - mDisplay, - BITS_PER_PIXEL, - size.mX, - size.mY, - getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate), - &exactMatch); - - if (refDisplayMode) - { - CGDisplaySwitchToMode (mDisplay, refDisplayMode); - // CFRelease(refDisplayMode); - } - - mFullscreenWidth = CGDisplayPixelsWide(mDisplay); - mFullscreenHeight = CGDisplayPixelsHigh(mDisplay); - mFullscreenBits = CGDisplayBitsPerPixel(mDisplay); - mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate)); - - LL_INFOS("Window") << "Switched resolution to " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; - - // Update the GL context to the new screen size - if (!aglUpdateContext(mContext)) - { - setupFailure("Can't set GL fullscreen", "Error", OSMB_OK); - result = FALSE; - } - } - else - { - // Switching from windowed to fullscreen - needsRebuild = TRUE; - } - } - else - { - if(mFullscreen) - { - // Switching from fullscreen to windowed - needsRebuild = TRUE; - } - else - { - // Windowed to windowed -- not sure why we would be called like this. Just change the window size. - // The bounds changed event handler will do the rest. - if(mWindow != NULL) - { - ::SizeWindow(mWindow, size.mX, size.mY, true); - } - } - } - - stop_glerror(); - if(needsRebuild || mForceRebuild) - { - mForceRebuild = FALSE; - destroyContext(); - result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync); - if (result) - { - if(mWindow != NULL) - { - MacShowWindow(mWindow); - BringToFront(mWindow); - } - - llverify(gGLManager.initGL()); - - //start with arrow cursor - initCursors(); - setCursor( UI_CURSOR_ARROW ); - } - } - - stop_glerror(); - - return result; + return FALSE; } void LLWindowMacOSX::destroyContext() @@ -925,32 +612,7 @@ void LLWindowMacOSX::destroyContext() if(mContext != NULL) { LL_DEBUGS("Window") << "destroyContext: unhooking drawable " << LL_ENDL; - - aglSetCurrentContext (NULL); - aglSetDrawable(mContext, NULL); - } - - // Make sure the display resolution gets restored - if(mOldDisplayMode != NULL) - { - LL_DEBUGS("Window") << "destroyContext: restoring display resolution " << LL_ENDL; - - CGDisplaySwitchToMode (mDisplay, mOldDisplayMode); - -#if CAPTURE_ALL_DISPLAYS - // Uncapture all displays (may want to do this for final build) - CGReleaseAllDisplays (); -#else - // Uncapture only the main display (useful for debugging) - CGDisplayRelease (mDisplay); -#endif - - // CFRelease(mOldDisplayMode); - - mOldDisplayMode = NULL; - - // Remove the global event handlers the fullscreen case needed - RemoveEventTypesFromHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList); + CGLSetCurrentContext(NULL); } // Clean up remaining GL state before blowing away window @@ -959,49 +621,29 @@ void LLWindowMacOSX::destroyContext() // Clean up the pixel format if(mPixelFormat != NULL) { - LL_DEBUGS("Window") << "destroyContext: destroying pixel format " << LL_ENDL; - aglDestroyPixelFormat(mPixelFormat); + CGLDestroyPixelFormat(mPixelFormat); mPixelFormat = NULL; } - // Remove any Carbon Event handlers we installed - if(mGlobalHandlerRef != NULL) - { - LL_DEBUGS("Window") << "destroyContext: removing global event handler" << LL_ENDL; - RemoveEventHandler(mGlobalHandlerRef); - mGlobalHandlerRef = NULL; - } - - if(mWindowHandlerRef != NULL) + // Clean up the GL context + if(mContext != NULL) { - LL_DEBUGS("Window") << "destroyContext: removing window event handler" << LL_ENDL; - RemoveEventHandler(mWindowHandlerRef); - mWindowHandlerRef = NULL; + CGLDestroyContext(mContext); } - - // Cleanup any TSM document we created. - if(mTSMDocument != NULL) + + // Destroy our LLOpenGLView + if(mGLView != NULL) { - LL_DEBUGS("Window") << "destroyContext: deleting TSM document" << LL_ENDL; - DeactivateTSMDocument(mTSMDocument); - DeleteTSMDocument(mTSMDocument); - mTSMDocument = NULL; + removeGLView(mGLView); + mGLView = NULL; } - + // Close the window if(mWindow != NULL) { - LL_DEBUGS("Window") << "destroyContext: disposing window" << LL_ENDL; - DisposeWindow(mWindow); - mWindow = NULL; - } - - // Clean up the GL context - if(mContext != NULL) - { - LL_DEBUGS("Window") << "destroyContext: destroying GL context" << LL_ENDL; - aglDestroyContext(mContext); - mContext = NULL; + NSWindowRef dead_window = mWindow; + mWindow = NULL; + closeWindow(dead_window); } } @@ -1022,17 +664,11 @@ LLWindowMacOSX::~LLWindowMacOSX() void LLWindowMacOSX::show() { - if(IsWindowCollapsed(mWindow)) - CollapseWindow(mWindow, false); - - MacShowWindow(mWindow); - BringToFront(mWindow); } void LLWindowMacOSX::hide() { setMouseClipping(FALSE); - HideWindow(mWindow); } //virtual @@ -1040,7 +676,6 @@ void LLWindowMacOSX::minimize() { setMouseClipping(FALSE); showCursor(); - CollapseWindow(mWindow, true); } //virtual @@ -1086,7 +721,6 @@ BOOL LLWindowMacOSX::getVisible() result = TRUE; }if (mWindow) { - if(MacIsWindowVisible(mWindow)) result = TRUE; } @@ -1107,7 +741,6 @@ BOOL LLWindowMacOSX::maximize() { if (mWindow && !mMaximized) { - ZoomWindow(mWindow, inContent, true); } return mMaximized; @@ -1120,58 +753,13 @@ BOOL LLWindowMacOSX::getFullscreen() void LLWindowMacOSX::gatherInput() { - // stop bouncing icon after fixed period of time - if (mBounceTimer.getStarted() && mBounceTimer.getElapsedTimeF32() > mBounceTime) - { - stopDockTileBounce(); - } - - // Use the old-school version so we get AppleEvent handler dispatch and menuselect handling. - // Anything that has an event handler will get processed inside WaitNextEvent, so we only need to handle - // the odd stuff here. - EventRecord evt; - while(WaitNextEvent(everyEvent, &evt, 0, NULL)) - { - // printf("WaitNextEvent returned true, event is %d.\n", evt.what); - switch(evt.what) - { - case mouseDown: - { - short part; - WindowRef window; - long selectResult; - part = FindWindow(evt.where, &window); - switch ( part ) - { - case inMenuBar: - selectResult = MenuSelect(evt.where); - - HiliteMenu(0); - break; - } - } - break; - - case kHighLevelEvent: - AEProcessAppleEvent (&evt); - break; - - case updateEvt: - // We shouldn't be getting these regularly (since our window will be buffered), but we need to handle them correctly... - BeginUpdate((WindowRef)evt.message); - EndUpdate((WindowRef)evt.message); - break; - - } - } - updateCursor(); } BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) { - Rect window_rect; - OSStatus err = -1; + float rect[4]; + S32 err = -1; if(mFullscreen) { @@ -1181,10 +769,10 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); + getContentViewBounds(mWindow, rect); - position->mX = window_rect.left; - position->mY = window_rect.top; + position->mX = rect[0]; + position->mY = rect[1]; } else { @@ -1196,8 +784,8 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) { - Rect window_rect; - OSStatus err = -1; + float rect[4]; + S32 err = -1; if(mFullscreen) { @@ -1207,10 +795,10 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); + getContentViewBounds(mWindow, rect); - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + size->mX = rect[2]; + size->mY = rect[3]; } else { @@ -1222,9 +810,9 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) BOOL LLWindowMacOSX::getSize(LLCoordWindow *size) { - Rect window_rect; - OSStatus err = -1; - + float rect[4]; + S32 err = -1; + if(mFullscreen) { size->mX = mFullscreenWidth; @@ -1233,16 +821,16 @@ BOOL LLWindowMacOSX::getSize(LLCoordWindow *size) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); - - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + getContentViewBounds(mWindow, rect); + + size->mX = rect[2]; + size->mY = rect[3]; } else { llerrs << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << llendl; } - + return (err == noErr); } @@ -1250,7 +838,8 @@ BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position) { if(mWindow) { - MacMoveWindow(mWindow, position.mX, position.mY, false); + float pos[2] = {position.mX, position.mY}; + setWindowPos(mWindow, pos); } return TRUE; @@ -1260,45 +849,35 @@ BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size) { if(mWindow) { - SizeWindow(mWindow, size.mX, size.mY, true); + LLCoordWindow to; + convertCoords(size, &to); + setWindowSize(mWindow, to.mX, to.mY); + return TRUE; } - return TRUE; + return FALSE; } BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size) { - Rect client_rect; if (mWindow) { - OSStatus err = GetWindowBounds(mWindow, kWindowContentRgn, &client_rect); - if (err == noErr) - { - client_rect.right = client_rect.left + size.mX; - client_rect.bottom = client_rect.top + size.mY; - err = SetWindowBounds(mWindow, kWindowContentRgn, &client_rect); - } - if (err == noErr) - { - return TRUE; - } - else - { - llinfos << "Error setting size" << err << llendl; - return FALSE; - } + const int titlePadding = 22; + setWindowSize(mWindow, size.mX, size.mY + titlePadding); + return TRUE; } + return FALSE; } void LLWindowMacOSX::swapBuffers() { - aglSwapBuffers(mContext); + CGLFlushDrawable(mContext); } F32 LLWindowMacOSX::getGamma() { - F32 result = 1.8; // Default to something sane + F32 result = 2.2; // Default to something sane CGGammaValue redMin; CGGammaValue redMax; @@ -1454,39 +1033,15 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) return result; } -static void fixOrigin(void) -{ - GrafPtr port; - Rect portrect; - - ::GetPort(&port); - ::GetPortBounds(port, &portrect); - if((portrect.left != 0) || (portrect.top != 0)) - { - // Mozilla sometimes changes our port origin. - ::SetOrigin(0,0); - } -} - BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position) { - Point cursor_point; + float cursor_point[2]; LLCoordScreen screen_pos; - GrafPtr save; if(mWindow == NULL) return FALSE; - - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - // gets the mouse location in local coordinates - ::GetMouse(&cursor_point); - -// lldebugs << "getCursorPosition(): cursor is at " << cursor_point.h << ", " << cursor_point.v << " port origin: " << portrect.left << ", " << portrect.top << llendl; - - ::SetPort(save); + + getCursorPos(mWindow, cursor_point); if(mCursorDecoupled) { @@ -1499,12 +1054,12 @@ BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position) // CGGetLastMouseDelta may behave strangely when the cursor's first captured. // Stash in the event handler instead. - cursor_point.h += mCursorLastEventDeltaX; - cursor_point.v += mCursorLastEventDeltaY; + cursor_point[0] += mCursorLastEventDeltaX; + cursor_point[1] += mCursorLastEventDeltaY; } - position->mX = cursor_point.h; - position->mY = cursor_point.v; + position->mX = cursor_point[0]; + position->mY = cursor_point[1]; return TRUE; } @@ -1521,7 +1076,6 @@ void LLWindowMacOSX::adjustCursorDecouple(bool warpingMouse) // llinfos << "adjustCursorDecouple: decoupling cursor" << llendl; CGAssociateMouseAndMouseCursorPosition(false); mCursorDecoupled = true; - FlushSpecificEventsFromQueue(GetCurrentEventQueue(), mMoveEventCampartorUPP, NULL); mCursorIgnoreNextDelta = TRUE; } } @@ -1568,179 +1122,46 @@ F32 LLWindowMacOSX::getPixelAspectRatio() // MBW -- XXX -- There's got to be a better way than this. Find it, please... +// Since we're no longer supporting the "typical" fullscreen mode with CGL or NSOpenGL anymore, these are unnecessary. -Geenz void LLWindowMacOSX::beforeDialog() { - if(mFullscreen) - { - -#if CAPTURE_ALL_DISPLAYS - // Uncapture all displays (may want to do this for final build) - CGReleaseAllDisplays (); -#else - // Uncapture only the main display (useful for debugging) - CGDisplayRelease (mDisplay); -#endif - // kDocumentWindowClass - // kMovableModalWindowClass - // kAllWindowClasses - - // GLint order = 0; - // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order); - aglSetDrawable(mContext, NULL); - // GetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), &oldWindowLevel); - // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), CGShieldingWindowLevel()); - - mHandsOffEvents = TRUE; - - } } void LLWindowMacOSX::afterDialog() { - if(mFullscreen) - { - mHandsOffEvents = FALSE; - - // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), oldWindowLevel); - aglSetFullScreen(mContext, 0, 0, 0, 0); - // GLint order = 1; - // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order); - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - CGCaptureAllDisplays (); -#else - // Capture only the main display (useful for debugging) - CGDisplayCapture (mDisplay); -#endif - } } void LLWindowMacOSX::flashIcon(F32 seconds) { - // Don't do this if we're already started, since this would try to install the NMRec twice. - if(!mBounceTimer.getStarted()) - { - OSErr err; - - mBounceTime = seconds; - memset(&mBounceRec, 0, sizeof(mBounceRec)); - mBounceRec.qType = nmType; - mBounceRec.nmMark = 1; - err = NMInstall(&mBounceRec); - if(err == noErr) - { - mBounceTimer.start(); - } - else - { - // This is very not-fatal (only problem is the icon will not bounce), but we'd like to find out about it somehow... - llinfos << "NMInstall failed with error code " << err << llendl; - } - } + // For consistency with OS X conventions, the number of seconds given is ignored and + // left up to the OS (which will actually bounce it for one second). + requestUserAttention(); } BOOL LLWindowMacOSX::isClipboardTextAvailable() { - OSStatus err; - ScrapRef scrap; - ScrapFlavorFlags flags; - BOOL result = false; - - err = GetCurrentScrap(&scrap); - - if(err == noErr) - { - err = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &flags); - } - - if(err == noErr) - result = true; - - return result; + return pasteBoardAvailable(); } BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst) -{ - OSStatus err; - ScrapRef scrap; - Size len; - BOOL result = false; - - err = GetCurrentScrap(&scrap); - - if(err == noErr) +{ + llutf16string str(copyFromPBoard()); + dst = utf16str_to_wstring(str); + if (dst != L"") { - err = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &len); - } - - if((err == noErr) && (len > 0)) - { - int u16len = len / sizeof(U16); - U16 *temp = new U16[u16len + 1]; - if (temp) - { - memset(temp, 0, (u16len + 1) * sizeof(temp[0])); - err = GetScrapFlavorData(scrap, kScrapFlavorTypeUnicode, &len, temp); - if (err == noErr) - { - // convert \r\n to \n and \r to \n in the incoming text. - U16 *s, *d; - for(s = d = temp; s[0] != '\0'; s++, d++) - { - if(s[0] == '\r') - { - if(s[1] == '\n') - { - // CRLF, a.k.a. DOS newline. Collapse to a single '\n'. - s++; - } - - d[0] = '\n'; - } - else - { - d[0] = s[0]; - } - } - - d[0] = '\0'; - - dst = utf16str_to_wstring(temp); - - result = true; - } - delete[] temp; - } + return true; + } else { + return false; } - - return result; } BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s) { - OSStatus err; - ScrapRef scrap; - //Size len; - //char *temp; BOOL result = false; - - if (!s.empty()) - { - err = GetCurrentScrap(&scrap); - if (err == noErr) - err = ClearScrap(&scrap); - - if (err == noErr) - { - llutf16string utf16str = wstring_to_utf16str(s); - size_t u16len = utf16str.length() * sizeof(U16); - err = PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone, u16len, utf16str.data()); - if (err == noErr) - result = true; - } - } + llutf16string utf16str = wstring_to_utf16str(s); + + result = copyToPBoard(utf16str.data(), utf16str.length()); return result; } @@ -1806,122 +1227,52 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) { - S32 client_height; - Rect client_rect; - - if(mFullscreen) - { - // In the fullscreen case, the "window" is the entire screen. - client_rect.left = 0; - client_rect.top = 0; - client_rect.right = mFullscreenWidth; - client_rect.bottom = mFullscreenHeight; - } - else if (!mWindow || - (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) || - NULL == to) - { - return FALSE; - } - to->mX = from.mX; - client_height = client_rect.bottom - client_rect.top; - to->mY = client_height - from.mY - 1; - + to->mY = from.mY; return TRUE; } BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) { - S32 client_height; - Rect client_rect; - - if(mFullscreen) - { - // In the fullscreen case, the "window" is the entire screen. - client_rect.left = 0; - client_rect.top = 0; - client_rect.right = mFullscreenWidth; - client_rect.bottom = mFullscreenHeight; - } - else if (!mWindow || - (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) || - NULL == to) - { - return FALSE; - } - to->mX = from.mX; - client_height = client_rect.bottom - client_rect.top; - to->mY = client_height - from.mY - 1; - + to->mY = from.mY; return TRUE; } BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) { - if(mFullscreen) - { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) + if(mWindow) { - GrafPtr save; - Point mouse_point; - - mouse_point.h = from.mX; - mouse_point.v = from.mY; - - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - ::GlobalToLocal(&mouse_point); + float mouse_point[2]; - to->mX = mouse_point.h; - to->mY = mouse_point.v; + mouse_point[0] = from.mX; + mouse_point[1] = from.mY; + + convertScreenToWindow(mWindow, mouse_point); - ::SetPort(save); + to->mX = mouse_point[0]; + to->mY = mouse_point[1]; return TRUE; } - return FALSE; } BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) { - if(mFullscreen) - { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) + if(mWindow) { - GrafPtr save; - Point mouse_point; - - mouse_point.h = from.mX; - mouse_point.v = from.mY; - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - LocalToGlobal(&mouse_point); + float mouse_point[2]; - to->mX = mouse_point.h; - to->mY = mouse_point.v; + mouse_point[0] = from.mX; + mouse_point[1] = from.mY; + convertWindowToScreen(mWindow, mouse_point); - ::SetPort(save); + to->mX = mouse_point[0]; + to->mY = mouse_point[1]; return TRUE; } - return FALSE; } @@ -1949,862 +1300,6 @@ void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& ca OSMessageBox(text, caption, type); } -pascal Boolean LLWindowMacOSX::staticMoveEventComparator( EventRef event, void* data) -{ - UInt32 evtClass = GetEventClass (event); - UInt32 evtKind = GetEventKind (event); - - if ((evtClass == kEventClassMouse) && ((evtKind == kEventMouseDragged) || (evtKind == kEventMouseMoved))) - { - return true; - } - - else - { - return false; - } -} - - -pascal OSStatus LLWindowMacOSX::staticEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData) -{ - LLWindowMacOSX *self = (LLWindowMacOSX*)userData; - - return(self->eventHandler(myHandler, event)); -} - -OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef event) -{ - OSStatus result = eventNotHandledErr; - UInt32 evtClass = GetEventClass (event); - UInt32 evtKind = GetEventKind (event); - - // Always handle command events, even in hands-off mode. - if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) - { - HICommand command; - GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command); - - switch(command.commandID) - { - case kHICommandQuit: - if(mCallbacks->handleCloseRequest(this)) - { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL - } - result = noErr; - break; - - default: - // MBW -- XXX -- Should we handle other events here? - break; - } - } - - if(mHandsOffEvents) - { - return(result); - } - - switch (evtClass) - { - case kEventClassTextInput: - { - switch (evtKind) - { - case kEventTextInputUpdateActiveInputArea: - { - EventParamType param_type; - - long fix_len; - UInt32 text_len; - if (mPreeditor - && (result = GetEventParameter(event, kEventParamTextInputSendFixLen, - typeLongInteger, ¶m_type, sizeof(fix_len), NULL, &fix_len)) == noErr - && typeLongInteger == param_type - && (result = GetEventParameter(event, kEventParamTextInputSendText, - typeUnicodeText, ¶m_type, 0, &text_len, NULL)) == noErr - && typeUnicodeText == param_type) - { - // Handle an optional (but essential to facilitate TSMDA) ReplaceRange param. - CFRange range; - if (GetEventParameter(event, kEventParamTextInputSendReplaceRange, - typeCFRange, ¶m_type, sizeof(range), NULL, &range) == noErr - && typeCFRange == param_type) - { - // Although the spec. is unclear, replace range should - // not present when there is an active preedit. We just - // ignore the case. markAsPreedit will detect the case and warn it. - const LLWString & text = mPreeditor->getPreeditString(); - const S32 location = wstring_wstring_length_from_utf16_length(text, 0, range.location); - const S32 length = wstring_wstring_length_from_utf16_length(text, location, range.length); - mPreeditor->markAsPreedit(location, length); - } - mPreeditor->resetPreedit(); - - // Receive the text from input method. - U16 *const text = new U16[text_len / sizeof(U16)]; - GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, NULL, text_len, NULL, text); - if (fix_len < 0) - { - // Do we still need this? Seems obsolete... - fix_len = text_len; - } - const LLWString fix_string - = utf16str_to_wstring(llutf16string(text, fix_len / sizeof(U16))); - const LLWString preedit_string - = utf16str_to_wstring(llutf16string(text + fix_len / sizeof(U16), (text_len - fix_len) / sizeof(U16))); - delete[] text; - - // Handle fixed (comitted) string. - if (fix_string.length() > 0) - { - for (LLWString::const_iterator i = fix_string.begin(); i != fix_string.end(); i++) - { - mPreeditor->handleUnicodeCharHere(*i); - } - } - - // Receive the segment info and caret position. - LLPreeditor::segment_lengths_t preedit_segment_lengths; - LLPreeditor::standouts_t preedit_standouts; - S32 caret_position = preedit_string.length(); - UInt32 text_range_array_size; - if (GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, - ¶m_type, 0, &text_range_array_size, NULL) == noErr - && typeTextRangeArray == param_type - && text_range_array_size > sizeof(TextRangeArray)) - { - // TextRangeArray is a variable-length struct. - TextRangeArray * const text_range_array = (TextRangeArray *) new char[text_range_array_size]; - GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, - NULL, text_range_array_size, NULL, text_range_array); - - // WARNING: We assume ranges are in ascending order, - // although the condition is undocumented. It seems - // OK to assume this. I also assumed - // the ranges are contiguous in previous versions, but I - // have heard a rumore that older versions os ATOK may - // return ranges with some _gap_. I don't know whether - // it is true, but I'm preparing my code for the case. - - const S32 ranges = text_range_array->fNumOfRanges; - preedit_segment_lengths.reserve(ranges); - preedit_standouts.reserve(ranges); - - S32 last_bytes = 0; - S32 last_utf32 = 0; - for (S32 i = 0; i < ranges; i++) - { - const TextRange &range = text_range_array->fRange[i]; - if (range.fStart > last_bytes) - { - const S32 length_utf16 = (range.fStart - last_bytes) / sizeof(U16); - const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16); - preedit_segment_lengths.push_back(length_utf32); - preedit_standouts.push_back(FALSE); - last_utf32 += length_utf32; - } - if (range.fEnd > range.fStart) - { - const S32 length_utf16 = (range.fEnd - range.fStart) / sizeof(U16); - const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16); - preedit_segment_lengths.push_back(length_utf32); - preedit_standouts.push_back( - kTSMHiliteSelectedRawText == range.fHiliteStyle - || kTSMHiliteSelectedConvertedText == range.fHiliteStyle - || kTSMHiliteSelectedText == range.fHiliteStyle); - last_utf32 += length_utf32; - } - if (kTSMHiliteCaretPosition == range.fHiliteStyle) - { - caret_position = last_utf32; - } - last_bytes = range.fEnd; - } - if (preedit_string.length() > last_utf32) - { - preedit_segment_lengths.push_back(preedit_string.length() - last_utf32); - preedit_standouts.push_back(FALSE); - } - - delete[] (char *) text_range_array; - } - - // Handle preedit string. - if (preedit_string.length() == 0) - { - preedit_segment_lengths.clear(); - preedit_standouts.clear(); - } - else if (preedit_segment_lengths.size() == 0) - { - preedit_segment_lengths.push_back(preedit_string.length()); - preedit_standouts.push_back(FALSE); - } - mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position); - - result = noErr; - } - } - break; - - case kEventTextInputUnicodeForKeyEvent: - { - UInt32 modifiers = 0; - - - // First, process the raw event. - { - EventRef rawEvent = NULL; - - // Get the original event and extract the modifier keys, so we can ignore command-key events. - if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr) - { - // Grab the modifiers for later use in this function... - GetEventParameter (rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - - // and call this function recursively to handle the raw key event. - eventHandler (myHandler, rawEvent); - - // save the raw event until we're done processing the unicode input as well. - mRawKeyEvent = rawEvent; - } - } - - OSStatus err = noErr; - EventParamType actualType = typeUnicodeText; - UInt32 actualSize = 0; - size_t actualCount = 0; - U16 *buffer = NULL; - - // Get the size of the unicode data - err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, 0, &actualSize, NULL); - if(err == noErr) - { - // allocate a buffer and get the actual data. - actualCount = actualSize / sizeof(U16); - buffer = new U16[actualCount]; - err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, actualSize, &actualSize, buffer); - } - - if(err == noErr) - { - if(modifiers & (cmdKey | controlKey)) - { - // This was a menu key equivalent. Ignore it. - } - else - { - MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); - - llassert( actualType == typeUnicodeText ); - - // The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar. - - // Convert to UTF32 and go character-by-character. - llutf16string utf16(buffer, actualCount); - LLWString utf32 = utf16str_to_wstring(utf16); - LLWString::iterator iter; - - for(iter = utf32.begin(); iter != utf32.end(); iter++) - { - mCallbacks->handleUnicodeChar(*iter, mask); - } - } - } - - if(buffer != NULL) - { - delete[] buffer; - } - - mRawKeyEvent = NULL; - result = err; - } - break; - - case kEventTextInputOffsetToPos: - { - EventParamType param_type; - long offset; - if (mPreeditor - && GetEventParameter(event, kEventParamTextInputSendTextOffset, typeLongInteger, - ¶m_type, sizeof(offset), NULL, &offset) == noErr - && typeLongInteger == param_type) - { - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - LLCoordGL caret_coord; - LLRect preedit_bounds; - if (0 <= offset - && mPreeditor->getPreeditLocation(wstring_wstring_length_from_utf16_length(text, preedit, offset / sizeof(U16)), - &caret_coord, &preedit_bounds, NULL)) - { - LLCoordGL caret_base_coord(caret_coord.mX, preedit_bounds.mBottom); - LLCoordScreen caret_base_coord_screen; - convertCoords(caret_base_coord, &caret_base_coord_screen); - Point qd_point; - qd_point.h = caret_base_coord_screen.mX; - qd_point.v = caret_base_coord_screen.mY; - SetEventParameter(event, kEventParamTextInputReplyPoint, typeQDPoint, sizeof(qd_point), &qd_point); - - short line_height = (short) preedit_bounds.getHeight(); - SetEventParameter(event, kEventParamTextInputReplyLineHeight, typeShortInteger, sizeof(line_height), &line_height); - - result = noErr; - } - else - { - result = errOffsetInvalid; - } - } - } - break; - - case kEventTextInputGetSelectedText: - { - if (mPreeditor) - { - S32 selection, selection_length; - mPreeditor->getSelectionRange(&selection, &selection_length); - if (selection_length) - { - const LLWString text = mPreeditor->getPreeditString().substr(selection, selection_length); - const llutf16string text_utf16 = wstring_to_utf16str(text); - result = SetEventParameter(event, kEventParamTextInputReplyText, typeUnicodeText, - text_utf16.length() * sizeof(U16), text_utf16.c_str()); - } - } - } - break; - } - } - break; - - case kEventClassKeyboard: - { - UInt32 keyCode = 0; - char charCode = 0; - UInt32 modifiers = 0; - - // Some of these may fail for some event types. That's fine. - GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode); - GetEventParameter (event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - - // save the raw event so getNativeKeyData can use it. - mRawKeyEvent = event; - - // printf("key event, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", keyCode, charCode, (char)charCode, modifiers); - // fflush(stdout); - - switch (evtKind) - { - case kEventRawKeyDown: - case kEventRawKeyRepeat: - if (gDebugWindowProc) - { - printf("key down, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", - (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers); - fflush(stdout); - } - gKeyboard->handleKeyDown(keyCode, modifiers); - result = eventNotHandledErr; - break; - - case kEventRawKeyUp: - if (gDebugWindowProc) - { - printf("key up, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", - (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers); - fflush(stdout); - } - gKeyboard->handleKeyUp(keyCode, modifiers); - result = eventNotHandledErr; - break; - - case kEventRawKeyModifiersChanged: - // The keyboard input system wants key up/down events for modifier keys. - // Mac OS doesn't supply these directly, but can supply events when the collective modifier state changes. - // Use these events to generate up/down events for the modifiers. - - if((modifiers & shiftKey) && !(mLastModifiers & shiftKey)) - { - if (gDebugWindowProc) printf("Shift key down event\n"); - gKeyboard->handleKeyDown(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000)); - } - else if(!(modifiers & shiftKey) && (mLastModifiers & shiftKey)) - { - if (gDebugWindowProc) printf("Shift key up event\n"); - gKeyboard->handleKeyUp(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000)); - } - - if((modifiers & alphaLock) && !(mLastModifiers & alphaLock)) - { - if (gDebugWindowProc) printf("Caps lock down event\n"); - gKeyboard->handleKeyDown(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000)); - } - else if(!(modifiers & alphaLock) && (mLastModifiers & alphaLock)) - { - if (gDebugWindowProc) printf("Caps lock up event\n"); - gKeyboard->handleKeyUp(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000)); - } - - if((modifiers & controlKey) && !(mLastModifiers & controlKey)) - { - if (gDebugWindowProc) printf("Control key down event\n"); - gKeyboard->handleKeyDown(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000)); - } - else if(!(modifiers & controlKey) && (mLastModifiers & controlKey)) - { - if (gDebugWindowProc) printf("Control key up event\n"); - gKeyboard->handleKeyUp(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000)); - } - - if((modifiers & optionKey) && !(mLastModifiers & optionKey)) - { - if (gDebugWindowProc) printf("Option key down event\n"); - gKeyboard->handleKeyDown(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000)); - } - else if(!(modifiers & optionKey) && (mLastModifiers & optionKey)) - { - if (gDebugWindowProc) printf("Option key up event\n"); - gKeyboard->handleKeyUp(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000)); - } - - // When the state of the 'Fn' key (the one that changes some of the mappings on a powerbook/macbook keyboard - // to an embedded keypad) changes, it may subsequently cause a key up event to be lost, which may lead to - // a movement key getting "stuck" down. This is bad. - // This is an OS bug -- even the GetKeys() API doesn't tell you the key has been released. - // This workaround causes all held-down keys to be reset whenever the state of the Fn key changes. This isn't - // exactly what we want, but it does avoid the case where you get stuck running forward. - if((modifiers & kEventKeyModifierFnMask) != (mLastModifiers & kEventKeyModifierFnMask)) - { - if (gDebugWindowProc) printf("Fn key state change event\n"); - gKeyboard->resetKeys(); - } - - if (gDebugWindowProc) fflush(stdout); - - mLastModifiers = modifiers; - result = eventNotHandledErr; - break; - } - - mRawKeyEvent = NULL; - } - break; - - case kEventClassMouse: - { - result = CallNextEventHandler(myHandler, event); - if (eventNotHandledErr == result) - { // only handle events not already handled (prevents wierd resize interaction) - EventMouseButton button = kEventMouseButtonPrimary; - HIPoint location = {0.0f, 0.0f}; - UInt32 modifiers = 0; - UInt32 clickCount = 1; - long wheelDelta = 0; - LLCoordScreen inCoords; - LLCoordGL outCoords; - MASK mask = 0; - - GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); - GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(location), NULL, &location); - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); - GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(wheelDelta), NULL, &wheelDelta); - GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount); - - inCoords.mX = llround(location.x); - inCoords.mY = llround(location.y); - - if(modifiers & shiftKey) { mask |= MASK_SHIFT; } - if(modifiers & controlKey) { mask |= MASK_CONTROL; } - if(modifiers & optionKey) { mask |= MASK_ALT; } - - if(mCursorDecoupled) - { - CGMouseDelta x, y; - - // If the cursor's decoupled, we need to read the latest movement delta as well. - CGGetLastMouseDelta( &x, &y ); - mCursorLastEventDeltaX = x; - mCursorLastEventDeltaY = y; - - if(mCursorIgnoreNextDelta) - { - mCursorLastEventDeltaX = 0; - mCursorLastEventDeltaY = 0; - mCursorIgnoreNextDelta = FALSE; - } - } - else - { - mCursorLastEventDeltaX = 0; - mCursorLastEventDeltaY = 0; - } - - inCoords.mX += mCursorLastEventDeltaX; - inCoords.mY += mCursorLastEventDeltaY; - - convertCoords(inCoords, &outCoords); - - // printf("coords in: %d, %d; coords out: %d, %d\n", inCoords.mX, inCoords.mY, outCoords.mX, outCoords.mY); - // fflush(stdout); - - - switch (evtKind) - { - case kEventMouseDown: - if (mLanguageTextInputAllowed) - { - // We need to interrupt before handling mouse events, - // so that the fixed string from IM are delivered to - // the currently focused UI component. - interruptLanguageTextInput(); - } - switch(button) - { - case kEventMouseButtonPrimary: - if(modifiers & cmdKey) - { - // Simulate a right click - mSimulatedRightClick = true; - mCallbacks->handleRightMouseDown(this, outCoords, mask); - } - else if(clickCount == 2) - { - // Windows double-click events replace the second mousedown event in a double-click. - mCallbacks->handleDoubleClick(this, outCoords, mask); - } - else - { - mCallbacks->handleMouseDown(this, outCoords, mask); - } - break; - case kEventMouseButtonSecondary: - mCallbacks->handleRightMouseDown(this, outCoords, mask); - break; - - case kEventMouseButtonTertiary: - mCallbacks->handleMiddleMouseDown(this, outCoords, mask); - break; - } - result = noErr; - break; - case kEventMouseUp: - - switch(button) - { - case kEventMouseButtonPrimary: - if(mSimulatedRightClick) - { - // End of simulated right click - mSimulatedRightClick = false; - mCallbacks->handleRightMouseUp(this, outCoords, mask); - } - else - { - mCallbacks->handleMouseUp(this, outCoords, mask); - } - break; - case kEventMouseButtonSecondary: - mCallbacks->handleRightMouseUp(this, outCoords, mask); - break; - - case kEventMouseButtonTertiary: - mCallbacks->handleMiddleMouseUp(this, outCoords, mask); - break; - } - result = noErr; - break; - - case kEventMouseWheelMoved: - { - static S32 z_delta = 0; - - z_delta += wheelDelta; - - if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) - { - mCallbacks->handleScrollWheel(this, -z_delta / WHEEL_DELTA); - z_delta = 0; - } - } - result = noErr; - break; - - case kEventMouseDragged: - case kEventMouseMoved: - mCallbacks->handleMouseMove(this, outCoords, mask); - result = noErr; - break; - - } - } - } - break; - - case kEventClassWindow: - switch(evtKind) - { - case kEventWindowActivated: - if (mTSMDocument) - { - ActivateTSMDocument(mTSMDocument); - } - mCallbacks->handleFocus(this); - break; - case kEventWindowDeactivated: - if (mTSMDocument) - { - DeactivateTSMDocument(mTSMDocument); - } - mCallbacks->handleFocusLost(this); - break; - - case kEventWindowBoundsChanging: - { - // This is where we would constrain move/resize to a particular screen - - const S32 MIN_WIDTH = mMinWindowWidth; - const S32 MIN_HEIGHT = mMinWindowHeight; - - Rect currentBounds; - Rect previousBounds; - - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds); - GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &previousBounds); - - // Put an offset into window un-maximize operation since the kEventWindowGetIdealSize - // event only allows the specification of size and not position. - if (mMaximized) - { - short leftOffset = mPreviousWindowRect.left - currentBounds.left; - currentBounds.left += leftOffset; - currentBounds.right += leftOffset; - - short topOffset = mPreviousWindowRect.top - currentBounds.top; - currentBounds.top += topOffset; - currentBounds.bottom += topOffset; - } - else - { - // Store off the size for future un-maximize operations - mPreviousWindowRect = previousBounds; - } - - if ((currentBounds.right - currentBounds.left) < MIN_WIDTH) - { - currentBounds.right = currentBounds.left + MIN_WIDTH; - } - - if ((currentBounds.bottom - currentBounds.top) < MIN_HEIGHT) - { - currentBounds.bottom = currentBounds.top + MIN_HEIGHT; - } - - SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds); - result = noErr; - } - break; - - case kEventWindowBoundsChanged: - { - // Get new window bounds - Rect newBounds; - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds); - - // Get previous window bounds - Rect oldBounds; - GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &oldBounds); - - // Determine if the new size is larger than the old - bool newBoundsLarger = ((newBounds.right - newBounds.left) >= (oldBounds.right - oldBounds.left)); - newBoundsLarger &= ((newBounds.bottom - newBounds.top) >= (oldBounds.bottom - oldBounds.top)); - - // Check to see if this is a zoom event (+ button on window pane) - unsigned int eventParams; - GetEventParameter(event, kEventParamAttributes, typeUInt32, NULL, sizeof(int), NULL, &eventParams); - bool isZoomEvent = ((eventParams & kWindowBoundsChangeZoom) != 0); - - // Maximized flag is if zoom event and increasing window size - mMaximized = (isZoomEvent && newBoundsLarger); - - aglUpdateContext(mContext); - - mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top); - } - break; - - case kEventWindowGetIdealSize: - // Only recommend a new ideal size when un-maximizing - if (mMaximized == TRUE) - { - Point nonMaximizedSize; - - nonMaximizedSize.v = mPreviousWindowRect.bottom - mPreviousWindowRect.top; - nonMaximizedSize.h = mPreviousWindowRect.right - mPreviousWindowRect.left; - - SetEventParameter(event, kEventParamDimensions, typeQDPoint, sizeof(Point), &nonMaximizedSize); - result = noErr; - } - break; - - case kEventWindowClose: - if(mCallbacks->handleCloseRequest(this)) - { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL - } - result = noErr; - break; - - case kEventWindowHidden: - // llinfos << "LLWindowMacOSX: Deactivating on hide" << llendl; - mMinimized = TRUE; - mCallbacks->handleActivate(this, false); - // result = noErr; - break; - - case kEventWindowShown: - // llinfos << "LLWindowMacOSX: Activating on show" << llendl; - mMinimized = FALSE; - mCallbacks->handleActivate(this, true); - // result = noErr; - break; - - case kEventWindowCollapsed: - // llinfos << "LLWindowMacOSX: Deactivating on collapse" << llendl; - mMinimized = TRUE; - mCallbacks->handleActivate(this, false); - // result = noErr; - break; - - case kEventWindowExpanded: - // llinfos << "LLWindowMacOSX: Activating on expand" << llendl; - mMinimized = FALSE; - mCallbacks->handleActivate(this, true); - // result = noErr; - break; - - case kEventWindowGetClickActivation: - // BringToFront(mWindow); - // result = noErr; - break; - } - break; - - case kEventClassTSMDocumentAccess: - if (mPreeditor) - { - switch(evtKind) - { - - case kEventTSMDocumentAccessGetLength: - { - // Return the number of UTF-16 units in the text, excluding those for preedit. - - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - const CFIndex length = wstring_utf16_length(text, 0, preedit) - + wstring_utf16_length(text, preedit + preedit_length, text.length()); - result = SetEventParameter(event, kEventParamTSMDocAccessCharacterCount, typeCFIndex, sizeof(length), &length); - } - break; - - case kEventTSMDocumentAccessGetSelectedRange: - { - // Return the selected range, excluding preedit. - // In our preeditor, preedit and selection are exclusive, so, - // when it has a preedit, there is no selection and the - // insertion point is on the preedit that corrupses into the - // beginning of the preedit when the preedit was removed. - - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - CFRange range; - if (preedit_length) - { - range.location = wstring_utf16_length(text, 0, preedit); - range.length = 0; - } - else - { - S32 selection, selection_length; - mPreeditor->getSelectionRange(&selection, &selection_length); - range.location = wstring_utf16_length(text, 0, selection); - range.length = wstring_utf16_length(text, selection, selection_length); - } - - result = SetEventParameter(event, kEventParamTSMDocAccessReplyCharacterRange, typeCFRange, sizeof(range), &range); - } - break; - - case kEventTSMDocumentAccessGetCharacters: - { - UniChar *target_pointer; - CFRange range; - EventParamType param_type; - if ((result = GetEventParameter(event, kEventParamTSMDocAccessSendCharacterRange, - typeCFRange, ¶m_type, sizeof(range), NULL, &range)) == noErr - && typeCFRange == param_type - && (result = GetEventParameter(event, kEventParamTSMDocAccessSendCharactersPtr, - typePtr, ¶m_type, sizeof(target_pointer), NULL, &target_pointer)) == noErr - && typePtr == param_type) - { - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - // The GetCharacters event of TSMDA has a fundamental flaw; - // An input method need to decide the starting offset and length - // *before* it actually see the contents, so it is impossible - // to guarantee the character-aligned access. The event reply - // has no way to indicate a condition something like "Request - // was not fulfilled due to unaligned access. Please retry." - // Any error sent back to the input method stops use of TSMDA - // entirely during the session... - // We need to simulate very strictly the behaviour as if the - // underlying *text engine* holds the contents in UTF-16. - // I guess this is the reason why Apple repeats saying "all - // text handling application should use UTF-16." They are - // trying to _fix_ the flaw by changing the appliations... - // ... or, domination of UTF-16 in the industry may be a part - // of the company vision, and Apple is trying to force third - // party developers to obey their vision. Remember that use - // of 16 bits per _a_character_ was one of the very fundamental - // Unicode design policy on its early days (during late 80s) - // and the original Unicode design was by two Apple employees... - - const llutf16string text_utf16 - = wstring_to_utf16str(text, preedit) - + wstring_to_utf16str(text.substr(preedit + preedit_length)); - - llassert_always(sizeof(U16) == sizeof(UniChar)); - llassert(0 <= range.location && 0 <= range.length && range.location + range.length <= text_utf16.length()); - memcpy(target_pointer, text_utf16.c_str() + range.location, range.length * sizeof(UniChar)); - - // Note that result has already been set above. - } - } - break; - - } - } - break; - } - return result; -} - const char* cursorIDToName(int id) { switch (id) @@ -2876,7 +1371,7 @@ static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY) void LLWindowMacOSX::updateCursor() { - OSStatus result = noErr; + S32 result = 0; if (mDragOverrideCursor != -1) { @@ -2909,11 +1404,11 @@ void LLWindowMacOSX::updateCursor() { default: case UI_CURSOR_ARROW: - InitCursor(); + setArrowCursor(); if(mCursorHidden) { // Since InitCursor resets the hide level, correct for it here. - ::HideCursor(); + hideNSCursor(); } break; @@ -2921,12 +1416,12 @@ void LLWindowMacOSX::updateCursor() // Find out what they look like and replicate them. // These are essentially correct - case UI_CURSOR_WAIT: SetThemeCursor(kThemeWatchCursor); break; - case UI_CURSOR_IBEAM: SetThemeCursor(kThemeIBeamCursor); break; - case UI_CURSOR_CROSS: SetThemeCursor(kThemeCrossCursor); break; - case UI_CURSOR_HAND: SetThemeCursor(kThemePointingHandCursor); break; + case UI_CURSOR_WAIT: /* Apple purposely doesn't allow us to set the beachball cursor manually. Let NSApp figure out when to do this. */ break; + case UI_CURSOR_IBEAM: setIBeamCursor(); break; + case UI_CURSOR_CROSS: setCrossCursor(); break; + case UI_CURSOR_HAND: setPointingHandCursor(); break; // case UI_CURSOR_NO: SetThemeCursor(kThemeNotAllowedCursor); break; - case UI_CURSOR_ARROWCOPY: SetThemeCursor(kThemeCopyArrowCursor); break; + case UI_CURSOR_ARROWCOPY: setCopyCursor(); break; // Double-check these case UI_CURSOR_NO: @@ -2969,7 +1464,7 @@ void LLWindowMacOSX::updateCursor() if(result != noErr) { - InitCursor(); + setArrowCursor(); } mCurrentCursor = mNextCursor; @@ -3039,7 +1534,7 @@ void LLWindowMacOSX::hideCursor() // llinfos << "hideCursor: hiding" << llendl; mCursorHidden = TRUE; mHideCursorPermanent = TRUE; - ::HideCursor(); + hideNSCursor(); } else { @@ -3056,7 +1551,7 @@ void LLWindowMacOSX::showCursor() // llinfos << "showCursor: showing" << llendl; mCursorHidden = FALSE; mHideCursorPermanent = FALSE; - ::ShowCursor(); + showNSCursor(); } else { @@ -3100,24 +1595,6 @@ LLSplashScreenMacOSX::~LLSplashScreenMacOSX() void LLSplashScreenMacOSX::showImpl() { // This code _could_ be used to display a spash screen... -#if 0 - IBNibRef nib = NULL; - OSStatus err; - - err = CreateNibReference(CFSTR("SecondLife"), &nib); - - if(err == noErr) - { - CreateWindowFromNib(nib, CFSTR("Splash Screen"), &mWindow); - - DisposeNibReference(nib); - } - - if(mWindow != NULL) - { - ShowWindow(mWindow); - } -#endif } void LLSplashScreenMacOSX::updateImpl(const std::string& mesg) @@ -3127,25 +1604,6 @@ void LLSplashScreenMacOSX::updateImpl(const std::string& mesg) CFStringRef string = NULL; string = CFStringCreateWithCString(NULL, mesg.c_str(), kCFStringEncodingUTF8); - - if(string != NULL) - { - ControlRef progressText = NULL; - ControlID id; - OSStatus err; - - id.signature = 'what'; - id.id = 0; - - err = GetControlByID(mWindow, &id, &progressText); - if(err == noErr) - { - err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&string); - Draw1Control(progressText); - } - - CFRelease(string); - } } } @@ -3154,111 +1612,21 @@ void LLSplashScreenMacOSX::hideImpl() { if(mWindow != NULL) { - DisposeWindow(mWindow); mWindow = NULL; } } - - S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 type) { - S32 result = OSBTN_CANCEL; - SInt16 retval_mac = 1; - AlertStdCFStringAlertParamRec params; - CFStringRef errorString = NULL; - CFStringRef explanationString = NULL; - DialogRef alert = NULL; - AlertType alertType = kAlertCautionAlert; - OSStatus err; - - explanationString = CFStringCreateWithCString(NULL, text.c_str(), kCFStringEncodingUTF8); - errorString = CFStringCreateWithCString(NULL, caption.c_str(), kCFStringEncodingUTF8); - - params.version = kStdCFStringAlertVersionOne; - params.movable = false; - params.helpButton = false; - params.defaultText = (CFStringRef)kAlertDefaultOKText; - params.cancelText = 0; - params.otherText = 0; - params.defaultButton = 1; - params.cancelButton = 0; - params.position = kWindowDefaultPosition; - params.flags = 0; - - switch(type) - { - case OSMB_OK: - default: - break; - case OSMB_OKCANCEL: - params.cancelText = (CFStringRef)kAlertDefaultCancelText; - params.cancelButton = 2; - break; - case OSMB_YESNO: - alertType = kAlertNoteAlert; - params.defaultText = CFSTR("Yes"); - params.cancelText = CFSTR("No"); - params.cancelButton = 2; - break; - } - - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); - - err = CreateStandardAlert( - alertType, - errorString, - explanationString, - ¶ms, - &alert); - - if(err == noErr) - { - err = RunStandardAlert( - alert, - NULL, - &retval_mac); - } - - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); - - switch(type) - { - case OSMB_OK: - case OSMB_OKCANCEL: - default: - if(retval_mac == 1) - result = OSBTN_OK; - else - result = OSBTN_CANCEL; - break; - case OSMB_YESNO: - if(retval_mac == 1) - result = OSBTN_YES; - else - result = OSBTN_NO; - break; - } - - if(errorString != NULL) - { - CFRelease(errorString); - } - - if(explanationString != NULL) - { - CFRelease(explanationString); - } - - return result; + return showAlert(text, caption, type); } // Open a URL with the user's default web browser. // Must begin with protocol identifier. void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) { + // I'm fairly certain that this is all legitimate under Apple's currently supported APIs. + bool found = false; S32 i; for (i = 0; i < gURLProtocolWhitelistCount; i++) @@ -3276,7 +1644,7 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) return; } - OSStatus result = noErr; + S32 result = 0; CFURLRef urlRef = NULL; llinfos << "Opening URL " << escaped_url << llendl; @@ -3313,7 +1681,7 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) LLSD LLWindowMacOSX::getNativeKeyData() { LLSD result = LLSD::emptyMap(); - +#if 0 if(mRawKeyEvent) { char char_code = 0; @@ -3335,7 +1703,7 @@ LLSD LLWindowMacOSX::getNativeKeyData() // This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc) // cause llsd serialization to create XML that the llsd deserializer won't parse! std::string unicode; - OSStatus err = noErr; + S32 err = noErr; EventParamType actualType = typeUTF8Text; UInt32 actualSize = 0; char *buffer = NULL; @@ -3357,7 +1725,7 @@ LLSD LLWindowMacOSX::getNativeKeyData() #endif } - +#endif lldebugs << "native key data is: " << result << llendl; @@ -3367,34 +1735,9 @@ LLSD LLWindowMacOSX::getNativeKeyData() BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b) { + // Is this even used anywhere? Do we really need an OS color picker? BOOL retval = FALSE; - OSErr error = noErr; - NColorPickerInfo info; - - memset(&info, 0, sizeof(info)); - info.theColor.color.rgb.red = (UInt16)(*r * 65535.f); - info.theColor.color.rgb.green = (UInt16)(*g * 65535.f); - info.theColor.color.rgb.blue = (UInt16)(*b * 65535.f); - info.placeWhere = kCenterOnMainScreen; - - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); - - error = NPickColor(&info); - - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); - - if (error == noErr) - { - retval = info.newColorChosen; - if (info.newColorChosen) - { - *r = ((float) info.theColor.color.rgb.red) / 65535.0; - *g = ((float) info.theColor.color.rgb.green) / 65535.0; - *b = ((float) info.theColor.color.rgb.blue) / 65535.0; - } - } + //S32 error = 0; return (retval); } @@ -3405,44 +1748,8 @@ void *LLWindowMacOSX::getPlatformWindow() return (void*)mWindow; } -void *LLWindowMacOSX::getMediaWindow() -{ - /* - Mozilla needs to be initialized with a WindowRef to function properly. - (There's no good reason for this, since it shouldn't be interacting with our window in any way, but that's another issue.) - If we're in windowed mode, we _could_ hand it our actual window pointer, but a subsequent switch to fullscreen will destroy that window, - which trips up Mozilla. - Instead of using our actual window, we create an invisible window which will persist for the lifetime of the application and pass that to Mozilla. - This satisfies its deep-seated need to latch onto a WindowRef and solves the issue with switching between fullscreen and windowed modes. - - Note that we will never destroy this window (by design!), but since only one will ever be created per run of the application, that's okay. - */ - - if(sMediaWindow == NULL) - { - Rect window_rect = {100, 100, 200, 200}; - - sMediaWindow = NewCWindow( - NULL, - &window_rect, - (ConstStr255Param) "\p", - false, // Create the window invisible. - zoomDocProc, // Window with a grow box and a zoom box - kLastWindowOfClass, // create it behind other windows - false, // no close box - 0); - } - - return (void*)sMediaWindow; -} - -void LLWindowMacOSX::stopDockTileBounce() -{ - NMRemove(&mBounceRec); - mBounceTimer.stop(); -} - // get a double value from a dictionary +/* static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) { double double_value; @@ -3452,7 +1759,7 @@ static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &double_value)) // or if cant convert it return -1; // fail return double_value; // otherwise return the long value -} +}*/ // get a long value from a dictionary static long getDictLong (CFDictionaryRef refDict, CFStringRef key) @@ -3468,8 +1775,8 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key) void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) { - ScriptLanguageRecord script_language; - + allowDirectMarkedTextInput(b, mGLView); + if (preeditor != mPreeditor && !b) { // This condition may occur by a call to @@ -3480,9 +1787,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) // is not disturbed. return; } - - UseInputWindow(mTSMDocument, !b); - + // Take care of old and new preeditors. if (preeditor != mPreeditor || !b) { @@ -3495,44 +1800,17 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) } mPreeditor = (b ? preeditor : NULL); } - + if (b == mLanguageTextInputAllowed) { return; } mLanguageTextInputAllowed = b; - - if (b) - { - if (mTSMScriptCode != smRoman) - { - script_language.fScript = mTSMScriptCode; - script_language.fLanguage = mTSMLangCode; - SetTextServiceLanguage(&script_language); - } - } - else - { - GetTextServiceLanguage(&script_language); - mTSMScriptCode = script_language.fScript; - mTSMLangCode = script_language.fLanguage; - if (mTSMScriptCode != smRoman) - { - script_language.fScript = smRoman; - script_language.fLanguage = langEnglish; - SetTextServiceLanguage(&script_language); - } - } } void LLWindowMacOSX::interruptLanguageTextInput() { - if (mTSMDocument) - { - FixTSMDocument(mTSMDocument); - } - // Don't we need to call resetPreedit here? - // Well, if Apple's TSM document is correct, we don't. + commitCurrentPreedit(mGLView); } //static @@ -3543,21 +1821,21 @@ std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList() } // static -MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers) +MASK LLWindowMacOSX::modifiersToMask(S16 modifiers) { MASK mask = 0; - if(modifiers & shiftKey) { mask |= MASK_SHIFT; } - if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; } - if(modifiers & optionKey) { mask |= MASK_ALT; } + if(modifiers & MAC_SHIFT_KEY) { mask |= MASK_SHIFT; } + if(modifiers & (MAC_CMD_KEY | MAC_CTRL_KEY)) { mask |= MASK_CONTROL; } + if(modifiers & MAC_ALT_KEY) { mask |= MASK_ALT; } return mask; } #if LL_OS_DRAGDROP_ENABLED - -OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, +/* +S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef drag) { - OSErr result = noErr; + S16 result = 0; LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon; lldebugs << "drag tracking handler, message = " << message << llendl; @@ -3582,7 +1860,6 @@ OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef return result; } - OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef drag) { @@ -3590,126 +1867,69 @@ OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefC return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED); } - -OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action) +*/ +void LLWindowMacOSX::handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action) { - OSErr result = dragNotAcceptedErr; // overall function result - OSErr err = noErr; // for local error handling - - // Get the mouse position and modifiers of this drag. - SInt16 modifiers, mouseDownModifiers, mouseUpModifiers; - ::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers); - MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); + MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers()); - Point mouse_point; - // This will return the mouse point in global screen coords - ::GetDragMouse(drag, &mouse_point, NULL); - LLCoordScreen screen_coords(mouse_point.h, mouse_point.v); + float mouse_point[2]; + // This will return the mouse point in window coords + getCursorPos(mWindow, mouse_point); + LLCoordWindow window_coords(mouse_point[0], mouse_point[1]); LLCoordGL gl_pos; - convertCoords(screen_coords, &gl_pos); - - // Look at the pasteboard and try to extract an URL from it - PasteboardRef pasteboard; - if(GetDragPasteboard(drag, &pasteboard) == noErr) + convertCoords(window_coords, &gl_pos); + + if(!url.empty()) { - ItemCount num_items = 0; - // Treat an error here as an item count of 0 - (void)PasteboardGetItemCount(pasteboard, &num_items); - - // Only deal with single-item drags. - if(num_items == 1) - { - PasteboardItemID item_id = NULL; - CFArrayRef flavors = NULL; - CFDataRef data = NULL; - - err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based. - - // Try to extract an URL from the pasteboard - if(err == noErr) - { - err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors); - } - - if(err == noErr) - { - if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL)) - { - // This is an URL. - err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeURL, &data); - } - else if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeUTF8PlainText)) + LLWindowCallbacks::DragNDropResult res = + mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url); + + switch (res) { + case LLWindowCallbacks::DND_NONE: // No drop allowed + if (action == LLWindowCallbacks::DNDA_TRACK) { - // This is a string that might be an URL. - err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data); + mDragOverrideCursor = 0; } - - } - - if(flavors != NULL) - { - CFRelease(flavors); - } - - if(data != NULL) - { - std::string url; - url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data)); - CFRelease(data); - - if(!url.empty()) - { - LLWindowCallbacks::DragNDropResult res = - mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url); - - switch (res) { - case LLWindowCallbacks::DND_NONE: // No drop allowed - if (action == LLWindowCallbacks::DNDA_TRACK) - { - mDragOverrideCursor = kThemeNotAllowedCursor; - } - else { - mDragOverrideCursor = -1; - } - break; - case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation - mDragOverrideCursor = kThemePointingHandCursor; - result = noErr; - break; - case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation - mDragOverrideCursor = kThemeCopyArrowCursor; - result = noErr; - break; - case LLWindowCallbacks::DND_LINK: // Drop accepted would result in a "link" operation: - mDragOverrideCursor = kThemeAliasArrowCursor; - result = noErr; - break; - default: - mDragOverrideCursor = -1; - break; - } - // This overrides the cursor being set by setCursor. - // This is a bit of a hack workaround because lots of areas - // within the viewer just blindly set the cursor. - if (mDragOverrideCursor == -1) - { - // Restore the cursor - ECursorType temp_cursor = mCurrentCursor; - // get around the "setting the same cursor" code in setCursor() - mCurrentCursor = UI_CURSOR_COUNT; - setCursor(temp_cursor); - } - else { - // Override the cursor - SetThemeCursor(mDragOverrideCursor); - } - + else { + mDragOverrideCursor = -1; } - } + break; + case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation + mDragOverrideCursor = UI_CURSOR_NO; + break; + case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation + mDragOverrideCursor = UI_CURSOR_ARROWCOPY; + break; + default: + mDragOverrideCursor = -1; + break; + } + // This overrides the cursor being set by setCursor. + // This is a bit of a hack workaround because lots of areas + // within the viewer just blindly set the cursor. + if (mDragOverrideCursor == -1) + { + // Restore the cursor + ECursorType temp_cursor = mCurrentCursor; + // get around the "setting the same cursor" code in setCursor() + mCurrentCursor = UI_CURSOR_COUNT; + setCursor(temp_cursor); + } + else { + // Override the cursor + switch (mDragOverrideCursor) { + case 0: + setArrowCursor(); + break; + case UI_CURSOR_NO: + setNotAllowedCursor(); + case UI_CURSOR_ARROWCOPY: + setCopyCursor(); + default: + break; + }; } } - - return result; } #endif // LL_OS_DRAGDROP_ENABLED |