12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910 |
- /**
- * @file llwindowmacosx.cpp
- * @brief Platform-dependent implementation of llwindow
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include <OpenGL/OpenGL.h>
- #include <CoreServices/CoreServices.h>
- #include "llwindowmacosx.h"
- #include "indra_constants.h"
- #include "lldir.h"
- #include "llfasttimer.h"
- #include "llgl.h"
- #include "llkeyboardmacosx.h"
- #include "llpreeditor.h"
- #include "llrender.h" // For LLRender::sGLCoreProfile
- #include "llstring.h"
- #include "llwindowmacosx-objc.h"
- constexpr S32 BITS_PER_PIXEL = 32;
- constexpr S32 MAX_NUM_RESOLUTIONS = 32;
- namespace
- {
- NSKeyEventRef mRawKeyEvent = NULL;
- }
- //
- // LLWindowMacOSX
- //
- bool LLWindowMacOSX::sUseMultGL = false;
- // Cross-platform bits:
- bool check_for_card(const char* RENDERER, const char* bad_card)
- {
- if (!strnicmp(RENDERER, bad_card, strlen(bad_card)))
- {
- std::string buffer = llformat(
- "Your video card appears to be a %s, which Second Life does not support.\n"
- "\n"
- "Second Life requires a video card with 32 Mb of memory or more, as well as\n"
- "multitexture support. We explicitly support nVidia GeForce 2 or better, \n"
- "and ATI Radeon 8500 or better.\n"
- "\n"
- "If you own a supported card and continue to receive this message, try \n"
- "updating to the latest video card drivers. Otherwise look in the\n"
- "secondlife.com support section or e-mail technical support\n"
- "\n"
- "You can try to run Second Life, but it will probably crash or run\n"
- "very slowly. Try anyway?",
- bad_card);
- S32 button = OSMessageBox(buffer.c_str(), "Unsupported video card",
- OSMB_YESNO);
- return button != OSBTN_YES;
- }
- return false;
- }
- // Get a long value from a dictionary
- static long getDictLong(CFDictionaryRef refDict, CFStringRef key)
- {
- CFNumberRef number_value = (CFNumberRef)CFDictionaryGetValue(refDict, key);
- if (!number_value)
- {
- // if can't get a number for the dictionary
- return -1; // fail
- }
- long int_value;
- if (!CFNumberGetValue(number_value, kCFNumberLongType, &int_value))
- {
- // or if cant convert it
- return -1; // fail
- }
- return int_value; // otherwise return the long value
- }
- // *HACK: 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 require a
- // pointer to the LLWindowMacOSX object. Stash it here and maintain in the
- // constructor and destructor. This assumes that there will be only one object
- // of this class at any time, which is currently the case.
- static LLWindowMacOSX* sWindowImplementation = NULL;
- LLWindowMacOSX::LLWindowMacOSX(const std::string& title, U32 flags,
- bool fullscreen, bool disable_vsync,
- U32 fsaa_samples)
- : LLWindow(fullscreen, flags)
- {
- setupCocoa();
- // Initialize the keyboard
- gKeyboardp = new LLKeyboardMacOSX();
- mWindow = NULL;
- mContext = NULL;
- mPixelFormat = NULL;
- mDisplay = CGMainDisplayID();
- mSimulatedRightClick = false;
- mLastModifiers = 0;
- mCursorDecoupled = false;
- mCursorLastEventDeltaX = 0;
- mCursorLastEventDeltaY = 0;
- mCursorIgnoreNextDelta = false;
- mMinimized = false;
- mLanguageTextInputAllowed = false;
- mPreeditor = NULL;
- mFSAASamples = fsaa_samples;
- mForceRebuild = false;
- // Get the original aspect ratio of the main device.
- mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) /
- (double)CGDisplayPixelsHigh(mDisplay);
- // Stash the window title
- mWindowTitle = title;
- // Stash an object pointer for OSMessageBox()
- sWindowImplementation = this;
- // Create the GL context and set it up for windowed or fullscreen, as
- // appropriate.
- if (createContext(fullscreen, disable_vsync))
- {
- if (mWindow)
- {
- makeWindowOrderFront(mWindow);
- }
- if (!gGLManager.initGL())
- {
- setupFailure(
- "Second Life is unable to run because your video card drivers\n"
- "are out of date or unsupported. Please make sure you have\n"
- "the latest video card drivers installed.\n"
- "If you continue to receive this message, contact customer service.");
- return;
- }
- // Start with arrow cursor
- initCursors();
- setCursor(UI_CURSOR_ARROW);
- allowLanguageTextInput(NULL, false);
- }
- stop_glerror();
- }
- void LLWindowMacOSX::setWindowTitle(const std::string& title)
- {
- // Remember the new title, for when we switch context
- mWindowTitle = title;
- setWinTitle(mWindow, title);
- }
- bool LLWindowMacOSX::createContext(bool fullscreen, bool disable_vsync)
- {
- mFullscreen = fullscreen;
- if (!mWindow)
- {
- mWindow = getMainAppWindow();
- }
- if (!mContext)
- {
- // Our OpenGL view is already defined within CoolVLViewer.xib.
- // Get the view instead.
- mGLView = createOpenGLView(mWindow, mFSAASamples, !disable_vsync,
- LLRender::sGLCoreProfile);
- mContext = getCGLContextObj(mGLView);
- gGLManager.mVRAM = getVramSize(mGLView);
- if (!mPixelFormat)
- {
- CGLPixelFormatAttribute attribs[] =
- {
- kCGLPFANoRecovery,
- kCGLPFADoubleBuffer,
- kCGLPFAClosestPolicy,
- kCGLPFAAccelerated,
- kCGLPFAMultisample,
- kCGLPFASampleBuffers, CGLPixelFormatAttribute(mFSAASamples ? 1
- : 0),
- kCGLPFASamples, CGLPixelFormatAttribute(mFSAASamples),
- kCGLPFAStencilSize, CGLPixelFormatAttribute(8),
- kCGLPFADepthSize, CGLPixelFormatAttribute(24),
- kCGLPFAAlphaSize, CGLPixelFormatAttribute(8),
- kCGLPFAColorSize, CGLPixelFormatAttribute(24),
- CGLPixelFormatAttribute(0)
- };
- GLint num_formats;
- CGLChoosePixelFormat(attribs, &mPixelFormat, &num_formats);
- if (!mPixelFormat)
- {
- // Try again
- CGLChoosePixelFormat(attribs, &mPixelFormat, &num_formats);
- }
- }
- }
- // This sets up our view to receive text from our non-inline text input
- // window.
- setupInputWindow(mWindow, mGLView);
- if (mContext)
- {
- LL_DEBUGS("Window") << "Setting current context" << LL_ENDL;
- U32 err = CGLSetCurrentContext(mContext);
- if (err != kCGLNoError)
- {
- setupFailure("Cannot activate GL rendering context");
- return false;
- }
- }
- // Disable vertical sync for swap
- GLint frames_per_swap = disable_vsync ? 0 : 1;
- CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap);
- // Enable multi-threaded OpenGL when configured to do so.
- if (sUseMultGL)
- {
- CGLError cgl_err;
- CGLContextObj ctx = CGLGetCurrentContext();
- cgl_err = CGLEnable(ctx, kCGLCEMPEngine);
- if (cgl_err != kCGLNoError)
- {
- LL_DEBUGS("GLInit") << "Multi-threaded OpenGL not available."
- << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
- }
- }
- makeFirstResponder(mWindow, mGLView);
- return true;
- }
- // 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, const LLCoordScreen&, bool,
- const LLCoordScreen* const)
- {
- return false;
- }
- void LLWindowMacOSX::destroyContext()
- {
- if (!mContext)
- {
- // We do not have a context
- return;
- }
- // Unhook the GL context from any drawable it may have
- LL_DEBUGS("Window") << "Unhooking drawable" << LL_ENDL;
- CGLSetCurrentContext(NULL);
- // Clean up remaining GL state before blowing away window
- gGLManager.shutdownGL();
- // Clean up the pixel format
- if (mPixelFormat)
- {
- LL_DEBUGS("Window") << "Destroying pixel format" << LL_ENDL;
- CGLDestroyPixelFormat(mPixelFormat);
- mPixelFormat = NULL;
- }
- LL_DEBUGS("Window") << "Destroying context" << LL_ENDL;
- CGLDestroyContext(mContext);
- #if 1
- mContext = NULL;
- #endif
- // Destroy our LLOpenGLView
- if (mGLView)
- {
- LL_DEBUGS("Window") << "Destroying GL view" << LL_ENDL;
- removeGLView(mGLView);
- mGLView = NULL;
- }
- // Close the window
- if (mWindow)
- {
- LL_DEBUGS("Window") << "Disposing window" << LL_ENDL;
- NSWindowRef dead_window = mWindow;
- mWindow = NULL;
- closeWindow(dead_window);
- }
- }
- LLWindowMacOSX::~LLWindowMacOSX()
- {
- destroyContext();
- if (mSupportedResolutions)
- {
- delete[] mSupportedResolutions;
- }
- sWindowImplementation = NULL;
- }
- void LLWindowMacOSX::show()
- {
- }
- void LLWindowMacOSX::hide()
- {
- setMouseClipping(false);
- }
- void LLWindowMacOSX::minimize()
- {
- setMouseClipping(false);
- showCursor();
- }
- void LLWindowMacOSX::restore()
- {
- show();
- }
- // Destroys all OS-specific code associated with a window. Usually called from
- // LLWindow::destroyWindow()
- void LLWindowMacOSX::close()
- {
- #if 0
- // Is window is already closed ?
- if (!mWindow)
- {
- return;
- }
- #endif
- // Make sure cursor is visible and we have not mangled the clipping state.
- setMouseClipping(false);
- showCursor();
- destroyContext();
- }
- bool LLWindowMacOSX::isValid()
- {
- return mFullscreen || mWindow != NULL;
- }
- bool LLWindowMacOSX::getVisible()
- {
- return mFullscreen || mWindow != NULL;
- }
- bool LLWindowMacOSX::getMinimized()
- {
- return mMinimized;
- }
- void LLWindowMacOSX::gatherInput()
- {
- updateCursor();
- }
- bool LLWindowMacOSX::getPosition(LLCoordScreen* position)
- {
- if (mFullscreen)
- {
- position->mX = 0;
- position->mY = 0;
- return true;
- }
- else if (mWindow)
- {
- const CGPoint& pos = getContentViewBoundsPosition(mWindow);
- position->mX = pos.x;
- position->mY = pos.y;
- return true;
- }
- llerrs << "No window and not fullscreen !" << llendl;
- return false;
- }
- bool LLWindowMacOSX::getSize(LLCoordScreen* size)
- {
- if (mFullscreen)
- {
- size->mX = mFullscreenWidth;
- size->mY = mFullscreenHeight;
- return true;
- }
- else if (mWindow)
- {
- const CGSize& sz = gHiDPISupport ? getDeviceContentViewSize(mWindow,
- mGLView)
- : getContentViewBoundsSize(mWindow);
- size->mX = sz.width;
- size->mY = sz.height;
- return true;
- }
- llerrs << "No window and not fullscreen !" << llendl;
- return false;
- }
- bool LLWindowMacOSX::getSize(LLCoordWindow* size)
- {
- if (mFullscreen)
- {
- size->mX = mFullscreenWidth;
- size->mY = mFullscreenHeight;
- return true;
- }
- else if (mWindow)
- {
- const CGSize& sz = gHiDPISupport ? getDeviceContentViewSize(mWindow,
- mGLView)
- : getContentViewBoundsSize(mWindow);
- size->mX = sz.width;
- size->mY = sz.height;
- return true;
- }
- llerrs << "No window and not fullscreen !" << llendl;
- return false;
- }
- bool LLWindowMacOSX::setPosition(const LLCoordScreen position)
- {
- if (mWindow)
- {
- float pos[2] = { (float)position.mX, (float)position.mY };
- setWindowPos(mWindow, pos);
- return true;
- }
- return false;
- }
- bool LLWindowMacOSX::setSize(const LLCoordScreen size)
- {
- if (mWindow)
- {
- LLCoordWindow to;
- convertCoords(size, &to);
- setWindowSize(mWindow, to.mX, to.mY);
- return true;
- }
- return false;
- }
- void LLWindowMacOSX::swapBuffers()
- {
- LL_FAST_TIMER(FTM_SWAP);
- CGLFlushDrawable(mContext);
- }
- void LLWindowMacOSX::setFSAASamples(U32 samples)
- {
- mFSAASamples = samples;
- mForceRebuild = true;
- }
- bool LLWindowMacOSX::restoreGamma()
- {
- CGDisplayRestoreColorSyncSettings();
- return true;
- }
- #if 0
- F32 LLWindowMacOSX::getGamma()
- {
- F32 result = 1.f; // Default to something sane
- CGGammaValue rmin, rmax, rgamma, gmin, gmax, ggamma, bmin, bmax, bgamma;
- if (CGGetDisplayTransferByFormula(mDisplay, &rmin, &rmax, &rgamma,
- &gmin, &gmax, &ggamma,
- &bmin, &bmax, &bgamma) == noErr)
- {
- F32 sum = rgamma + ggamma + bgamma;
- if (sum > 0.f)
- {
- result = 3.f / sum;
- }
- }
- return result;
- }
- #endif
- // Should we allow this in windowed mode ?
- bool LLWindowMacOSX::setGamma(F32 gamma)
- {
- mCurrentGamma = llclamp(gamma, 0.01f, 10.f);
- LL_DEBUGS("Window") << "Setting gamma to " << mCurrentGamma << LL_ENDL;
- CGGammaValue rmin, rmax, rgamma, gmin, gmax, ggamma, bmin, bmax, bgamma;
- if (CGGetDisplayTransferByFormula(mDisplay,
- &rmin, &rmax, &rgamma,
- &gmin, &gmax, &ggamma,
- &bmin, &bmax, &bgamma) != noErr)
- {
- return false;
- }
- F32 inv_gamma = 1.f / mCurrentGamma;
- return CGSetDisplayTransferByFormula(mDisplay,
- rmin, rmax, inv_gamma,
- gmin, gmax, inv_gamma,
- bmin, bmax, inv_gamma) == noErr;
- }
- // Constrains the mouse to the window.
- void LLWindowMacOSX::setMouseClipping(bool b)
- {
- // Just stash the requested state. We will simulate this when the cursor is
- // hidden by decoupling.
- mIsMouseClipping = b;
- adjustCursorDecouple();
- }
- bool LLWindowMacOSX::setCursorPosition(const LLCoordWindow& position)
- {
- LLCoordScreen screen_pos;
- if (!mCallbacks || !convertCoords(position, &screen_pos))
- {
- return false;
- }
- CGPoint new_pos;
- new_pos.x = screen_pos.mX;
- new_pos.y = screen_pos.mY;
- CGSetLocalEventsSuppressionInterval(0.0);
- bool result = CGWarpMouseCursorPosition(new_pos) == noErr;
- // Under certain circumstances, this will trigger us to decouple the cursor
- adjustCursorDecouple(true);
- // Trigger mouse move callback
- LLCoordGL gl_pos;
- convertCoords(position, &gl_pos);
- F32 scale = getSystemUISize();
- gl_pos.mX *= scale;
- gl_pos.mY *= scale;
- mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
- return result;
- }
- bool LLWindowMacOSX::getCursorPosition(LLCoordWindow* position)
- {
- if (!mWindow || !position)
- {
- return false;
- }
- float cursor_point[2];
- getCursorPos(mWindow, cursor_point);
- if (mCursorDecoupled)
- {
- cursor_point[0] += mCursorLastEventDeltaX;
- cursor_point[1] += mCursorLastEventDeltaY;
- }
- F32 scale = getSystemUISize();
- position->mX = cursor_point[0] * scale;
- position->mY = cursor_point[1] * scale;
- return true;
- }
- void LLWindowMacOSX::adjustCursorDecouple(bool warping_mouse)
- {
- if (mIsMouseClipping && mCursorHidden)
- {
- if (warping_mouse)
- {
- // The cursor should be decoupled. Make sure it is.
- if (!mCursorDecoupled)
- {
- LL_DEBUGS("Window") << "Decoupling cursor" << LL_ENDL;
- CGAssociateMouseAndMouseCursorPosition(false);
- mCursorDecoupled = true;
- mCursorIgnoreNextDelta = true;
- }
- }
- }
- else
- {
- // The cursor should not be decoupled. Make sure it is not.
- if (mCursorDecoupled)
- {
- LL_DEBUGS("Window") << "Re-coupling cursor" << LL_ENDL;
- CGAssociateMouseAndMouseCursorPosition(true);
- mCursorDecoupled = false;
- }
- }
- }
- F32 LLWindowMacOSX::getNativeAspectRatio()
- {
- if (mFullscreen)
- {
- return (F32)mFullscreenWidth / (F32)mFullscreenHeight;
- }
- else
- {
- // The constructor for this class grabs the aspect ratio of the monitor
- // before doing any resolution switching, and stashes it in
- // mOriginalAspectRatio. Here, we just return it.
- if (mOverrideAspectRatio > 0.f)
- {
- return mOverrideAspectRatio;
- }
- return mOriginalAspectRatio;
- }
- }
- F32 LLWindowMacOSX::getPixelAspectRatio()
- {
- // OS X always enforces a 1:1 pixel aspect ratio, regardless of video mode
- return 1.f;
- }
- // Since we are no longer supporting the "typical" fullscreen mode with CGL or
- // NSOpenGL anymore, these are unnecessary. -Geenz
- void LLWindowMacOSX::beforeDialog()
- {
- }
- void LLWindowMacOSX::afterDialog()
- {
- // Fixes crash with Core Flow view on OS-X
- CGLSetCurrentContext(mContext);
- }
- void LLWindowMacOSX::flashIcon(F32)
- {
- // 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()
- {
- return pasteBoardAvailable();
- }
- bool LLWindowMacOSX::pasteTextFromClipboard(LLWString& dst)
- {
- llutf16string str(copyFromPBoard());
- dst = utf16str_to_wstring(str);
- // *HACK: there is (sometimes) a spurious 'nul' character appearing at the
- // end of the string returned by copyFromPBoard()... So, let's remove it.
- size_t len = dst.size();
- if (len > 1 && dst[len - 1] == '\0')
- {
- dst = dst.substr(0, len - 1);
- }
- return dst != L"";
- }
- bool LLWindowMacOSX::copyTextToClipboard(const LLWString& s)
- {
- llutf16string utf16str = wstring_to_utf16str(s);
- return copyToPBoard(utf16str.data(), utf16str.length());
- }
- //virtual
- bool LLWindowMacOSX::isPrimaryTextAvailable()
- {
- return !mPrimaryClipboard.empty();
- }
- //virtual
- bool LLWindowMacOSX::pasteTextFromPrimary(LLWString& text)
- {
- if (mPrimaryClipboard.empty())
- {
- return false;
- }
- text = mPrimaryClipboard;
- return true;
- }
- // virtual
- bool LLWindowMacOSX::copyTextToPrimary(const LLWString& text)
- {
- mPrimaryClipboard = text;
- return true;
- }
- LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32& num_resolutions)
- {
- if (mSupportedResolutions)
- {
- num_resolutions = mNumSupportedResolutions;
- return mSupportedResolutions;
- }
- CFArrayRef modes = CGDisplayAvailableModes(mDisplay);
- if (modes)
- {
- mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
- mNumSupportedResolutions = 0;
- // Examine each mode
- CFIndex cnt = CFArrayGetCount(modes);
- for (CFIndex index = 0;
- index < cnt && mNumSupportedResolutions < MAX_NUM_RESOLUTIONS;
- ++index)
- {
- // Pull the mode dictionary out of the CFArray
- CFDictionaryRef mode =
- (CFDictionaryRef)CFArrayGetValueAtIndex(modes, index);
- S32 w = getDictLong(mode, kCGDisplayWidth);
- S32 h = getDictLong(mode, kCGDisplayHeight);
- S32 bits = getDictLong(mode, kCGDisplayBitsPerPixel);
- if (bits == BITS_PER_PIXEL && w >= 800 && h >= 600)
- {
- bool resolution_exists = false;
- for (S32 i = 0; i < mNumSupportedResolutions; ++i)
- {
- if (mSupportedResolutions[i].mWidth == w &&
- mSupportedResolutions[i].mHeight == h)
- {
- resolution_exists = true;
- break;
- }
- }
- if (!resolution_exists)
- {
- mSupportedResolutions[mNumSupportedResolutions].mWidth = w;
- mSupportedResolutions[mNumSupportedResolutions++].mHeight = h;
- }
- }
- }
- }
- num_resolutions = mNumSupportedResolutions;
- return mSupportedResolutions;
- }
- bool LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow* to)
- {
- to->mX = from.mX;
- to->mY = from.mY;
- return true;
- }
- bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to)
- {
- to->mX = from.mX;
- to->mY = from.mY;
- return true;
- }
- bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to)
- {
- if (mWindow && to)
- {
- float mouse_point[2];
- mouse_point[0] = from.mX;
- mouse_point[1] = from.mY;
- convertScreenToWindow(mWindow, mouse_point);
- to->mX = mouse_point[0];
- to->mY = mouse_point[1];
- return true;
- }
- return false;
- }
- bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen* to)
- {
- if (mWindow && to)
- {
- float mouse_point[2];
- mouse_point[0] = from.mX;
- mouse_point[1] = from.mY;
- convertWindowToScreen(mWindow, mouse_point);
- to->mX = mouse_point[0];
- to->mY = mouse_point[1];
- return true;
- }
- return false;
- }
- bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL* to)
- {
- LLCoordWindow window_coord;
- return convertCoords(from, &window_coord) &&
- convertCoords(window_coord, to);
- }
- bool LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen* to)
- {
- LLCoordWindow window_coord;
- return convertCoords(from, &window_coord) &&
- convertCoords(window_coord, to);
- }
- void LLWindowMacOSX::setupFailure(const std::string& text)
- {
- destroyContext();
- OSMessageBox(text);
- }
- static const char* cursorIDToName(int id)
- {
- switch (id)
- {
- case UI_CURSOR_ARROW: return "ui_cursor_arrow";
- case UI_CURSOR_WAIT: return "ui_cursor_wait";
- case UI_CURSOR_HAND: return "ui_cursor_hand";
- case UI_CURSOR_IBEAM: return "ui_cursor_ibeam";
- case UI_CURSOR_CROSS: return "ui_cursor_cross";
- case UI_CURSOR_SIZENWSE: return "ui_cursor_sizenwse";
- case UI_CURSOR_SIZENESW: return "ui_cursor_sizenesw";
- case UI_CURSOR_SIZEWE: return "ui_cursor_sizewe";
- case UI_CURSOR_SIZENS: return "ui_cursor_sizens";
- case UI_CURSOR_NO: return "ui_cursor_no";
- case UI_CURSOR_WORKING: return "ui_cursor_working";
- case UI_CURSOR_TOOLGRAB: return "ui_cursor_toolgrab";
- case UI_CURSOR_TOOLLAND: return "ui_cursor_toolland";
- case UI_CURSOR_TOOLFOCUS: return "ui_cursor_toolfocus";
- case UI_CURSOR_TOOLCREATE: return "ui_cursor_toolcreate";
- case UI_CURSOR_ARROWDRAG: return "ui_cursor_arrowdrag";
- case UI_CURSOR_ARROWCOPY: return "ui_cursor_arrowcopy";
- case UI_CURSOR_ARROWDRAGMULTI: return "ui_cursor_arrowdragmulti";
- case UI_CURSOR_ARROWCOPYMULTI: return "ui_cursor_arrowcopymulti";
- case UI_CURSOR_NOLOCKED: return "ui_cursor_nolocked";
- case UI_CURSOR_ARROWLOCKED: return "ui_cursor_arrowlocked";
- case UI_CURSOR_GRABLOCKED: return "ui_cursor_grablocked";
- case UI_CURSOR_TOOLTRANSLATE: return "ui_cursor_tooltranslate";
- case UI_CURSOR_TOOLROTATE: return "ui_cursor_toolrotate";
- case UI_CURSOR_TOOLSCALE: return "ui_cursor_toolscale";
- case UI_CURSOR_TOOLCAMERA: return "ui_cursor_toolcamera";
- case UI_CURSOR_TOOLPAN: return "ui_cursor_toolpan";
- case UI_CURSOR_TOOLZOOMIN: return "ui_cursor_toolzoomin";
- case UI_CURSOR_TOOLPICKOBJECT3: return "ui_cursor_toolpickobject3";
- case UI_CURSOR_TOOLSIT: return "ui_cursor_toolsit";
- case UI_CURSOR_TOOLBUY: return "ui_cursor_toolbuy";
- case UI_CURSOR_TOOLPAY: return "ui_cursor_toolpay";
- case UI_CURSOR_TOOLOPEN: return "ui_cursor_toolopen";
- case UI_CURSOR_TOOLPLAY: return "ui_cursor_toolplay";
- case UI_CURSOR_TOOLPAUSE: return "ui_cursor_toolpause";
- case UI_CURSOR_TOOLMEDIAOPEN: return "ui_cursor_toolmediaopen";
- case UI_CURSOR_PIPETTE: return "ui_cursor_pipette";
- case UI_CURSOR_TOOLPATHFINDING: return "ui_cursor_pathfinding";
- case UI_CURSOR_TOOLPATHFINDING_PATH_START: return "ui_cursor_pathfinding_start";
- case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD: return "ui_cursor_pathfinding_start_add";
- case UI_CURSOR_TOOLPATHFINDING_PATH_END: return "ui_cursor_pathfinding_end";
- case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD: return "ui_cursor_pathfinding_end_add";
- case UI_CURSOR_TOOLNO: return "ui_cursor_no";
- }
- llerrs << "Unknown cursor id: " << id << llendl;
- return "ui_cursor_arrow";
- }
- static CursorRef gCursors[UI_CURSOR_COUNT];
- static void initPixmapCursor(int cursorid, int hotspot_x, int hotspot_y)
- {
- // Cursors are in:
- // <Application Bundle>/Contents/Resources/cursors_mac/ui_cursor_foo.tif
- std::string fullpath = gDirUtil.getAppRODataDir() + "/cursors_mac/";
- fullpath += cursorIDToName(cursorid);
- fullpath += ".tif";
- gCursors[cursorid] = createImageCursor(fullpath.c_str(), hotspot_x,
- hotspot_y);
- }
- void LLWindowMacOSX::updateCursor()
- {
- if (mNextCursor == UI_CURSOR_ARROW && mBusyCount > 0)
- {
- mNextCursor = UI_CURSOR_WORKING;
- }
- if (mCurrentCursor == mNextCursor)
- {
- if (mCursorHidden && mHideCursorPermanent && isCGCursorVisible())
- {
- hideNSCursor();
- adjustCursorDecouple();
- }
- return;
- }
- // RN: replace multi-drag cursors with single versions
- if (mNextCursor == UI_CURSOR_ARROWDRAGMULTI)
- {
- mNextCursor = UI_CURSOR_ARROWDRAG;
- }
- else if (mNextCursor == UI_CURSOR_ARROWCOPYMULTI)
- {
- mNextCursor = UI_CURSOR_ARROWCOPY;
- }
- switch (mNextCursor)
- {
- default:
- case UI_CURSOR_ARROW:
- setArrowCursor();
- if (mCursorHidden)
- {
- // Since InitCursor resets the hide level, correct for it here.
- hideNSCursor();
- }
- break;
- // Some of the standard Windows cursors have no standard Mac
- // equivalents. Find out what they look like and replicate them.
- // These are essentially correct
- case UI_CURSOR_WAIT:
- // Apple purposely does not 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_ARROWCOPY:
- setCopyCursor();
- break;
- // Double-check these
- case UI_CURSOR_NO:
- case UI_CURSOR_SIZEWE:
- case UI_CURSOR_SIZENS:
- case UI_CURSOR_SIZENWSE:
- case UI_CURSOR_SIZENESW:
- case UI_CURSOR_WORKING:
- case UI_CURSOR_TOOLGRAB:
- case UI_CURSOR_TOOLLAND:
- case UI_CURSOR_TOOLFOCUS:
- case UI_CURSOR_TOOLCREATE:
- case UI_CURSOR_ARROWDRAG:
- case UI_CURSOR_NOLOCKED:
- case UI_CURSOR_ARROWLOCKED:
- case UI_CURSOR_GRABLOCKED:
- case UI_CURSOR_TOOLTRANSLATE:
- case UI_CURSOR_TOOLROTATE:
- case UI_CURSOR_TOOLSCALE:
- case UI_CURSOR_TOOLCAMERA:
- case UI_CURSOR_TOOLPAN:
- case UI_CURSOR_TOOLZOOMIN:
- case UI_CURSOR_TOOLPICKOBJECT3:
- case UI_CURSOR_TOOLPLAY:
- case UI_CURSOR_TOOLPAUSE:
- case UI_CURSOR_TOOLMEDIAOPEN:
- case UI_CURSOR_TOOLSIT:
- case UI_CURSOR_TOOLBUY:
- case UI_CURSOR_TOOLPAY:
- case UI_CURSOR_TOOLOPEN:
- case UI_CURSOR_TOOLPATHFINDING:
- case UI_CURSOR_TOOLPATHFINDING_PATH_START:
- case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD:
- case UI_CURSOR_TOOLPATHFINDING_PATH_END:
- case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD:
- case UI_CURSOR_TOOLNO:
- {
- if (setImageCursor(gCursors[mNextCursor]) != noErr)
- {
- setArrowCursor();
- }
- }
- }
- mCurrentCursor = mNextCursor;
- }
- void LLWindowMacOSX::initCursors()
- {
- initPixmapCursor(UI_CURSOR_NO, 8, 8);
- initPixmapCursor(UI_CURSOR_WORKING, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLGRAB, 2, 14);
- initPixmapCursor(UI_CURSOR_TOOLLAND, 13, 8);
- initPixmapCursor(UI_CURSOR_TOOLFOCUS, 7, 6);
- initPixmapCursor(UI_CURSOR_TOOLCREATE, 7, 7);
- initPixmapCursor(UI_CURSOR_ARROWDRAG, 1, 1);
- initPixmapCursor(UI_CURSOR_ARROWCOPY, 1, 1);
- initPixmapCursor(UI_CURSOR_NOLOCKED, 8, 8);
- initPixmapCursor(UI_CURSOR_ARROWLOCKED, 1, 1);
- initPixmapCursor(UI_CURSOR_GRABLOCKED, 2, 14);
- initPixmapCursor(UI_CURSOR_TOOLTRANSLATE, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLROTATE, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLSCALE, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLCAMERA, 7, 6);
- initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6);
- initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6);
- initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLSIT, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLBUY, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLOPEN, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLNO, 8, 8);
- initPixmapCursor(UI_CURSOR_SIZENWSE, 10, 10);
- initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10);
- initPixmapCursor(UI_CURSOR_SIZEWE, 10, 10);
- initPixmapCursor(UI_CURSOR_SIZENS, 10, 10);
- }
- void LLWindowMacOSX::setCursor(ECursorType c)
- {
- if (!mCursorFrozen)
- {
- mNextCursor = c;
- }
- }
- void LLWindowMacOSX::captureMouse()
- {
- // By registering a global Event handler for mouse move events, we ensure
- // that mouse events are always processed. Thus, capture and release are
- // unnecessary.
- }
- void LLWindowMacOSX::releaseMouse()
- {
- // By registering a global Event handler for mouse move events, we ensure
- // that mouse events are always processed. Thus, capture and release are
- // unnecessary.
- }
- void LLWindowMacOSX::hideCursor()
- {
- if (!mCursorHidden)
- {
- mCursorHidden = mHideCursorPermanent = true;
- hideNSCursor();
- }
- adjustCursorDecouple();
- }
- void LLWindowMacOSX::showCursor()
- {
- if (mCursorHidden)
- {
- mCursorHidden = mHideCursorPermanent = false;
- showNSCursor();
- }
- adjustCursorDecouple();
- }
- void LLWindowMacOSX::showCursorFromMouseMove()
- {
- if (!mHideCursorPermanent)
- {
- showCursor();
- }
- }
- void LLWindowMacOSX::hideCursorUntilMouseMove()
- {
- if (!mHideCursorPermanent)
- {
- hideCursor();
- mHideCursorPermanent = false;
- }
- }
- //
- // LLSplashScreenMacOSX
- //
- LLSplashScreenMacOSX::LLSplashScreenMacOSX()
- {
- mWindow = NULL;
- }
- void LLSplashScreenMacOSX::showImpl()
- {
- // This _could_ be used to display a spash screen...
- }
- void LLSplashScreenMacOSX::updateImpl(const std::string& mesg)
- {
- }
- void LLSplashScreenMacOSX::hideImpl()
- {
- if (mWindow)
- {
- mWindow = NULL;
- }
- }
- S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption,
- U32 type)
- {
- 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)
- {
- bool found = false;
- for (S32 i = 0; i < gURLProtocolWhitelistCount; ++i)
- {
- if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos)
- {
- found = true;
- break;
- }
- }
- if (!found)
- {
- llwarns << "spawn_web_browser called for url with protocol not on whitelist: "
- << escaped_url << llendl;
- return;
- }
- S32 result = 0;
- CFURLRef urlRef = NULL;
- llinfos << "Opening URL " << escaped_url << llendl;
- CFStringRef stringRef = CFStringCreateWithCString(NULL,
- escaped_url.c_str(),
- kCFStringEncodingUTF8);
- if (stringRef)
- {
- // This will succeed if the string is a full URL, including the http://
- // Note that URLs specified this way need to be properly percent-
- // escaped.
- urlRef = CFURLCreateWithString(NULL, stringRef, NULL);
- // Do not use CRURLCreateWithFileSystemPath -- only want valid URLs
- CFRelease(stringRef);
- }
- if (urlRef)
- {
- result = LSOpenCFURLRef(urlRef, NULL);
- if (result != noErr)
- {
- llwarns << "Error " << result << " on open." << llendl;
- }
- CFRelease(urlRef);
- }
- else
- {
- llwarns << "Could not create URL." << llendl;
- }
- }
- // Make the raw keyboard data available
- LLSD LLWindowMacOSX::getNativeKeyData()
- {
- LLSD result = LLSD::emptyMap();
- if (mRawKeyEvent)
- {
- result["event_type"] = LLSD::Integer(mRawKeyEvent->mEventType);
- result["event_modifiers"] =
- LLSD::Integer(mRawKeyEvent->mEventModifiers);
- result["event_keycode"] = LLSD::Integer(mRawKeyEvent->mEventKeyCode);
- result["event_chars"] =
- mRawKeyEvent->mEventChars ? LLSD(LLSD::Integer(mRawKeyEvent->mEventChars))
- : LLSD();
- result["event_umodchars"] =
- mRawKeyEvent->mEventUnmodChars ? LLSD(LLSD::Integer(mRawKeyEvent->mEventUnmodChars))
- : LLSD();
- result["event_isrepeat"] = LLSD::Boolean(mRawKeyEvent->mEventRepeat);
- }
- LL_DEBUGS("Window") << "Native key data is: " << result << LL_ENDL;
- return result;
- }
- F32 LLWindowMacOSX::getSystemUISize()
- {
- return gHiDPISupport ? ::getDeviceUnitSize(mGLView) : 1.f;
- }
- void* LLWindowMacOSX::getPlatformWindow()
- {
- // NOTE: this will be NULL in fullscreen mode. Plan accordingly.
- return (void*)mWindow;
- }
- void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor* preeditor, bool b)
- {
- if (!preeditor) return;
- if (preeditor != mPreeditor && !b)
- {
- // This condition may occur by a call to
- // setEnabled(bool) against LLTextEditor or LLLineEditor
- // when the control is not focused.
- // We need to silently ignore the case so that
- // the language input status of the focused control
- // is not disturbed.
- return;
- }
- // Take care of old and new preeditors.
- if (preeditor != mPreeditor || !b)
- {
- // We need to interrupt before updating mPreeditor,
- // so that the fix string from input method goes to
- // the old preeditor.
- if (mLanguageTextInputAllowed)
- {
- interruptLanguageTextInput();
- }
- mPreeditor = (b ? preeditor : NULL);
- }
- if (mLanguageTextInputAllowed != b)
- {
- mLanguageTextInputAllowed = b;
- allowDirectMarkedTextInput(b, mGLView);
- }
- }
- void LLWindowMacOSX::interruptLanguageTextInput()
- {
- commitCurrentPreedit(mGLView);
- }
- //static
- std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList()
- {
- // Fonts previously in getFontListSans() have moved to fonts.xml.
- return std::vector<std::string>();
- }
- void LLWindowMacOSX::updateMouseDeltas(float* deltas)
- {
- if (mCursorDecoupled && deltas)
- {
- if (mCursorIgnoreNextDelta)
- {
- mCursorLastEventDeltaX = mCursorLastEventDeltaY = 0;
- mCursorIgnoreNextDelta = false;
- }
- else
- {
- mCursorLastEventDeltaX = ll_round(deltas[0]);
- mCursorLastEventDeltaY = ll_round(-deltas[1]);
- }
- }
- else
- {
- mCursorLastEventDeltaX = mCursorLastEventDeltaY = 0;
- }
- }
- void LLWindowMacOSX::getMouseDeltas(float* deltas)
- {
- if (deltas)
- {
- deltas[0] = mCursorLastEventDeltaX;
- deltas[1] = mCursorLastEventDeltaY;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Shared OpenGL context support
- ///////////////////////////////////////////////////////////////////////////////
- struct LLSharedOpenGLContext
- {
- CGLContextObj mContext;
- };
- void* LLWindowMacOSX::createSharedContext()
- {
- LLSharedOpenGLContext* context = new LLSharedOpenGLContext;
- CGLCreateContext(mPixelFormat, mContext, &(context->mContext));
- if (!context->mContext)
- {
- // Something went (very) wrong... Free the structure and return a NULL
- // pointer to signify we do not have a GL context available. HB
- llwarns_sparse << "Failed to create a new shared GL context."
- << llendl;
- delete context;
- return NULL;
- }
- if (sUseMultGL)
- {
- CGLEnable(mContext, kCGLCEMPEngine);
- }
- return (void*)context;
- }
- void LLWindowMacOSX::makeContextCurrent(void* context)
- {
- if (context)
- {
- CGLSetCurrentContext(((LLSharedOpenGLContext*)context)->mContext);
- }
- else
- {
- // Restore main GL thread context.
- CGLSetCurrentContext(mContext);
- }
- }
- void LLWindowMacOSX::destroySharedContext(void* context)
- {
- if (context) // Ignore attempts to destroy invalid contexts. HB
- {
- LLSharedOpenGLContext* sc = (LLSharedOpenGLContext*)context;
- CGLDestroyContext(sc->mContext);
- delete sc;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- // These functions are used as wrappers for our internal event handling
- // callbacks. It is a good idea to wrap these to avoid reworking more code than
- // we need to within LLWindow.
- ///////////////////////////////////////////////////////////////////////////////
- bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
- {
- bool ret_val = false;
- if (gKeyboardp)
- {
- mRawKeyEvent = event;
- ret_val = gKeyboardp->handleKeyUp(key, mask);
- mRawKeyEvent = NULL;
- }
- return ret_val;
- }
- bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask)
- {
- bool ret_val = false;
- if (gKeyboardp)
- {
- mRawKeyEvent = event;
- ret_val = gKeyboardp->handleKeyDown(key, mask);
- mRawKeyEvent = NULL;
- }
- return ret_val;
- }
- void callResetKeys()
- {
- if (gKeyboardp)
- {
- gKeyboardp->resetKeys();
- }
- }
- bool callUnicodeCallback(wchar_t character, unsigned int mask)
- {
- if (!sWindowImplementation) return false;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return false;
- NativeKeyEventData event_data;
- memset(&event_data, 0, sizeof(NativeKeyEventData));
- event_data.mKeyEvent = NativeKeyEventData::KEYCHAR;
- event_data.mEventType = 0;
- event_data.mEventModifiers = mask;
- event_data.mEventKeyCode = 0;
- event_data.mEventChars = character;
- event_data.mEventUnmodChars = character;
- event_data.mEventRepeat = false;
- mRawKeyEvent = &event_data;
- bool result = callbacks->handleUnicodeChar(character, mask);
- mRawKeyEvent = NULL;
- return result;
- }
- void callFocus()
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleFocus(sWindowImplementation);
- }
- }
- }
- void callFocusLost()
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleFocusLost(sWindowImplementation);
- }
- }
- }
- void callRightMouseDown(float* pos, MASK mask)
- {
- if (!sWindowImplementation || !gKeyboardp) return;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return;
- if (sWindowImplementation->allowsLanguageInput())
- {
- sWindowImplementation->interruptLanguageTextInput();
- }
- LLCoordGL out_coords;
- out_coords.mX = ll_round(pos[0]);
- out_coords.mY = ll_round(pos[1]);
- callbacks->handleRightMouseDown(sWindowImplementation, out_coords,
- gKeyboardp->currentMask(true));
- }
- void callRightMouseUp(float* pos, MASK mask)
- {
- if (!sWindowImplementation || !gKeyboardp) return;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return;
- if (sWindowImplementation->allowsLanguageInput())
- {
- sWindowImplementation->interruptLanguageTextInput();
- }
- LLCoordGL out_coords;
- out_coords.mX = ll_round(pos[0]);
- out_coords.mY = ll_round(pos[1]);
- callbacks->handleRightMouseUp(sWindowImplementation, out_coords,
- gKeyboardp->currentMask(true));
- }
- void callLeftMouseDown(float* pos, MASK mask)
- {
- if (!sWindowImplementation || !gKeyboardp) return;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return;
- if (sWindowImplementation->allowsLanguageInput())
- {
- sWindowImplementation->interruptLanguageTextInput();
- }
- LLCoordGL out_coords;
- out_coords.mX = ll_round(pos[0]);
- out_coords.mY = ll_round(pos[1]);
- callbacks->handleMouseDown(sWindowImplementation, out_coords,
- gKeyboardp->currentMask(true));
- }
- void callLeftMouseUp(float* pos, MASK mask)
- {
- if (!sWindowImplementation || !gKeyboardp) return;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return;
- if (sWindowImplementation->allowsLanguageInput())
- {
- sWindowImplementation->interruptLanguageTextInput();
- }
- LLCoordGL out_coords;
- out_coords.mX = ll_round(pos[0]);
- out_coords.mY = ll_round(pos[1]);
- callbacks->handleMouseUp(sWindowImplementation, out_coords,
- gKeyboardp->currentMask(true));
- }
- void callDoubleClick(float* pos, MASK mask)
- {
- if (!sWindowImplementation || !gKeyboardp) return;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return;
- if (sWindowImplementation->allowsLanguageInput())
- {
- sWindowImplementation->interruptLanguageTextInput();
- }
- LLCoordGL out_coords;
- out_coords.mX = ll_round(pos[0]);
- out_coords.mY = ll_round(pos[1]);
- callbacks->handleDoubleClick(sWindowImplementation, out_coords,
- gKeyboardp->currentMask(true));
- }
- void callResize(unsigned int width, unsigned int height)
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleResize(sWindowImplementation, width, height);
- }
- }
- }
- void callMouseMoved(float* pos, MASK mask)
- {
- if (!sWindowImplementation || !gKeyboardp) return;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return;
- LLCoordGL out_coords;
- out_coords.mX = ll_round(pos[0]);
- out_coords.mY = ll_round(pos[1]);
- float deltas[2];
- sWindowImplementation->getMouseDeltas(deltas);
- out_coords.mX += deltas[0];
- out_coords.mY += deltas[1];
- callbacks->handleMouseMove(sWindowImplementation, out_coords,
- gKeyboardp->currentMask(true));
- }
- void callMouseDragged(float* pos, MASK mask)
- {
- if (!sWindowImplementation || !gKeyboardp) return;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return;
- LLCoordGL out_coords;
- out_coords.mX = ll_round(pos[0]);
- out_coords.mY = ll_round(pos[1]);
- float deltas[2];
- sWindowImplementation->getMouseDeltas(deltas);
- out_coords.mX += deltas[0];
- out_coords.mY += deltas[1];
- callbacks->handleMouseDragged(sWindowImplementation, out_coords,
- gKeyboardp->currentMask(true));
- }
- void callScrollMoved(float delta)
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleScrollWheel(sWindowImplementation, delta);
- }
- }
- }
- void callMouseExit()
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleMouseLeave(sWindowImplementation);
- }
- }
- }
- void callWindowFocus()
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleFocus(sWindowImplementation);
- return;
- }
- }
- llwarns << "Window implementation or callbacks not yet initialized."
- << llendl;
- }
- void callWindowUnfocus()
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleFocusLost(sWindowImplementation);
- }
- }
- }
- void callWindowHide()
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleActivate(sWindowImplementation, false);
- }
- }
- }
- void callWindowUnhide()
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleActivate(sWindowImplementation, true);
- }
- }
- }
- void callWindowDidChangeScreen()
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleWindowDidChangeScreen(sWindowImplementation);
- }
- }
- }
- void callDeltaUpdate(float* delta, MASK mask)
- {
- if (sWindowImplementation)
- {
- sWindowImplementation->updateMouseDeltas(delta);
- }
- }
- void callMiddleMouseDown(float* pos, MASK mask)
- {
- if (!sWindowImplementation) return;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return;
- LLCoordGL out_coords;
- out_coords.mX = ll_round(pos[0]);
- out_coords.mY = ll_round(pos[1]);
- float deltas[2];
- sWindowImplementation->getMouseDeltas(deltas);
- out_coords.mX += deltas[0];
- out_coords.mY += deltas[1];
- callbacks->handleMiddleMouseDown(sWindowImplementation, out_coords, mask);
- }
- void callMiddleMouseUp(float* pos, MASK mask)
- {
- if (!sWindowImplementation) return;
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (!callbacks) return;
- LLCoordGL out_coords;
- out_coords.mX = ll_round(pos[0]);
- out_coords.mY = ll_round(pos[1]);
- float deltas[2];
- sWindowImplementation->getMouseDeltas(deltas);
- out_coords.mX += deltas[0];
- out_coords.mY += deltas[1];
- callbacks->handleMiddleMouseUp(sWindowImplementation, out_coords, mask);
- }
- void callQuitHandler()
- {
- if (sWindowImplementation)
- {
- LLWindowCallbacks* callbacks = sWindowImplementation->getCallbacks();
- if (callbacks)
- {
- callbacks->handleQuit(sWindowImplementation);
- }
- }
- }
- void getPreeditSelectionRange(int* position, int* length)
- {
- if (sWindowImplementation)
- {
- LLPreeditor* preeditor = sWindowImplementation->getPreeditor();
- if (preeditor)
- {
- preeditor->getSelectionRange(position, length);
- }
- }
- }
- void getPreeditMarkedRange(int* position, int* length)
- {
- if (sWindowImplementation)
- {
- LLPreeditor* preeditor = sWindowImplementation->getPreeditor();
- if (preeditor)
- {
- preeditor->getPreeditRange(position, length);
- }
- }
- }
- void setPreeditMarkedRange(int position, int length)
- {
- if (sWindowImplementation)
- {
- LLPreeditor* preeditor = sWindowImplementation->getPreeditor();
- if (preeditor)
- {
- preeditor->markAsPreedit(position, length);
- }
- }
- }
- bool handleUnicodeCharacter(wchar_t c)
- {
- if (sWindowImplementation)
- {
- LLPreeditor* preeditor = sWindowImplementation->getPreeditor();
- if (preeditor)
- {
- return preeditor->handleUnicodeCharHere(c);
- }
- }
- return false;
- }
- void resetPreedit()
- {
- if (sWindowImplementation)
- {
- LLPreeditor* preeditor = sWindowImplementation->getPreeditor();
- if (preeditor)
- {
- preeditor->resetPreedit();
- }
- }
- }
- // For reasons of convenience, handle IME updates here. This largely mirrors the
- // old implementation.
- void setMarkedText(unsigned short* unitext, unsigned int* sel_range,
- unsigned int* replace_range, long text_len,
- attributedStringInfo segments)
- {
- if (!sWindowImplementation) return;
- LLPreeditor* preeditor = sWindowImplementation->getPreeditor();
- if (!preeditor) return;
- preeditor->resetPreedit();
- // This should be a viable replacement for the
- // kEventParamTextInputSendReplaceRange parameter.
- if (replace_range[0] < replace_range[1])
- {
- const LLWString& text = preeditor->getWText();
- S32 location = wstring_length_from_utf16_length(text, 0,
- replace_range[0]);
- S32 length = wstring_length_from_utf16_length(text, location,
- replace_range[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);
- }
- void getPreeditLocation(float* location, unsigned int length)
- {
- if (!sWindowImplementation)
- {
- return;
- }
- LLPreeditor* preeditor = sWindowImplementation->getPreeditor();
- if (preeditor)
- {
- LLCoordGL coord;
- LLCoordScreen screen;
- LLRect rect;
- preeditor->getPreeditLocation(length, &coord, &rect, NULL);
- float c[4] = { (float)coord.mX, (float)coord.mY, 0.f, 0.f };
- convertRectToScreen(sWindowImplementation->getPlatformWindow(), c);
- location[0] = c[0];
- location[1] = c[1];
- }
- }
- void callModifier(MASK mask)
- {
- if (gKeyboardp)
- {
- gKeyboardp->handleModifier(mask);
- }
- }
- // Drag and drop into viewer window not yet implemented in the Cool VL Viewer
- void callHandleDragEntered(std::string url)
- {
- }
- void callHandleDragExited(std::string url)
- {
- }
- void callHandleDragUpdated(std::string url)
- {
- }
- void callHandleDragDropped(std::string url)
- {
- }
|