diff options
Diffstat (limited to 'indra/llwindow/llwindowsdl.cpp')
-rw-r--r-- | indra/llwindow/llwindowsdl.cpp | 757 |
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; |