summaryrefslogtreecommitdiff
path: root/indra/llwindow/llwindowsdl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llwindow/llwindowsdl.cpp')
-rw-r--r--indra/llwindow/llwindowsdl.cpp757
1 files changed, 536 insertions, 221 deletions
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index df8b2ba5ab..98484419f9 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -51,12 +51,14 @@ extern "C" {
# include "fontconfig/fontconfig.h"
}
-#if LL_LINUX
+#if LL_LINUX || __FreeBSD__
// not necessarily available on random SDL platforms, so #if LL_LINUX
// for execv(), waitpid(), fork()
# include <unistd.h>
# include <sys/types.h>
# include <sys/wait.h>
+# define GLX_GLXEXT_PROTOTYPES 1
+# include <GL/glx.h>
#endif // LL_LINUX
extern BOOL gDebugWindowProc;
@@ -66,6 +68,43 @@ const S32 MAX_NUM_RESOLUTIONS = 200;
// static variable for ATI mouse cursor crash work-around:
static bool ATIbug = false;
+#if LL_DARWIN
+
+#include <OpenGL/OpenGL.h>
+#include <CoreGraphics/CGDirectDisplay.h>
+#include <CoreServices/CoreServices.h>
+
+BOOL gHiDPISupport = TRUE;
+
+namespace
+{
+ struct NativeKeyEventData {
+ enum EventType {
+ KEYUNKNOWN,
+ KEYUP,
+ KEYDOWN,
+ KEYCHAR
+ };
+
+ EventType mKeyEvent = KEYUNKNOWN;
+ uint32_t mEventType = 0;
+ uint32_t mEventModifiers = 0;
+ uint32_t mEventKeyCode = 0;
+ uint32_t mEventChars = 0;
+ uint32_t mEventUnmodChars = 0;
+ bool mEventRepeat = false;
+ } *mRawKeyEvent = NULL;
+}
+//
+// LLWindowMacOSX
+//
+
+BOOL LLWindowSDL::sUseMultGL = FALSE;
+
+#endif
+
+BOOL hasHIDPI = 0;
+
//
// LLWindowSDL
//
@@ -119,7 +158,9 @@ bool LLWindowSDL::ll_try_gtk_init(void)
if (!tried_gtk_init)
{
tried_gtk_init = TRUE;
+#ifndef LL_USESYSTEMLIBS
if (!g_thread_supported ()) g_thread_init (NULL);
+#endif
maybe_lock_display();
gtk_is_good = gtk_init_check(NULL, NULL);
maybe_unlock_display();
@@ -197,6 +238,10 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
gKeyboard->setCallbacks(callbacks);
// Note that we can't set up key-repeat until after SDL has init'd video
+#if LL_DARWIN
+ hasHIDPI = gHiDPISupport;
+#endif
+
// Ignore use_gl for now, only used for drones on PC
mWindow = NULL;
mNeedsResize = FALSE;
@@ -267,7 +312,7 @@ static SDL_Surface *Load_BMP_Resource(const char *basename)
return SDL_LoadBMP(path_buffer);
}
-#if LL_X11
+#if 0
// This is an XFree86/XOrg-specific hack for detecting the amount of Video RAM
// on this machine. It works by searching /var/log/var/log/Xorg.?.log or
// /var/log/XFree86.?.log for a ': (VideoRAM ?|Memory): (%d+) kB' regex, where
@@ -430,44 +475,25 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
<< int(c_sdl_version.major) << "."
<< int(c_sdl_version.minor) << "."
<< int(c_sdl_version.patch) << LL_ENDL;
- const SDL_version *r_sdl_version;
- r_sdl_version = SDL_Linked_Version();
+ SDL_version r_sdl_version;
+ SDL_GetVersion(&r_sdl_version);
LL_INFOS() << " Running against SDL "
- << int(r_sdl_version->major) << "."
- << int(r_sdl_version->minor) << "."
- << int(r_sdl_version->patch) << LL_ENDL;
+ << int(r_sdl_version.major) << "."
+ << int(r_sdl_version.minor) << "."
+ << int(r_sdl_version.patch) << LL_ENDL;
- const SDL_VideoInfo *video_info = SDL_GetVideoInfo( );
- if (!video_info)
+ SDL_DisplayMode display_mode;
+ if (SDL_GetDesktopDisplayMode(0, &display_mode) < 0)
{
LL_INFOS() << "SDL_GetVideoInfo() failed! " << SDL_GetError() << LL_ENDL;
setupFailure("SDL_GetVideoInfo() failed, Window creation error", "Error", OSMB_OK);
return FALSE;
}
- if (video_info->current_h > 0)
+ if (display_mode.h > 0)
{
- mOriginalAspectRatio = (float)video_info->current_w / (float)video_info->current_h;
- LL_INFOS() << "Original aspect ratio was " << video_info->current_w << ":" << video_info->current_h << "=" << mOriginalAspectRatio << LL_ENDL;
- }
-
- SDL_EnableUNICODE(1);
- SDL_WM_SetCaption(mWindowTitle.c_str(), mWindowTitle.c_str());
-
- // Set the application icon.
- SDL_Surface *bmpsurface;
- bmpsurface = Load_BMP_Resource("ll_icon.BMP");
- if (bmpsurface)
- {
- // This attempts to give a black-keyed mask to the icon.
- SDL_SetColorKey(bmpsurface,
- SDL_SRCCOLORKEY,
- SDL_MapRGB(bmpsurface->format, 0,0,0) );
- SDL_WM_SetIcon(bmpsurface, NULL);
- // The SDL examples cheerfully avoid freeing the icon
- // surface, but I'm betting that's leaky.
- SDL_FreeSurface(bmpsurface);
- bmpsurface = NULL;
+ mOriginalAspectRatio = (float)display_mode.w / (float)display_mode.h;
+ LL_INFOS() << "Original aspect ratio was " << display_mode.w << ":" << display_mode.h << "=" << mOriginalAspectRatio << LL_ENDL;
}
// note: these SetAttributes make Tom's 9600-on-AMD64 fail to
@@ -481,13 +507,23 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
// We need stencil support for a few (minor) things.
if (!getenv("LL_GL_NO_STENCIL"))
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, (bits <= 16) ? 1 : 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, (bits <= 16) ? 1 : 8);
// *FIX: try to toggle vsync here?
mFullscreen = fullscreen;
- int sdlflags = SDL_OPENGL | SDL_RESIZABLE | SDL_ANYFORMAT;
+ int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;// | SDL_ANYFORMAT;
+
+ if(hasHIDPI) sdlflags = sdlflags | SDL_WINDOW_ALLOW_HIGHDPI;
+
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
+#if LL_DARWIN
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+#else
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
+#endif
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
@@ -551,19 +587,24 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
height = 768;
}
- mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN);
+ mWindow = SDL_CreateWindow(mWindowTitle.c_str(),
+ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ width, height, sdlflags | SDL_WINDOW_FULLSCREEN);
+
if (!mWindow && bits > 16)
{
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
- mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN);
+ mWindow = SDL_CreateWindow(mWindowTitle.c_str(),
+ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ width, height, sdlflags | SDL_WINDOW_FULLSCREEN);
}
if (mWindow)
{
+ SDL_GL_CreateContext(mWindow);
mFullscreen = TRUE;
- mFullscreenWidth = mWindow->w;
- mFullscreenHeight = mWindow->h;
- mFullscreenBits = mWindow->format->BitsPerPixel;
+ SDL_GetWindowSize(mWindow, &mFullscreenWidth, &mFullscreenHeight);
+ //mFullscreenBits = mWindow->format->BitsPerPixel;
mFullscreenRefresh = -1;
LL_INFOS() << "Running at " << mFullscreenWidth
@@ -595,11 +636,15 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
width = 768;
LL_INFOS() << "createContext: creating window " << width << "x" << height << "x" << bits << LL_ENDL;
- mWindow = SDL_SetVideoMode(width, height, bits, sdlflags);
+ mWindow = SDL_CreateWindow(mWindowTitle.c_str(),
+ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ width, height, sdlflags);
if (!mWindow && bits > 16)
{
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
- mWindow = SDL_SetVideoMode(width, height, bits, sdlflags);
+ mWindow = SDL_CreateWindow(mWindowTitle.c_str(),
+ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ width, height, sdlflags);
}
if (!mWindow)
@@ -608,29 +653,63 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
setupFailure("Window creation error", "Error", OSMB_OK);
return FALSE;
}
+ SDL_GL_CreateContext(mWindow);
} else if (!mFullscreen && (mWindow != NULL))
{
LL_INFOS() << "createContext: SKIPPING - !fullscreen, but +mWindow " << width << "x" << height << "x" << bits << LL_ENDL;
}
- // Detect video memory size.
-# if LL_X11
- gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024;
- if (gGLManager.mVRAM != 0)
+ //SDL_EnableUNICODE(1);
+ SDL_SetWindowTitle(mWindow, mWindowTitle.c_str());
+
+ // Set the application icon.
+ SDL_Surface *bmpsurface;
+ bmpsurface = Load_BMP_Resource("ll_icon.BMP");
+ if (bmpsurface)
{
- LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
+ // This attempts to give a black-keyed mask to the icon.
+ SDL_SetColorKey(bmpsurface,
+ SDL_TRUE,
+ SDL_MapRGB(bmpsurface->format, 0,0,0) );
+ SDL_SetWindowIcon(mWindow, bmpsurface);
+ // The SDL examples cheerfully avoid freeing the icon
+ // surface, but I'm betting that's leaky.
+ SDL_FreeSurface(bmpsurface);
+ bmpsurface = NULL;
+ }
+
+ // Detect video memory size.
+#if LL_DARWIN
+ CGLRendererInfoObj info = 0;
+ GLint vram_megabytes = 0;
+ int num_renderers = 0;
+ auto err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
+ &info, &num_renderers);
+ if (!err) {
+ CGLDescribeRenderer(info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes);
+ CGLDestroyRendererInfo(info);
} else
-# endif // LL_X11
- {
- // fallback to letting SDL detect VRAM.
- // note: I've not seen SDL's detection ever actually find
- // VRAM != 0, but if SDL *does* detect it then that's a bonus.
- gGLManager.mVRAM = video_info->video_mem / 1024;
- if (gGLManager.mVRAM != 0)
- {
- LL_INFOS() << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
+ vram_megabytes = 256;
+ gGLManager.mVRAM = vram_megabytes;
+#else
+ PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger;
+ queryInteger = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC)
+ glXGetProcAddressARB((const GLubyte *)"glXQueryCurrentRendererIntegerMESA");
+ unsigned int vram_megabytes = 0;
+ queryInteger(GLX_RENDERER_VIDEO_MEMORY_MESA, &vram_megabytes);
+ if (!vram_megabytes) {
+ glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, (int *)&vram_megabytes);
+ vram_megabytes /= 1024;
}
- }
+ if (!vram_megabytes) {
+ glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, (int *)&vram_megabytes);
+ vram_megabytes /= 1024;
+ }
+
+ gGLManager.mVRAM = vram_megabytes;
+# endif // LL_DARWIN
+ if (gGLManager.mVRAM)
+ LL_INFOS() << "Detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
// If VRAM is not detected, that is handled later
// *TODO: Now would be an appropriate time to check for some
@@ -660,6 +739,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
// relaxed about if we have to.
if (colorBits < 32)
{
+#if 0
close();
setupFailure(
"Second Life requires True Color (32-bit) to run in a window.\n"
@@ -670,6 +750,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
"Error",
OSMB_OK);
return FALSE;
+#endif
}
#if 0 // *FIX: we're going to brave it for now...
@@ -693,15 +774,17 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
/* Grab the window manager specific information */
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
- if ( SDL_GetWMInfo(&info) )
+ if ( SDL_GetWindowWMInfo(mWindow, &info) )
{
/* Save the information for later use */
if ( info.subsystem == SDL_SYSWM_X11 )
{
mSDL_Display = info.info.x11.display;
- mSDL_XWindowID = info.info.x11.wmwindow;
+ mSDL_XWindowID = info.info.x11.window;
+ /*
Lock_Display = info.info.x11.lock_func;
Unlock_Display = info.info.x11.unlock_func;
+ */
}
else
{
@@ -718,14 +801,20 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
//make sure multisampling is disabled by default
+#if GL_VERSION_1_3
glDisable(GL_MULTISAMPLE_ARB);
+#endif
// We need to do this here, once video is init'd
+ /*
if (-1 == SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
SDL_DEFAULT_REPEAT_INTERVAL))
LL_WARNS() << "Couldn't enable key-repeat: " << SDL_GetError() <<LL_ENDL;
+ */
// Don't need to get the current gamma, since there's a call that restores it to the system defaults.
+
+
return TRUE;
}
@@ -793,24 +882,47 @@ LLWindowSDL::~LLWindowSDL()
void LLWindowSDL::show()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_ShowWindow(mWindow);
+ }
}
void LLWindowSDL::hide()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_HideWindow(mWindow);
+ }
}
-//virtual
void LLWindowSDL::minimize()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_MinimizeWindow(mWindow);
+ }
+}
+
+BOOL LLWindowSDL::maximize()
+{
+ BOOL result = FALSE;
+
+ if (mWindow)
+ {
+ SDL_MaximizeWindow(mWindow);
+ result = TRUE;
+ }
+
+ return result;
}
-//virtual
void LLWindowSDL::restore()
{
- // *FIX: What to do with SDL?
+ if (mWindow)
+ {
+ SDL_RestoreWindow(mWindow);
+ }
}
@@ -840,11 +952,9 @@ BOOL LLWindowSDL::getVisible()
{
BOOL result = FALSE;
- // *FIX: This isn't really right...
- // Then what is?
if (mWindow)
{
- result = TRUE;
+ if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_SHOWN ) result = TRUE;
}
return(result);
@@ -854,10 +964,12 @@ BOOL LLWindowSDL::getMinimized()
{
BOOL result = FALSE;
- if (mWindow && (1 == mIsMinimized))
+ if (mWindow)
{
- result = TRUE;
+ if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MINIMIZED ) result = TRUE;
}
+
+ mIsMinimized = result;
return(result);
}
@@ -867,18 +979,13 @@ BOOL LLWindowSDL::getMaximized()
if (mWindow)
{
- // TODO
+ if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MAXIMIZED ) result = TRUE;
+ else result = FALSE;
}
return(result);
}
-BOOL LLWindowSDL::maximize()
-{
- // TODO
- return FALSE;
-}
-
BOOL LLWindowSDL::getFullscreen()
{
return mFullscreen;
@@ -896,9 +1003,20 @@ BOOL LLWindowSDL::getSize(LLCoordScreen *size)
{
if (mWindow)
{
- size->mX = mWindow->w;
- size->mY = mWindow->h;
- return (TRUE);
+ /*
+ if(hasHIDPI)
+ {
+ SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY);
+ }
+ else
+ {
+ SDL_GetWindowSize(mWindow, &size->mX, &size->mY);
+ }
+ */
+
+ SDL_GetWindowSize(mWindow, &size->mX, &size->mY);
+
+ return (TRUE);
}
return (FALSE);
@@ -908,9 +1026,16 @@ BOOL LLWindowSDL::getSize(LLCoordWindow *size)
{
if (mWindow)
{
- size->mX = mWindow->w;
- size->mY = mWindow->h;
- return (TRUE);
+ if(hasHIDPI)
+ {
+ SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY);
+ }
+ else
+ {
+ SDL_GetWindowSize(mWindow, &size->mX, &size->mY);
+ }
+
+ return (TRUE);
}
return (FALSE);
@@ -918,13 +1043,15 @@ BOOL LLWindowSDL::getSize(LLCoordWindow *size)
BOOL LLWindowSDL::setPosition(const LLCoordScreen position)
{
+ BOOL result = FALSE;
+
if(mWindow)
{
- // *FIX: (?)
- //MacMoveWindow(mWindow, position.mX, position.mY, false);
+ SDL_SetWindowPosition(mWindow, position.mX, position.mY);
+ result = TRUE;
}
- return TRUE;
+ return result;
}
BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size)
@@ -934,9 +1061,10 @@ BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size)
// Push a resize event onto SDL's queue - we'll handle it
// when it comes out again.
SDL_Event event;
- event.type = SDL_VIDEORESIZE;
- event.resize.w = size.mX;
- event.resize.h = size.mY;
+ event.type = SDL_WINDOWEVENT;
+ event.window.event = SDL_WINDOWEVENT_RESIZED;
+ event.window.data1 = size.mX;
+ event.window.data2 = size.mY;
SDL_PushEvent(&event); // copied into queue
return TRUE;
@@ -952,9 +1080,10 @@ BOOL LLWindowSDL::setSizeImpl(const LLCoordWindow size)
// Push a resize event onto SDL's queue - we'll handle it
// when it comes out again.
SDL_Event event;
- event.type = SDL_VIDEORESIZE;
- event.resize.w = size.mX;
- event.resize.h = size.mY;
+ event.type = SDL_WINDOWEVENT;
+ event.window.event = SDL_WINDOWEVENT_RESIZED;
+ event.window.data1 = size.mX;
+ event.window.data2 = size.mY;
SDL_PushEvent(&event); // copied into queue
return TRUE;
@@ -968,7 +1097,7 @@ void LLWindowSDL::swapBuffers()
{
if (mWindow)
{
- SDL_GL_SwapBuffers();
+ SDL_GL_SwapWindow(mWindow);
}
}
@@ -990,7 +1119,9 @@ F32 LLWindowSDL::getGamma()
BOOL LLWindowSDL::restoreGamma()
{
//CGDisplayRestoreColorSyncSettings();
- SDL_SetGamma(1.0f, 1.0f, 1.0f);
+ Uint16 ramp;
+ SDL_CalculateGammaRamp(1.0f, &ramp);
+ SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp);
return true;
}
@@ -999,7 +1130,9 @@ BOOL LLWindowSDL::setGamma(const F32 gamma)
mGamma = gamma;
if (mGamma == 0) mGamma = 0.1f;
mGamma = 1/mGamma;
- SDL_SetGamma(mGamma, mGamma, mGamma);
+ Uint16 ramp;
+ SDL_CalculateGammaRamp(mGamma, &ramp);
+ SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp);
return true;
}
@@ -1035,6 +1168,36 @@ void LLWindowSDL::setMinSize(U32 min_width, U32 min_height, bool enforce_immedia
#endif
}
+void *LLWindowSDL::createSharedContext()
+{
+ // *FIX: What to do with SDL?
+ return nullptr;
+}
+
+void LLWindowSDL::makeContextCurrent(void* context)
+{
+ // *FIX: What to do with SDL?
+}
+
+void LLWindowSDL::destroySharedContext(void* context)
+{
+ // *FIX: What to do with SDL?
+}
+
+void LLWindowSDL::toggleVSync(bool enable_vsync)
+{
+ if( !enable_vsync)
+ {
+ SDL_GL_SetSwapInterval(0);
+ SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"0",SDL_HINT_OVERRIDE);
+ }
+ else
+ {
+ SDL_GL_SetSwapInterval(1);
+ SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"1",SDL_HINT_OVERRIDE);
+ }
+}
+
BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
{
BOOL result = TRUE;
@@ -1045,12 +1208,13 @@ BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
return FALSE;
}
- //LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL;
-
// do the actual forced cursor move.
- SDL_WarpMouse(screen_pos.mX, screen_pos.mY);
- //LL_INFOS() << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << LL_ENDL;
+ if (mFullscreen)
+ SDL_WarpMouseGlobal(screen_pos.mX, screen_pos.mY);
+ else
+ SDL_WarpMouseInWindow(mWindow, screen_pos.mX, screen_pos.mY);
+
return result;
}
@@ -1070,6 +1234,11 @@ BOOL LLWindowSDL::getCursorPosition(LLCoordWindow *position)
return convertCoords(screen_pos, position);
}
+F32 LLWindowSDL::getSystemUISize()
+{
+ if(hasHIDPI) return 2.0f;
+ else return 1.f;
+}
F32 LLWindowSDL::getNativeAspectRatio()
{
@@ -1125,6 +1294,12 @@ F32 LLWindowSDL::getPixelAspectRatio()
return pixel_aspect;
}
+U32 LLWindowSDL::getAvailableVRAMMegabytes()
+{
+ static const U32 mb = 1024*1024;
+ static const U32 total_factor = 2;
+ return gGLManager.mVRAM - (LLImageGL::getTextureBytesAllocated() * total_factor/mb);
+}
// This is to support 'temporarily windowed' mode so that
// dialogs are still usable in fullscreen.
@@ -1146,7 +1321,7 @@ void LLWindowSDL::beforeDialog()
// it only works in X11
if (running_x11 && mWindow)
{
- SDL_WM_ToggleFullScreen(mWindow);
+ SDL_SetWindowFullscreen(mWindow, SDL_WINDOW_FULLSCREEN);
}
}
}
@@ -1188,7 +1363,7 @@ void LLWindowSDL::afterDialog()
// in X11
if (running_x11 && mWindow)
{
- SDL_WM_ToggleFullScreen(mWindow);
+ SDL_SetWindowFullscreen(mWindow, SDL_WINDOW_FULLSCREEN);
}
}
}
@@ -1331,17 +1506,24 @@ BOOL LLWindowSDL::copyTextToPrimary(const LLWString &text)
BOOL LLWindowSDL::isClipboardTextAvailable()
{
- return FALSE; // unsupported
+ return SDL_HasClipboardText();
}
BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
{
- return FALSE; // unsupported
+ auto data = SDL_GetClipboardText();
+ if (data)
+ {
+ dst = LLWString(utf8str_to_wstring(data));
+ SDL_free(data);
+ return TRUE;
+ }
+ return FALSE;
}
BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
{
- return FALSE; // unsupported
+ return !SDL_SetClipboardText(wstring_to_utf8str(s).c_str());
}
BOOL LLWindowSDL::isPrimaryTextAvailable()
@@ -1368,6 +1550,7 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso
mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
mNumSupportedResolutions = 0;
+ /*
SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
if ( (modes != NULL) && (modes != ((SDL_Rect **) -1)) )
{
@@ -1382,8 +1565,14 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso
{
modes--;
SDL_Rect *r = *modes;
- int w = r->w;
- int h = r->h;
+ */
+ static int display_in_use = 0; // Only using first display
+ auto display_mode_count = SDL_GetNumDisplayModes(display_in_use);
+ SDL_DisplayMode mode;
+ for (int i = 0; i < display_mode_count; ++i) {
+ SDL_GetDisplayMode(display_in_use, i, &mode);
+ int w = mode.w;
+ int h = mode.h;
if ((w >= 800) && (h >= 600))
{
// make sure we don't add the same resolution multiple times!
@@ -1397,7 +1586,7 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso
}
}
}
- }
+ //}
}
num_resolutions = mNumSupportedResolutions;
@@ -1410,7 +1599,9 @@ BOOL LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to)
return FALSE;
to->mX = from.mX;
- to->mY = mWindow->h - from.mY - 1;
+ int h;
+ SDL_GetWindowSize(mWindow, nullptr, &h);
+ to->mY = h - from.mY - 1;
return TRUE;
}
@@ -1421,7 +1612,9 @@ BOOL LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to)
return FALSE;
to->mX = from.mX;
- to->mY = mWindow->h - from.mY - 1;
+ int h;
+ SDL_GetWindowSize(mWindow, nullptr, &h);
+ to->mY = h - from.mY - 1;
return TRUE;
}
@@ -1482,13 +1675,13 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
else
mReallyCapturedCount = 0;
- SDL_GrabMode wantmode, newmode;
+ SDL_bool wantmode, newmode;
if (mReallyCapturedCount <= 0) // uncapture
{
- wantmode = SDL_GRAB_OFF;
+ wantmode = SDL_FALSE;
} else // capture
{
- wantmode = SDL_GRAB_ON;
+ wantmode = SDL_TRUE;
}
if (mReallyCapturedCount < 0) // yuck, imbalance.
@@ -1512,7 +1705,7 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
*keyboard* input from the window manager, which was
frustrating users. */
int result;
- if (wantmode == SDL_GRAB_ON)
+ if (wantmode == SDL_TRUE)
{
//LL_INFOS() << "X11 POINTER GRABBY" << LL_ENDL;
//newmode = SDL_WM_GrabInput(wantmode);
@@ -1523,13 +1716,13 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
None, None, CurrentTime);
maybe_unlock_display();
if (GrabSuccess == result)
- newmode = SDL_GRAB_ON;
+ newmode = SDL_TRUE;
else
- newmode = SDL_GRAB_OFF;
- } else if (wantmode == SDL_GRAB_OFF)
+ newmode = SDL_FALSE;
+ } else if (wantmode == SDL_FALSE)
{
//LL_INFOS() << "X11 POINTER UNGRABBY" << LL_ENDL;
- newmode = SDL_GRAB_OFF;
+ newmode = SDL_FALSE;
//newmode = SDL_WM_GrabInput(SDL_GRAB_OFF);
maybe_lock_display();
@@ -1539,7 +1732,7 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
maybe_unlock_display();
} else
{
- newmode = SDL_GRAB_QUERY; // neutral
+ //newmode = SDL_GRAB_QUERY; // neutral
}
} else // not actually running on X11, for some reason
newmode = wantmode;
@@ -1550,11 +1743,11 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
}
// return boolean success for whether we ended up in the desired state
- return (capture && SDL_GRAB_ON==newmode) ||
- (!capture && SDL_GRAB_OFF==newmode);
+ return (capture && SDL_TRUE==newmode) ||
+ (!capture && SDL_FALSE==newmode);
}
-U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain)
+U32 LLWindowSDL::SDLCheckGrabbyKeys(SDL_Keycode keysym, BOOL gain)
{
/* part of the fix for SL-13243: Some popular window managers like
to totally eat alt-drag for the purposes of moving windows. We
@@ -1743,51 +1936,67 @@ void LLWindowSDL::gatherInput()
{
switch (event.type)
{
- case SDL_MOUSEMOTION:
- {
- LLCoordWindow winCoord(event.button.x, event.button.y);
- LLCoordGL openGlCoord;
- convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(TRUE);
- mCallbacks->handleMouseMove(this, openGlCoord, mask);
- break;
- }
-
case SDL_KEYDOWN:
- mKeyScanCode = event.key.keysym.scancode;
- mKeyVirtualKey = event.key.keysym.unicode;
- mKeyModifiers = event.key.keysym.mod;
+ mKeyScanCode = event.key.keysym.scancode;
+ mKeyModifiers = event.key.keysym.mod;
- gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
- // part of the fix for SL-13243
- if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
- SDLReallyCaptureInput(TRUE);
+ gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
+ // part of the fix for SL-13243
+ if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
+ SDLReallyCaptureInput(TRUE);
- if (event.key.keysym.unicode)
- {
- handleUnicodeUTF16(event.key.keysym.unicode,
- gKeyboard->currentMask(FALSE));
- }
+ if (event.key.keysym.sym < SDLK_SPACE)
+ {
+ handleUnicodeUTF16(event.key.keysym.sym,
+ gKeyboard->currentMask(FALSE));
+ }
+ break;
+
+ case SDL_TEXTINPUT:
+ mCallbacks->handleUnicodeString(event.text.text, false);
break;
+ case SDL_TEXTEDITING:
+ mCallbacks->handleUnicodeString(event.edit.text, true);
+ break;
+
case SDL_KEYUP:
- mKeyScanCode = event.key.keysym.scancode;
- mKeyVirtualKey = event.key.keysym.unicode;
- mKeyModifiers = event.key.keysym.mod;
+ mKeyScanCode = event.key.keysym.scancode;
+ mKeyModifiers = event.key.keysym.mod;
- if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0)
- SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
+ if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0)
+ SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
- gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
+ gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
break;
+ case SDL_MOUSEMOTION:
+ {
+ LLCoordWindow winCoord(event.button.x, event.button.y);
+ LLCoordGL openGlCoord;
+ convertCoords(winCoord, &openGlCoord);
+
+ openGlCoord.mX = openGlCoord.mX * getSystemUISize();
+ openGlCoord.mY = openGlCoord.mY * getSystemUISize();
+
+ //LL_INFOS() << "SDL_MOUSEMOTION " << event.button.x << " " << event.button.y << " gl " << openGlCoord.mX << " " << openGlCoord.mY << LL_ENDL;
+
+ MASK mask = gKeyboard->currentMask(TRUE);
+ mCallbacks->handleMouseMove(this, openGlCoord, mask);
+ break;
+ }
+
case SDL_MOUSEBUTTONDOWN:
{
bool isDoubleClick = false;
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(TRUE);
+
+ openGlCoord.mX *= getSystemUISize();
+ openGlCoord.mY *= getSystemUISize();
+
+ MASK mask = gKeyboard->currentMask(TRUE);
if (event.button.button == SDL_BUTTON_LEFT) // SDL doesn't manage double clicking...
{
@@ -1799,7 +2008,7 @@ void LLWindowSDL::gatherInput()
if (++leftClick >= 2)
{
leftClick = 0;
- isDoubleClick = true;
+ isDoubleClick = true;
}
}
lastLeftDown = now;
@@ -1827,108 +2036,127 @@ void LLWindowSDL::gatherInput()
else
mCallbacks->handleMouseDown(this, openGlCoord, mask);
}
-
else if (event.button.button == SDL_BUTTON_RIGHT) // right
{
- mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
+ mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
}
-
else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
{
mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
}
- else if (event.button.button == 4) // mousewheel up...thanks to X11 for making SDL consider these "buttons".
- mCallbacks->handleScrollWheel(this, -1);
- else if (event.button.button == 5) // mousewheel down...thanks to X11 for making SDL consider these "buttons".
- mCallbacks->handleScrollWheel(this, 1);
break;
}
+ case SDL_MOUSEWHEEL:
+ if (event.wheel.y > 0) // mousewheel up
+ mCallbacks->handleScrollWheel(this, -1);
+ else if (event.wheel.y < 0) // mousewheel down
+ mCallbacks->handleScrollWheel(this, 1);
+ break;
+
case SDL_MOUSEBUTTONUP:
{
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
- MASK mask = gKeyboard->currentMask(TRUE);
+
+ openGlCoord.mX *= getSystemUISize();
+ openGlCoord.mY *= getSystemUISize();
+
+ MASK mask = gKeyboard->currentMask(TRUE);
if (event.button.button == SDL_BUTTON_LEFT) // left
- mCallbacks->handleMouseUp(this, openGlCoord, mask);
+ mCallbacks->handleMouseUp(this, openGlCoord, mask);
else if (event.button.button == SDL_BUTTON_RIGHT) // right
- mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
+ mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
- mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
+ mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
// don't handle mousewheel here...
break;
}
- case SDL_VIDEOEXPOSE: // VIDEOEXPOSE doesn't specify the damage, but hey, it's OpenGL...repaint the whole thing!
- mCallbacks->handlePaint(this, 0, 0, mWindow->w, mWindow->h);
- break;
-
- case SDL_VIDEORESIZE: // *FIX: handle this?
+ case SDL_WINDOWEVENT:
{
- LL_INFOS() << "Handling a resize event: " << event.resize.w <<
- "x" << event.resize.h << LL_ENDL;
+ if (event.window.event == SDL_WINDOWEVENT_EXPOSED)
+ { // VIDEOEXPOSE doesn't specify the damage, but hey, it's OpenGL...repaint the whole thing!
+ int w, h;
+ //SDL_GetWindowSize(mWindow, &w, &h);
+ SDL_GL_GetDrawableSize(mWindow, &w, &h);
+
+ mCallbacks->handlePaint(this, 0, 0, w, h);
+ }
+ else if (event.window.event == SDL_WINDOWEVENT_RESIZED)
+ {
+ LL_INFOS() << "Handling a resize event: " << event.window.data1 <<
+ "x" << event.window.data2 << LL_ENDL;
- S32 width = llmax(event.resize.w, (S32)mMinWindowWidth);
- S32 height = llmax(event.resize.h, (S32)mMinWindowHeight);
+ S32 width = llmax(event.window.data1, (S32)mMinWindowWidth);
+ S32 height = llmax(event.window.data2, (S32)mMinWindowHeight);
- // *FIX: I'm not sure this is necessary!
- mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags);
- if (!mWindow)
- {
- // *FIX: More informative dialog?
- LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL;
- if(mCallbacks->handleCloseRequest(this))
+ // *FIX: I'm not sure this is necessary!
+ /*
+ mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags);
+ if (!mWindow)
+ {
+ // *FIX: More informative dialog?
+ LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL;
+ if(mCallbacks->handleCloseRequest(this))
+ {
+ // Get the app to initiate cleanup.
+ mCallbacks->handleQuit(this);
+ // The app is responsible for calling destroyWindow when done with GL
+ }
+ break;
+ }
+ */
+
+ mCallbacks->handleResize(this, width * getSystemUISize(), height * getSystemUISize());
+ }
+ else if(event.window.event == SDL_WINDOWEVENT_ENTER)
{
- // Get the app to initiate cleanup.
- mCallbacks->handleQuit(this);
- // The app is responsible for calling destroyWindow when done with GL
+ LL_INFOS() << "SDL_WINDOWEVENT_ENTER" << LL_ENDL;
+ if(!mHaveInputFocus) mCallbacks->handleFocus(this);
+ mHaveInputFocus = TRUE;
}
- break;
- }
-
- mCallbacks->handleResize(this, width, height);
- break;
- }
- case SDL_ACTIVEEVENT:
- if (event.active.state & SDL_APPINPUTFOCUS)
+ else if(event.window.event == SDL_WINDOWEVENT_LEAVE)
{
- // Note that for SDL (particularly on X11), keyboard
- // and mouse focus are independent things. Here we are
- // tracking keyboard focus state changes.
-
- // We have to do our own state massaging because SDL
- // can send us two unfocus events in a row for example,
- // which confuses the focus code [SL-24071].
- if (event.active.gain != mHaveInputFocus)
- {
- mHaveInputFocus = !!event.active.gain;
-
- if (mHaveInputFocus)
- mCallbacks->handleFocus(this);
- else
- mCallbacks->handleFocusLost(this);
- }
+ LL_INFOS() << "SDL_WINDOWEVENT_LEAVE" << LL_ENDL;
+ if(mHaveInputFocus) mCallbacks->handleFocusLost(this);
+ mHaveInputFocus = FALSE;
}
- if (event.active.state & SDL_APPACTIVE)
+ else if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
{
- // Change in iconification/minimization state.
- if ((!event.active.gain) != mIsMinimized)
- {
- mIsMinimized = (!event.active.gain);
+ LL_INFOS() << "SDL_WINDOWEVENT_FOCUS_GAINED" << LL_ENDL;
+ if(!mHaveInputFocus) mCallbacks->handleFocus(this);
+ mHaveInputFocus = TRUE;
+ }
+ else if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
+ {
+ LL_INFOS() << "SDL_WINDOWEVENT_FOCUS_LOST" << LL_ENDL;
+ if(mHaveInputFocus) mCallbacks->handleFocusLost(this);
+ mHaveInputFocus = FALSE;
+ }
+ /*
- mCallbacks->handleActivate(this, !mIsMinimized);
- LL_INFOS() << "SDL deiconification state switched to " << BOOL(event.active.gain) << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "Ignored bogus redundant SDL deiconification state switch to " << BOOL(event.active.gain) << LL_ENDL;
- }
+ Bug : the app remains inactive when maximized ..
+
+ else if(event.window.event == SDL_WINDOWEVENT_MINIMIZED)
+ {
+ LL_INFOS() << "SDL_WINDOWEVENT_MINIMIZED" << LL_ENDL;
+ if(!mIsMinimized) mCallbacks->handleActivate(this,FALSE);
+ mIsMinimized = TRUE;
}
- break;
+ else if(event.window.event == SDL_WINDOWEVENT_MAXIMIZED)
+ {
+ LL_INFOS() << "SDL_WINDOWEVENT_MAXIMIZED" << LL_ENDL;
+ if(mIsMinimized) mCallbacks->handleActivate(this,TRUE);
+ mIsMinimized = FALSE;
+ }
+ */
+ }
+ break;
case SDL_QUIT:
if(mCallbacks->handleCloseRequest(this))
@@ -1938,9 +2166,10 @@ void LLWindowSDL::gatherInput()
// The app is responsible for calling destroyWindow when done with GL
}
break;
- default:
- //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL;
- break;
+
+ default:
+ //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL;
+ break;
}
}
@@ -2467,9 +2696,55 @@ BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
return (FALSE);
}
+
+#if LL_DARWIN
+
+LLSD LLWindowSDL::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() << "native key data is: " << result << LL_ENDL;
+
+ return result;
+}
+
+#else
+
+LLSD LLWindowSDL::getNativeKeyData()
+{
+ LLSD result = LLSD::emptyMap();
+
+ U32 modifiers = 0;
+ modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0;
+ modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;
+ modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0;
+ modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0;
+ modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0;
+ modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0;
+ modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0;
+
+ result["scan_code"] = (S32)mKeyScanCode;
+ result["virtual_key"] = (S32)mKeyVirtualKey;
+ result["modifiers"] = (S32)modifiers;
+
+ return result;
+}
+
+#endif // LL_DARWIN
+
#endif // LL_GTK
-#if LL_LINUX
+#if LL_LINUX || __FreeBSD__
// extracted from spawnWebBrowser for clarity and to eliminate
// compiler confusion regarding close(int fd) vs. LLWindow::close()
void exec_cmd(const std::string& cmd, const std::string& arg)
@@ -2525,7 +2800,7 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL;
-#if LL_LINUX
+#if LL_LINUX || __FreeBSD__
# if LL_X11
if (mSDL_Display)
{
@@ -2537,13 +2812,53 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
# endif // LL_X11
std::string cmd, arg;
+#ifdef LL_USESYSTEMLIBS
+ cmd = gDirUtilp->getExecutableDir();
+#else
cmd = gDirUtilp->getAppRODataDir();
cmd += gDirUtilp->getDirDelimiter();
cmd += "etc";
+#endif
cmd += gDirUtilp->getDirDelimiter();
cmd += "launch_url.sh";
arg = escaped_url;
exec_cmd(cmd, arg);
+
+#elif LL_DARWIN
+
+ S32 result = 0;
+ CFURLRef urlRef = NULL;
+
+ LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL;
+
+ 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);
+
+ // Don't use CRURLCreateWithFileSystemPath -- only want valid URLs
+
+ CFRelease(stringRef);
+ }
+
+ if (urlRef)
+ {
+ result = LSOpenCFURLRef(urlRef, NULL);
+
+ if (result != noErr)
+ {
+ LL_INFOS() << "Error " << result << " on open." << LL_ENDL;
+ }
+
+ CFRelease(urlRef);
+ }
+ else
+ {
+ LL_INFOS() << "Error: couldn't create URL." << LL_ENDL;
+ }
+
#endif // LL_LINUX
LL_INFOS() << "spawn_web_browser returning." << LL_ENDL;