00001
00032 #if LL_SDL
00033
00034 #include "linden_common.h"
00035
00036 #include "llwindowsdl.h"
00037 #include "llkeyboardsdl.h"
00038 #include "llerror.h"
00039 #include "llgl.h"
00040 #include "llstring.h"
00041 #include "lldir.h"
00042
00043 #include "llglheaders.h"
00044
00045 #include "indra_constants.h"
00046
00047 #if LL_GTK
00048 extern "C" {
00049 # include "gtk/gtk.h"
00050 }
00051 #endif // LL_GTK
00052
00053 #if LL_LINUX || LL_SOLARIS
00054
00055
00056 # include <unistd.h>
00057 # include <sys/types.h>
00058 # include <sys/wait.h>
00059 #endif // LL_LINUX || LL_SOLARIS
00060
00061 extern BOOL gDebugWindowProc;
00062
00063 const S32 MAX_NUM_RESOLUTIONS = 32;
00064
00065
00066
00067
00068
00069 #if LL_X11
00070 # include <X11/Xutil.h>
00071 #endif //LL_X11
00072
00073
00074
00075
00076
00077 static LLWindowSDL *gWindowImplementation = NULL;
00078
00079 static BOOL was_fullscreen = FALSE;
00080
00081
00082 void maybe_lock_display(void)
00083 {
00084 if (gWindowImplementation) {
00085 gWindowImplementation->Lock_Display();
00086 }
00087 }
00088
00089
00090 void maybe_unlock_display(void)
00091 {
00092 if (gWindowImplementation) {
00093 gWindowImplementation->Unlock_Display();
00094 }
00095 }
00096
00097
00098 #if LL_GTK
00099
00100 BOOL ll_try_gtk_init(void)
00101 {
00102 static BOOL done_gtk_diag = FALSE;
00103 static BOOL gtk_is_good = FALSE;
00104 static BOOL done_setlocale = FALSE;
00105 static BOOL tried_gtk_init = FALSE;
00106
00107 if (!done_setlocale)
00108 {
00109 llinfos << "Starting GTK Initialization." << llendl;
00110 maybe_lock_display();
00111 gtk_disable_setlocale();
00112 maybe_unlock_display();
00113 done_setlocale = TRUE;
00114 }
00115
00116 if (!tried_gtk_init)
00117 {
00118 tried_gtk_init = TRUE;
00119 if (!g_thread_supported ()) g_thread_init (NULL);
00120 maybe_lock_display();
00121 gtk_is_good = gtk_init_check(NULL, NULL);
00122 maybe_unlock_display();
00123 if (!gtk_is_good)
00124 llwarns << "GTK Initialization failed." << llendl;
00125 }
00126
00127 if (gtk_is_good && !done_gtk_diag)
00128 {
00129 llinfos << "GTK Initialized." << llendl;
00130 llinfos << "- Compiled against GTK version "
00131 << GTK_MAJOR_VERSION << "."
00132 << GTK_MINOR_VERSION << "."
00133 << GTK_MICRO_VERSION << llendl;
00134 llinfos << "- Running against GTK version "
00135 << gtk_major_version << "."
00136 << gtk_minor_version << "."
00137 << gtk_micro_version << llendl;
00138 gchar *gtk_warning;
00139 maybe_lock_display();
00140 gtk_warning = gtk_check_version(GTK_MAJOR_VERSION,
00141 GTK_MINOR_VERSION,
00142 GTK_MICRO_VERSION);
00143 maybe_unlock_display();
00144 if (gtk_warning)
00145 {
00146 llwarns << "- GTK COMPATIBILITY WARNING: " <<
00147 gtk_warning << llendl;
00148 gtk_is_good = FALSE;
00149 }
00150
00151 done_gtk_diag = TRUE;
00152 }
00153
00154 return gtk_is_good;
00155 }
00156 #endif // LL_GTK
00157
00158
00159 #if LL_X11
00160 Window get_SDL_XWindowID(void)
00161 {
00162 if (gWindowImplementation) {
00163 return gWindowImplementation->mSDL_XWindowID;
00164 }
00165 return None;
00166 }
00167
00168 Display* get_SDL_Display(void)
00169 {
00170 if (gWindowImplementation) {
00171 return gWindowImplementation->mSDL_Display;
00172 }
00173 return NULL;
00174 }
00175 #endif // LL_X11
00176
00177
00178 BOOL check_for_card(const char* RENDERER, const char* bad_card)
00179 {
00180 if (!strncasecmp(RENDERER, bad_card, strlen(bad_card)))
00181 {
00182 char buffer[1024];
00183 snprintf(buffer, sizeof(buffer),
00184 "Your video card appears to be a %s, which Second Life does not support.\n"
00185 "\n"
00186 "Second Life requires a video card with 32 Mb of memory or more, as well as\n"
00187 "multitexture support. We explicitly support nVidia GeForce 2 or better, \n"
00188 "and ATI Radeon 8500 or better.\n"
00189 "\n"
00190 "If you own a supported card and continue to receive this message, try \n"
00191 "updating to the latest video card drivers. Otherwise look in the\n"
00192 "secondlife.com support section or e-mail technical support\n"
00193 "\n"
00194 "You can try to run Second Life, but it will probably crash or run\n"
00195 "very slowly. Try anyway?",
00196 bad_card);
00197 S32 button = OSMessageBox(buffer, "Unsupported video card", OSMB_YESNO);
00198 if (OSBTN_YES == button)
00199 {
00200 return FALSE;
00201 }
00202 else
00203 {
00204 return TRUE;
00205 }
00206 }
00207
00208 return FALSE;
00209 }
00210
00211
00212
00213
00214 LLWindowSDL::LLWindowSDL(char *title, S32 x, S32 y, S32 width,
00215 S32 height, U32 flags,
00216 BOOL fullscreen, BOOL clearBg,
00217 BOOL disable_vsync, BOOL use_gl,
00218 BOOL ignore_pixel_depth,
00219 S32 stereo_mode)
00220 : LLWindow(fullscreen, flags), mGamma(1.0f)
00221 {
00222
00223 gKeyboard = new LLKeyboardSDL();
00224
00225
00226
00227 mWindow = NULL;
00228 mCursorDecoupled = FALSE;
00229 mCursorLastEventDeltaX = 0;
00230 mCursorLastEventDeltaY = 0;
00231 mCursorIgnoreNextDelta = FALSE;
00232 mNeedsResize = FALSE;
00233 mOverrideAspectRatio = 0.f;
00234 mGrabbyKeyFlags = 0;
00235 mReallyCapturedCount = 0;
00236 mHaveInputFocus = -1;
00237 mIsMinimized = -1;
00238
00239 #if LL_X11
00240 mSDL_XWindowID = None;
00241 mSDL_Display = NULL;
00242 #endif // LL_X11
00243
00244 #if LL_GTK
00245
00246
00247
00248
00249 ll_try_gtk_init();
00250 #endif // LL_GTK
00251
00252
00253 mOriginalAspectRatio = 1024.0 / 768.0;
00254
00255 if (!title)
00256 title = "SDL Window";
00257
00258
00259 mWindowTitle = new char[strlen(title) + 1];
00260 if(mWindowTitle == NULL)
00261 {
00262 llerrs << "Memory allocation failure" << llendl;
00263 return;
00264 }
00265
00266 strcpy(mWindowTitle, title);
00267
00268 if(createContext(x, y, width, height, 32, fullscreen, disable_vsync))
00269 {
00270 gGLManager.initGL();
00271
00272
00273 initCursors();
00274 setCursor( UI_CURSOR_ARROW );
00275 }
00276
00277 stop_glerror();
00278
00279
00280 gWindowImplementation = this;
00281
00282 #if LL_X11
00283 mFlashing = FALSE;
00284 #endif // LL_X11
00285 }
00286
00287 static SDL_Surface *Load_BMP_Resource(const char *basename)
00288 {
00289 const int PATH_BUFFER_SIZE=1000;
00290 char path_buffer[PATH_BUFFER_SIZE];
00291
00292
00293 snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s",
00294 gDirUtilp->getAppRODataDir().c_str(),
00295 gDirUtilp->getDirDelimiter().c_str(),
00296 gDirUtilp->getDirDelimiter().c_str(),
00297 basename);
00298 path_buffer[PATH_BUFFER_SIZE-1] = '\0';
00299
00300 return SDL_LoadBMP(path_buffer);
00301 }
00302
00303 #if LL_X11
00304
00305
00306
00307
00308 static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str)
00309 {
00310 const int line_buf_size = 1000;
00311 char line_buf[line_buf_size];
00312 while (fgets(line_buf, line_buf_size, fp))
00313 {
00314
00315
00316
00317
00318
00319
00320 const char *part1_template = prefix_str;
00321 const char part2_template[] = " kB";
00322 char *part1 = strstr(line_buf, part1_template);
00323 if (part1)
00324 {
00325 part1 = &part1[strlen(part1_template)];
00326 char *part2 = strstr(part1, part2_template);
00327 if (part2)
00328 {
00329
00330
00331
00332 int rtn = 0;
00333 for (; part1 < part2; ++part1)
00334 {
00335 if (*part1 < '0' || *part1 > '9')
00336 {
00337
00338 rtn = 0;
00339 break;
00340 }
00341 rtn *= 10;
00342 rtn += (*part1) - '0';
00343 }
00344 if (rtn > 0)
00345 {
00346
00347 return rtn;
00348 }
00349 }
00350 }
00351 }
00352 return 0;
00353 }
00354
00355 static int x11_detect_VRAM_kb()
00356 {
00357 #if LL_SOLARIS
00358 #error Can this be done without an explicit architecture test, ie a test FOR xorg? Was followed by: && defined(__sparc)
00359
00360
00361 return(0);
00362 #else
00363
00364 std::string x_log_location("/var/log/");
00365 std::string fname;
00366 int rtn = 0;
00367 int display_num = 0;
00368 FILE *fp;
00369 char *display_env = getenv("DISPLAY");
00370
00371 if (display_env[0] == ':' &&
00372 display_env[1] >= '0' && display_env[1] <= '9')
00373 {
00374 display_num = display_env[1] - '0';
00375 }
00376
00377
00378
00379
00380
00381 fname = x_log_location;
00382 fname += "Xorg.";
00383 fname += ('0' + display_num);
00384 fname += ".log";
00385 fp = fopen(fname.c_str(), "r");
00386 if (fp)
00387 {
00388 llinfos << "Looking in " << fname
00389 << " for VRAM info..." << llendl;
00390 rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
00391 fclose(fp);
00392 if (0 == rtn)
00393 {
00394 fp = fopen(fname.c_str(), "r");
00395 if (fp)
00396 {
00397 rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
00398 fclose(fp);
00399 }
00400 }
00401 }
00402 else
00403 {
00404 llinfos << "Could not open " << fname
00405 << " - skipped." << llendl;
00406
00407 fname = x_log_location;
00408 fname += "XFree86.";
00409 fname += ('0' + display_num);
00410 fname += ".log";
00411 fp = fopen(fname.c_str(), "r");
00412 if (fp)
00413 {
00414 llinfos << "Looking in " << fname
00415 << " for VRAM info..." << llendl;
00416 rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
00417 fclose(fp);
00418 if (0 == rtn)
00419 {
00420 fp = fopen(fname.c_str(), "r");
00421 if (fp)
00422 {
00423 rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
00424 fclose(fp);
00425 }
00426 }
00427 }
00428 else
00429 {
00430 llinfos << "Could not open " << fname
00431 << " - skipped." << llendl;
00432 }
00433 }
00434 return rtn;
00435 #endif // LL_SOLARIS
00436 }
00437 #endif // LL_X11
00438
00439 BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync)
00440 {
00441
00442
00443
00444 llinfos << "createContext, fullscreen=" << fullscreen <<
00445 " size=" << width << "x" << height << llendl;
00446
00447
00448 mGrabbyKeyFlags = 0;
00449 mReallyCapturedCount = 0;
00450
00451 if (SDL_Init(SDL_INIT_VIDEO) < 0)
00452 {
00453 llinfos << "sdl_init() failed! " << SDL_GetError() << llendl;
00454 setupFailure("window creation error", "error", OSMB_OK);
00455 return false;
00456 }
00457
00458 SDL_version c_sdl_version;
00459 SDL_VERSION(&c_sdl_version);
00460 llinfos << "Compiled against SDL "
00461 << int(c_sdl_version.major) << "."
00462 << int(c_sdl_version.minor) << "."
00463 << int(c_sdl_version.patch) << llendl;
00464 const SDL_version *r_sdl_version;
00465 r_sdl_version = SDL_Linked_Version();
00466 llinfos << " Running against SDL "
00467 << int(r_sdl_version->major) << "."
00468 << int(r_sdl_version->minor) << "."
00469 << int(r_sdl_version->patch) << llendl;
00470
00471 const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo( );
00472 if (!videoInfo)
00473 {
00474 llinfos << "SDL_GetVideoInfo() failed! " << SDL_GetError() << llendl;
00475 setupFailure("Window creation error", "Error", OSMB_OK);
00476 return FALSE;
00477 }
00478
00479 SDL_EnableUNICODE(1);
00480 SDL_WM_SetCaption(mWindowTitle, mWindowTitle);
00481
00482
00483 SDL_Surface *bmpsurface;
00484 bmpsurface = Load_BMP_Resource("ll_icon.BMP");
00485 if (bmpsurface)
00486 {
00487
00488 SDL_SetColorKey(bmpsurface,
00489 SDL_SRCCOLORKEY,
00490 SDL_MapRGB(bmpsurface->format, 0,0,0) );
00491 SDL_WM_SetIcon(bmpsurface, NULL);
00492
00493
00494 SDL_FreeSurface(bmpsurface);
00495 bmpsurface = NULL;
00496 }
00497
00498
00499
00500
00501
00502 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
00503 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
00504 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
00505 #if !LL_SOLARIS
00506 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (bits <= 16) ? 16 : 24);
00507 #else
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
00522 #endif
00523 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, (bits <= 16) ? 1 : 8);
00524
00525
00526
00527 mFullscreen = fullscreen;
00528 was_fullscreen = fullscreen;
00529
00530 int sdlflags = SDL_OPENGL | SDL_RESIZABLE | SDL_ANYFORMAT;
00531
00532 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
00533
00534 mSDLFlags = sdlflags;
00535
00536 if (mFullscreen)
00537 {
00538 llinfos << "createContext: setting up fullscreen " << width << "x" << height << llendl;
00539
00540
00541 if((width == 0) || (height == 0))
00542 {
00543
00544
00545
00546 S32 resolutionCount = 0;
00547 LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount);
00548
00549 if(resolutionList != NULL)
00550 {
00551 F32 closestAspect = 0;
00552 U32 closestHeight = 0;
00553 U32 closestWidth = 0;
00554 int i;
00555
00556 llinfos << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << llendl;
00557
00558 for(i=0; i < resolutionCount; i++)
00559 {
00560 F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight;
00561
00562 llinfos << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << llendl;
00563
00564 if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) &&
00565 (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio)))
00566 {
00567 llinfos << " (new closest mode) " << llendl;
00568
00569
00570 closestWidth = resolutionList[i].mWidth;
00571 closestHeight = resolutionList[i].mHeight;
00572 closestAspect = aspect;
00573 }
00574 }
00575
00576 width = closestWidth;
00577 height = closestHeight;
00578 }
00579 }
00580
00581 if((width == 0) || (height == 0))
00582 {
00583
00584 width = 1024;
00585 height = 768;
00586 }
00587
00588 mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN);
00589
00590 if (mWindow)
00591 {
00592 mFullscreen = TRUE;
00593 was_fullscreen = TRUE;
00594 mFullscreenWidth = mWindow->w;
00595 mFullscreenHeight = mWindow->h;
00596 mFullscreenBits = mWindow->format->BitsPerPixel;
00597 mFullscreenRefresh = -1;
00598
00599 llinfos << "Running at " << mFullscreenWidth
00600 << "x" << mFullscreenHeight
00601 << "x" << mFullscreenBits
00602 << " @ " << mFullscreenRefresh
00603 << llendl;
00604 }
00605 else
00606 {
00607 llwarns << "createContext: fullscreen creation failure. SDL: " << SDL_GetError() << llendl;
00608
00609 mFullscreen = FALSE;
00610 was_fullscreen = FALSE;
00611 mFullscreenWidth = -1;
00612 mFullscreenHeight = -1;
00613 mFullscreenBits = -1;
00614 mFullscreenRefresh = -1;
00615
00616 char error[256];
00617 snprintf(error, sizeof(error), "Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
00618 OSMessageBox(error, "Error", OSMB_OK);
00619 }
00620 }
00621
00622 if(!mFullscreen && (mWindow == NULL))
00623 {
00624 if (width == 0)
00625 width = 1024;
00626 if (height == 0)
00627 width = 768;
00628
00629 llinfos << "createContext: creating window " << width << "x" << height << "x" << bits << llendl;
00630 mWindow = SDL_SetVideoMode(width, height, bits, sdlflags);
00631
00632 if (!mWindow)
00633 {
00634 llwarns << "createContext: window creation failure. SDL: " << SDL_GetError() << llendl;
00635 setupFailure("Window creation error", "Error", OSMB_OK);
00636 return FALSE;
00637 }
00638 } else if (!mFullscreen && (mWindow != NULL))
00639 {
00640 llinfos << "createContext: SKIPPING - !fullscreen, but +mWindow " << width << "x" << height << "x" << bits << llendl;
00641 }
00642
00643
00644 # if LL_X11
00645 gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024;
00646 if (gGLManager.mVRAM != 0)
00647 {
00648 llinfos << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << llendl;
00649 } else
00650 # endif // LL_X11
00651 {
00652
00653
00654
00655 gGLManager.mVRAM = videoInfo->video_mem / 1024;
00656 if (gGLManager.mVRAM != 0)
00657 {
00658 llinfos << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << llendl;
00659 }
00660 }
00661
00662
00663
00664
00665
00666
00667 GLint depthBits, stencilBits, redBits, greenBits, blueBits, alphaBits;
00668
00669 glGetIntegerv(GL_RED_BITS, &redBits);
00670 glGetIntegerv(GL_GREEN_BITS, &greenBits);
00671 glGetIntegerv(GL_BLUE_BITS, &blueBits);
00672 glGetIntegerv(GL_ALPHA_BITS, &alphaBits);
00673 glGetIntegerv(GL_DEPTH_BITS, &depthBits);
00674 glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
00675
00676 llinfos << "GL buffer:" << llendl
00677 llinfos << " Red Bits " << S32(redBits) << llendl
00678 llinfos << " Green Bits " << S32(greenBits) << llendl
00679 llinfos << " Blue Bits " << S32(blueBits) << llendl
00680 llinfos << " Alpha Bits " << S32(alphaBits) << llendl
00681 llinfos << " Depth Bits " << S32(depthBits) << llendl
00682 llinfos << " Stencil Bits " << S32(stencilBits) << llendl;
00683
00684 GLint colorBits = redBits + greenBits + blueBits + alphaBits;
00685
00686
00687
00688 #if LL_SOLARIS
00689 #error && defined(__sparc)
00690 if(colorBits < 24)
00691 #else
00692 if (colorBits < 32)
00693 #endif
00694 {
00695 close();
00696 setupFailure(
00697 #if LL_SOLARIS
00698 #error && defined(__sparc)
00699 "Second Life requires at least 24-bit color on SPARC to run in a window.\n"
00700 "Please use fbconfig to set your default color depth to 24 bits.\n"
00701 "You may also need to adjust the X11 setting in SMF. To do so use\n"
00702 " 'svccfg -s svc:/application/x11/x11-server setprop options/default_depth=24'\n"
00703 #else
00704 "Second Life requires True Color (32-bit) to run in a window.\n"
00705 "Please go to Control Panels -> Display -> Settings and\n"
00706 "set the screen to 32-bit color.\n"
00707 #endif
00708 "Alternately, if you choose to run fullscreen, Second Life\n"
00709 "will automatically adjust the screen each time it runs.",
00710 "Error",
00711 OSMB_OK);
00712 return FALSE;
00713 }
00714
00715 #if 0 // *FIX: we're going to brave it for now...
00716 if (alphaBits < 8)
00717 {
00718 close();
00719 setupFailure(
00720 "Second Life is unable to run because it can't get an 8 bit alpha\n"
00721 "channel. Usually this is due to video card driver issues.\n"
00722 "Please make sure you have the latest video card drivers installed.\n"
00723 "Also be sure your monitor is set to True Color (32-bit) in\n"
00724 "Control Panels -> Display -> Settings.\n"
00725 "If you continue to receive this message, contact customer service.",
00726 "Error",
00727 OSMB_OK);
00728 return FALSE;
00729 }
00730 #endif
00731
00732 #if LL_X11
00733 init_x11clipboard();
00734 #endif // LL_X11
00735
00736
00737 if (-1 == SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
00738 SDL_DEFAULT_REPEAT_INTERVAL))
00739 llwarns << "Couldn't enable key-repeat: " << SDL_GetError() <<llendl;
00740
00741
00742 return TRUE;
00743 }
00744
00745
00746
00747 BOOL LLWindowSDL::switchContext(BOOL fullscreen, LLCoordScreen size, BOOL disable_vsync)
00748 {
00749 const BOOL needsRebuild = TRUE;
00750 BOOL result = true;
00751
00752 llinfos << "switchContext, fullscreen=" << fullscreen << llendl;
00753 stop_glerror();
00754 if(needsRebuild)
00755 {
00756 destroyContext();
00757 result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync);
00758 if (result)
00759 {
00760 gGLManager.initGL();
00761
00762
00763 initCursors();
00764 setCursor( UI_CURSOR_ARROW );
00765 }
00766 }
00767
00768 stop_glerror();
00769
00770 return result;
00771 }
00772
00773 void LLWindowSDL::destroyContext()
00774 {
00775 llinfos << "destroyContext begins" << llendl;
00776 #if LL_X11
00777 quit_x11clipboard();
00778 #endif // LL_X11
00779
00780
00781 llinfos << "shutdownGL begins" << llendl;
00782 gGLManager.shutdownGL();
00783 llinfos << "SDL_QuitSS/VID begins" << llendl;
00784 SDL_QuitSubSystem(SDL_INIT_VIDEO);
00785
00786
00787 mWindow = NULL;
00788 }
00789
00790 LLWindowSDL::~LLWindowSDL()
00791 {
00792 quitCursors();
00793 destroyContext();
00794
00795 if(mSupportedResolutions != NULL)
00796 {
00797 delete []mSupportedResolutions;
00798 }
00799
00800 delete[] mWindowTitle;
00801
00802 gWindowImplementation = NULL;
00803 }
00804
00805
00806 void LLWindowSDL::show()
00807 {
00808
00809 }
00810
00811 void LLWindowSDL::hide()
00812 {
00813
00814 }
00815
00816 void LLWindowSDL::minimize()
00817 {
00818
00819 }
00820
00821 void LLWindowSDL::restore()
00822 {
00823
00824 }
00825
00826
00827
00828
00829 void LLWindowSDL::close()
00830 {
00831
00832
00833
00834
00835
00836
00837
00838 setMouseClipping(FALSE);
00839 showCursor();
00840
00841 destroyContext();
00842 }
00843
00844 BOOL LLWindowSDL::isValid()
00845 {
00846 return (mWindow != NULL);
00847 }
00848
00849 BOOL LLWindowSDL::getVisible()
00850 {
00851 BOOL result = FALSE;
00852
00853
00854
00855 if (mWindow)
00856 {
00857 result = TRUE;
00858 }
00859
00860 return(result);
00861 }
00862
00863 BOOL LLWindowSDL::getMinimized()
00864 {
00865 BOOL result = FALSE;
00866
00867 if (mWindow && (1 == mIsMinimized))
00868 {
00869 result = TRUE;
00870 }
00871 return(result);
00872 }
00873
00874 BOOL LLWindowSDL::getMaximized()
00875 {
00876 BOOL result = FALSE;
00877
00878 if (mWindow)
00879 {
00880
00881 }
00882
00883 return(result);
00884 }
00885
00886 BOOL LLWindowSDL::maximize()
00887 {
00888
00889 return FALSE;
00890 }
00891
00892 BOOL LLWindowSDL::getFullscreen()
00893 {
00894 return mFullscreen;
00895 }
00896
00897 BOOL LLWindowSDL::getPosition(LLCoordScreen *position)
00898 {
00899
00900 position->mX = 0;
00901 position->mY = 0;
00902 return TRUE;
00903 }
00904
00905 BOOL LLWindowSDL::getSize(LLCoordScreen *size)
00906 {
00907 if (mWindow)
00908 {
00909 size->mX = mWindow->w;
00910 size->mY = mWindow->h;
00911 return (TRUE);
00912 }
00913
00914 llerrs << "LLWindowSDL::getPosition(): no window and not fullscreen!" << llendl;
00915 return (FALSE);
00916 }
00917
00918 BOOL LLWindowSDL::getSize(LLCoordWindow *size)
00919 {
00920 if (mWindow)
00921 {
00922 size->mX = mWindow->w;
00923 size->mY = mWindow->h;
00924 return (TRUE);
00925 }
00926
00927 llerrs << "LLWindowSDL::getPosition(): no window and not fullscreen!" << llendl;
00928 return (FALSE);
00929 }
00930
00931 BOOL LLWindowSDL::setPosition(const LLCoordScreen position)
00932 {
00933 if(mWindow)
00934 {
00935
00936
00937 }
00938
00939 return TRUE;
00940 }
00941
00942 BOOL LLWindowSDL::setSize(const LLCoordScreen size)
00943 {
00944 if(mWindow)
00945 {
00946
00947
00948 }
00949
00950 return TRUE;
00951 }
00952
00953 void LLWindowSDL::swapBuffers()
00954 {
00955 if (mWindow)
00956 SDL_GL_SwapBuffers();
00957 }
00958
00959 F32 LLWindowSDL::getGamma()
00960 {
00961 return 1/mGamma;
00962 }
00963
00964 BOOL LLWindowSDL::restoreGamma()
00965 {
00966
00967 SDL_SetGamma(1.0f, 1.0f, 1.0f);
00968 return true;
00969 }
00970
00971 BOOL LLWindowSDL::setGamma(const F32 gamma)
00972 {
00973 mGamma = gamma;
00974 if (mGamma == 0) mGamma = 0.1f;
00975 mGamma = 1/mGamma;
00976 SDL_SetGamma(mGamma, mGamma, mGamma);
00977 return true;
00978 }
00979
00980 BOOL LLWindowSDL::isCursorHidden()
00981 {
00982 return mCursorHidden;
00983 }
00984
00985
00986
00987
00988 void LLWindowSDL::setMouseClipping( BOOL b )
00989 {
00990
00991
00992 mIsMouseClipping = b;
00993
00994 adjustCursorDecouple();
00995 }
00996
00997 BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
00998 {
00999 BOOL result = TRUE;
01000 LLCoordScreen screen_pos;
01001
01002 if (!convertCoords(position, &screen_pos))
01003 {
01004 return FALSE;
01005 }
01006
01007
01008
01009 SDL_WarpMouse(screen_pos.mX, screen_pos.mY);
01010
01011
01012 adjustCursorDecouple(true);
01013
01014 return result;
01015 }
01016
01017 BOOL LLWindowSDL::getCursorPosition(LLCoordWindow *position)
01018 {
01019
01020 LLCoordScreen screen_pos;
01021
01022
01023 int x, y;
01024 SDL_GetMouseState(&x, &y);
01025
01026 screen_pos.mX = x;
01027 screen_pos.mY = y;
01028
01029 return convertCoords(screen_pos, position);
01030 }
01031
01032 void LLWindowSDL::adjustCursorDecouple(bool warpingMouse)
01033 {
01034 if(mIsMouseClipping && mCursorHidden)
01035 {
01036 if(warpingMouse)
01037 {
01038
01039 if(!mCursorDecoupled)
01040 {
01041
01042
01043 mCursorDecoupled = true;
01044 mCursorIgnoreNextDelta = TRUE;
01045 }
01046 }
01047 }
01048 else
01049 {
01050
01051 if(mCursorDecoupled)
01052 {
01053
01054
01055 mCursorDecoupled = false;
01056 }
01057 }
01058 }
01059
01060 F32 LLWindowSDL::getNativeAspectRatio()
01061 {
01062 #if 0
01063
01064
01065
01066 S32 num_resolutions;
01067 LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions);
01068
01069
01070 return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight);
01071
01072 #endif
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 if (mOverrideAspectRatio > 0.f)
01092 {
01093 return mOverrideAspectRatio;
01094 }
01095
01096 return mOriginalAspectRatio;
01097 }
01098
01099 F32 LLWindowSDL::getPixelAspectRatio()
01100 {
01101 F32 pixel_aspect = 1.f;
01102 if (getFullscreen())
01103 {
01104 LLCoordScreen screen_size;
01105 getSize(&screen_size);
01106 pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
01107 }
01108
01109 return pixel_aspect;
01110 }
01111
01112
01113
01114
01115
01116 static LLCoordScreen old_size;
01117 static BOOL old_fullscreen;
01118 void LLWindowSDL::beforeDialog()
01119 {
01120 llinfos << "LLWindowSDL::beforeDialog()" << llendl;
01121
01122 if (SDLReallyCaptureInput(FALSE)
01123 && getSize(&old_size))
01124 {
01125 old_fullscreen = was_fullscreen;
01126
01127 if (old_fullscreen)
01128 {
01129
01130
01131 }
01132 }
01133
01134 #if LL_X11
01135 if (mSDL_Display)
01136 {
01137
01138
01139 maybe_lock_display();
01140 XSync(mSDL_Display, False);
01141 maybe_unlock_display();
01142 }
01143 #endif // LL_X11
01144
01145 #if LL_GTK
01146
01147
01148 ll_try_gtk_init();
01149 #endif // LL_GTK
01150
01151 maybe_lock_display();
01152 }
01153
01154 void LLWindowSDL::afterDialog()
01155 {
01156 llinfos << "LLWindowSDL::afterDialog()" << llendl;
01157
01158 maybe_unlock_display();
01159
01160 if (old_fullscreen && !was_fullscreen)
01161 {
01162
01163
01164 }
01165
01166
01167 }
01168
01169
01170 S32 LLWindowSDL::stat(const char* file_name, struct stat* stat_info)
01171 {
01172 return ::stat( file_name, stat_info );
01173 }
01174
01175 #if LL_X11
01176
01177 void LLWindowSDL::x11_set_urgent(BOOL urgent)
01178 {
01179 if (mSDL_Display && !mFullscreen)
01180 {
01181 XWMHints *wm_hints;
01182
01183 llinfos << "X11 hint for urgency, " << urgent << llendl;
01184
01185 maybe_lock_display();
01186 wm_hints = XGetWMHints(mSDL_Display, mSDL_XWindowID);
01187 if (!wm_hints)
01188 wm_hints = XAllocWMHints();
01189
01190 if (urgent)
01191 wm_hints->flags |= XUrgencyHint;
01192 else
01193 wm_hints->flags &= ~XUrgencyHint;
01194
01195 XSetWMHints(mSDL_Display, mSDL_XWindowID, wm_hints);
01196 XFree(wm_hints);
01197 XSync(mSDL_Display, False);
01198 maybe_unlock_display();
01199 }
01200 }
01201 #endif // LL_X11
01202
01203 void LLWindowSDL::flashIcon(F32 seconds)
01204 {
01205 #if !LL_X11
01206 llinfos << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << llendl;
01207 #else
01208 llinfos << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << llendl;
01209
01210 F32 remaining_time = mFlashTimer.getRemainingTimeF32();
01211 if (remaining_time < seconds)
01212 remaining_time = seconds;
01213 mFlashTimer.reset();
01214 mFlashTimer.setTimerExpirySec(remaining_time);
01215
01216 x11_set_urgent(TRUE);
01217 mFlashing = TRUE;
01218 #endif // LL_X11
01219 }
01220
01221 #if LL_X11
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231 typedef Atom x11clipboard_type;
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245 static x11clipboard_type get_x11_readwrite_clipboard_type(void)
01246 {
01247 return XInternAtom(get_SDL_Display(), "CLIPBOARD", False);
01248 }
01249
01250 static x11clipboard_type get_x11_write_clipboard_type(void)
01251 {
01252 return XA_PRIMARY;
01253 }
01254
01255
01256
01257
01258 static x11clipboard_type get_x11_cutbuffer_clipboard_type(void)
01259 {
01260 return XInternAtom(get_SDL_Display(), "SECONDLIFE_CUTBUFFER", False);
01261 }
01262
01263
01264 static Atom get_x11_targets_atom(void)
01265 {
01266 return XInternAtom(get_SDL_Display(), "TARGETS", False);
01267 }
01268
01269 static Atom get_x11_text_atom(void)
01270 {
01271 return XInternAtom(get_SDL_Display(), "TEXT", False);
01272 }
01273
01274
01275
01276
01277
01278 #define SDLCLIPTYPE(A, B, C, D) (int)(((A)<<24)|((B)<<16)|((C)<<8)|((D)<<0))
01279 #define FORMAT_PREFIX "SECONDLIFE_x11clipboard_0x"
01280
01281 static
01282 x11clipboard_type convert_format(int type)
01283 {
01284 if (!gWindowImplementation)
01285 {
01286 llwarns << "!gWindowImplementation in convert_format()"
01287 << llendl;
01288 return XA_STRING;
01289 }
01290
01291 switch (type)
01292 {
01293 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
01294
01295 return XA_STRING;
01296 case SDLCLIPTYPE('U', 'T', 'F', '8'):
01297
01298 return XInternAtom(gWindowImplementation->mSDL_Display,
01299 "UTF8_STRING", False);
01300 default:
01301 {
01302
01303
01304 char format[sizeof(FORMAT_PREFIX)+8+1];
01305
01306 snprintf(format, sizeof(format), "%s%08lx", FORMAT_PREFIX, (unsigned long)type);
01307 return XInternAtom(gWindowImplementation->mSDL_Display,
01308 format, False);
01309 }
01310 }
01311 }
01312
01313
01314
01315 static int
01316 convert_data(int type, char *dst, const char *src, int srclen)
01317 {
01318 int dstlen;
01319
01320 dstlen = 0;
01321 switch (type)
01322 {
01323 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
01324 case SDLCLIPTYPE('U', 'T', 'F', '8'):
01325 if (src == NULL)
01326 {
01327 break;
01328 }
01329 if ( srclen == 0 )
01330 srclen = strlen(src);
01331
01332 dstlen = srclen + 1;
01333
01334 if ( dst )
01335 {
01336 memcpy(dst, src, srclen);
01337 dst[srclen] = '\0';
01338 }
01339 break;
01340
01341 default:
01342 llwarns << "convert_data: Unknown medium type" << llendl;
01343 break;
01344 }
01345 return(dstlen);
01346 }
01347
01348
01349
01350
01351 static int
01352 convert_x11clipboard(int type, char *dst, const char *src, int srclen)
01353 {
01354 int dstlen;
01355
01356 dstlen = 0;
01357 switch (type)
01358 {
01359 case SDLCLIPTYPE('U', 'T', 'F', '8'):
01360 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
01361 if (src == NULL)
01362 {
01363 break;
01364 }
01365 if ( srclen == 0 )
01366 srclen = strlen(src);
01367
01368 dstlen = srclen + 1;
01369
01370 if ( dst )
01371 {
01372 memcpy(dst, src, srclen);
01373 dst[srclen] = '\0';
01374 }
01375 break;
01376
01377 default:
01378 llwarns << "convert_x11clipboard: Unknown medium type" << llendl;
01379 break;
01380 }
01381 return dstlen;
01382 }
01383
01384 int
01385 LLWindowSDL::is_empty_x11clipboard(void)
01386 {
01387 int retval;
01388
01389 maybe_lock_display();
01390 retval = ( XGetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type()) == None );
01391 maybe_unlock_display();
01392
01393 return(retval);
01394 }
01395
01396 void
01397 LLWindowSDL::put_x11clipboard(int type, int srclen, const char *src)
01398 {
01399 x11clipboard_type format;
01400 int dstlen;
01401 char *dst;
01402
01403 format = convert_format(type);
01404 dstlen = convert_data(type, NULL, src, srclen);
01405
01406 dst = (char *)malloc(dstlen);
01407 if ( dst != NULL )
01408 {
01409 maybe_lock_display();
01410 Window root = DefaultRootWindow(mSDL_Display);
01411 convert_data(type, dst, src, srclen);
01412
01413
01414
01415 if (type == SDLCLIPTYPE('T','E','X','T'))
01416 {
01417
01418 llinfos << "X11: Populating cutbuffer." <<llendl;
01419 XChangeProperty(mSDL_Display, root,
01420 XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace,
01421 (unsigned char*)dst, dstlen-1);
01422 } else {
01423
01424
01425
01426 }
01427
01428 XChangeProperty(mSDL_Display, root,
01429 get_x11_cutbuffer_clipboard_type(), format, 8, PropModeReplace,
01430 (unsigned char*)dst, dstlen-1);
01431 free(dst);
01432
01433
01434 XSetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type(),
01435 mSDL_XWindowID, CurrentTime);
01436 XSetSelectionOwner(mSDL_Display, get_x11_write_clipboard_type(),
01437 mSDL_XWindowID, CurrentTime);
01438
01439 maybe_unlock_display();
01440 }
01441 }
01442
01443 void
01444 LLWindowSDL::get_x11clipboard(int type, int *dstlen, char **dst)
01445 {
01446 x11clipboard_type format;
01447
01448 *dstlen = 0;
01449 format = convert_format(type);
01450
01451 Window owner;
01452 Atom selection;
01453 Atom seln_type;
01454 int seln_format;
01455 unsigned long nbytes;
01456 unsigned long overflow;
01457 char *src;
01458
01459 maybe_lock_display();
01460 owner = XGetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type());
01461 maybe_unlock_display();
01462 if (owner == None)
01463 {
01464
01465 owner = DefaultRootWindow(mSDL_Display);
01466 selection = XA_CUT_BUFFER0;
01467 } else if (owner == mSDL_XWindowID)
01468 {
01469
01470 owner = DefaultRootWindow(mSDL_Display);
01471 selection = get_x11_cutbuffer_clipboard_type();
01472 }
01473 else
01474 {
01475
01476 int selection_response = 0;
01477 SDL_Event event;
01478
01479 owner = mSDL_XWindowID;
01480 maybe_lock_display();
01481 selection = XInternAtom(mSDL_Display, "SDL_SELECTION", False);
01482 XConvertSelection(mSDL_Display, get_x11_readwrite_clipboard_type(), format,
01483 selection, owner, CurrentTime);
01484 maybe_unlock_display();
01485 llinfos << "X11: Waiting for clipboard to arrive." <<llendl;
01486 while ( ! selection_response )
01487 {
01488
01489
01490 SDL_PumpEvents();
01491 if (1 == SDL_PeepEvents(&event, 1, SDL_GETEVENT,
01492 SDL_SYSWMEVENTMASK) )
01493 {
01494 if ( event.type == SDL_SYSWMEVENT )
01495 {
01496 XEvent xevent =
01497 event.syswm.msg->event.xevent;
01498
01499 if ( (xevent.type == SelectionNotify)&&
01500 (xevent.xselection.requestor == owner) )
01501 selection_response = 1;
01502 }
01503 } else {
01504 llinfos << "X11: Waiting for SYSWM event..." << llendl;
01505 }
01506 }
01507 llinfos << "X11: Clipboard arrived." <<llendl;
01508 }
01509
01510 maybe_lock_display();
01511 if ( XGetWindowProperty(mSDL_Display, owner, selection, 0, INT_MAX/4,
01512 False, format, &seln_type, &seln_format,
01513 &nbytes, &overflow, (unsigned char **)&src) == Success )
01514 {
01515 if ( seln_type == format )
01516 {
01517 *dstlen = convert_x11clipboard(type, NULL, src, nbytes);
01518 *dst = (char *)realloc(*dst, *dstlen);
01519 if ( *dst == NULL )
01520 *dstlen = 0;
01521 else
01522 convert_x11clipboard(type, *dst, src, nbytes);
01523 }
01524 XFree(src);
01525 }
01526 maybe_unlock_display();
01527 }
01528
01529 int clipboard_filter_callback(const SDL_Event *event)
01530 {
01531
01532 if ( event->type != SDL_SYSWMEVENT )
01533 {
01534 return(1);
01535 }
01536
01537
01538 switch (event->syswm.msg->event.xevent.type) {
01539
01540 case SelectionRequest: {
01541 XSelectionRequestEvent *req;
01542 XEvent sevent;
01543 int seln_format;
01544 unsigned long nbytes;
01545 unsigned long overflow;
01546 unsigned char *seln_data;
01547
01548 req = &event->syswm.msg->event.xevent.xselectionrequest;
01549 sevent.xselection.type = SelectionNotify;
01550 sevent.xselection.display = req->display;
01551 sevent.xselection.selection = req->selection;
01552 sevent.xselection.target = None;
01553 sevent.xselection.property = None;
01554 sevent.xselection.requestor = req->requestor;
01555 sevent.xselection.time = req->time;
01556 if ( XGetWindowProperty(get_SDL_Display(), DefaultRootWindow(get_SDL_Display()),
01557 get_x11_cutbuffer_clipboard_type(), 0, INT_MAX/4, False, req->target,
01558 &sevent.xselection.target, &seln_format,
01559 &nbytes, &overflow, &seln_data) == Success )
01560 {
01561 if ( sevent.xselection.target == req->target)
01562 {
01563 if ( sevent.xselection.target == XA_STRING ||
01564 sevent.xselection.target ==
01565 convert_format(SDLCLIPTYPE('U','T','F','8')) )
01566 {
01567 if ( seln_data[nbytes-1] == '\0' )
01568 --nbytes;
01569 }
01570 XChangeProperty(get_SDL_Display(), req->requestor, req->property,
01571 req->target, seln_format, PropModeReplace,
01572 seln_data, nbytes);
01573 sevent.xselection.property = req->property;
01574 } else if (get_x11_targets_atom() == req->target) {
01575
01576 const int num_supported = 3;
01577 Atom supported[num_supported] = {
01578 XA_STRING,
01579 get_x11_text_atom(),
01580 get_x11_targets_atom()
01581 };
01582 supported[0] = sevent.xselection.target;
01583 XChangeProperty(get_SDL_Display(), req->requestor,
01584 req->property, XA_ATOM, 32, PropModeReplace,
01585 (unsigned char*)supported,
01586 num_supported);
01587 sevent.xselection.property = req->property;
01588 llinfos << "Clipboard: An app asked us what selections format we offer." << llendl;
01589 } else {
01590 llinfos << "Clipboard: An app requested an unsupported selection format " << req->target << ", we have " << sevent.xselection.target << llendl;
01591 sevent.xselection.target = None;
01592 }
01593 XFree(seln_data);
01594 }
01595 int sendret =
01596 XSendEvent(get_SDL_Display(),req->requestor,False,0,&sevent);
01597 if ((sendret==BadValue) || (sendret==BadWindow))
01598 llwarns << "Clipboard SendEvent failed" << llendl;
01599 XSync(get_SDL_Display(), False);
01600 }
01601 break;
01602 }
01603
01604
01605 return(1);
01606 }
01607
01608 int
01609 LLWindowSDL::init_x11clipboard(void)
01610 {
01611 SDL_SysWMinfo info;
01612 int retval;
01613
01614
01615 retval = -1;
01616 SDL_SetError("SDL is not running on known window manager");
01617
01618 SDL_VERSION(&info.version);
01619 if ( SDL_GetWMInfo(&info) )
01620 {
01621
01622 if ( info.subsystem == SDL_SYSWM_X11 )
01623 {
01624 mSDL_Display = info.info.x11.display;
01625 mSDL_XWindowID = info.info.x11.wmwindow;
01626 Lock_Display = info.info.x11.lock_func;
01627 Unlock_Display = info.info.x11.unlock_func;
01628
01629
01630 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
01631 SDL_SetEventFilter(clipboard_filter_callback);
01632
01633 retval = 0;
01634 }
01635 else
01636 {
01637 SDL_SetError("SDL is not running on X11");
01638 }
01639 }
01640 return(retval);
01641 }
01642
01643 void
01644 LLWindowSDL::quit_x11clipboard(void)
01645 {
01646 mSDL_Display = NULL;
01647 mSDL_XWindowID = None;
01648 Lock_Display = NULL;
01649 Unlock_Display = NULL;
01650
01651 SDL_SetEventFilter(NULL);
01652 }
01653
01654
01655
01656 BOOL LLWindowSDL::isClipboardTextAvailable()
01657 {
01658 return !is_empty_x11clipboard();
01659 }
01660
01661 BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
01662 {
01663 int cliplen;
01664 char *cliptext = NULL;
01665 get_x11clipboard(SDLCLIPTYPE('U','T','F','8'), &cliplen, &cliptext);
01666 if (cliptext)
01667 {
01668 llinfos << "X11: Got UTF8 clipboard text." << llendl;
01669
01670
01671 std::string clip_str(cliptext);
01672
01673
01674
01675 dst = utf8str_to_wstring(clip_str);
01676
01677
01678
01679
01680
01681 free(cliptext);
01682 return TRUE;
01683 }
01684 get_x11clipboard(SDLCLIPTYPE('T','E','X','T'), &cliplen, &cliptext);
01685 if (cliptext)
01686 {
01687 llinfos << "X11: Got ISO 8859-1 clipboard text." << llendl;
01688 std::string clip_str(cliptext);
01689 std::string utf8_str = rawstr_to_utf8(clip_str);
01690 dst = utf8str_to_wstring(utf8_str);
01691 free(cliptext);
01692 }
01693 return FALSE;
01694 }
01695
01696 BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
01697 {
01698 std::string utf8text = wstring_to_utf8str(s);
01699 const char* cstr = utf8text.c_str();
01700 if (cstr == NULL)
01701 {
01702 return FALSE;
01703 }
01704 int cstrlen = strlen(cstr);
01705 int i;
01706 for (i=0; i<cstrlen; ++i)
01707 {
01708 if (0x80 & (unsigned char)cstr[i])
01709 {
01710
01711 llinfos << "X11: UTF8 copyTextToClipboard" << llendl;
01712 put_x11clipboard(SDLCLIPTYPE('U','T','F','8'), cstrlen, cstr);
01713 return TRUE;
01714 }
01715 }
01716
01717 llinfos << "X11: ISO 8859-1 copyTextToClipboard" << llendl;
01718 put_x11clipboard(SDLCLIPTYPE('T','E','X','T'), cstrlen, cstr);
01719 return TRUE;
01720 }
01721 #else
01722
01723 BOOL LLWindowSDL::isClipboardTextAvailable()
01724 {
01725 return FALSE;
01726 }
01727
01728 BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
01729 {
01730 return FALSE;
01731 }
01732
01733 BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
01734 {
01735 return FALSE;
01736 }
01737 #endif // LL_X11
01738
01739 BOOL LLWindowSDL::sendEmail(const char* address, const char* subject, const char* body_text,
01740 const char* attachment, const char* attachment_displayed_name )
01741 {
01742
01743
01744 return FALSE;
01745 }
01746
01747
01748 LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions)
01749 {
01750 if (!mSupportedResolutions)
01751 {
01752 mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
01753 mNumSupportedResolutions = 0;
01754
01755 SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
01756 if ( (modes != NULL) && (modes != ((SDL_Rect **) -1)) )
01757 {
01758 int count = 0;
01759 while (*modes)
01760 {
01761 modes++;
01762 count++;
01763 }
01764
01765 while (count--)
01766 {
01767 modes--;
01768 SDL_Rect *r = *modes;
01769 int w = r->w;
01770 int h = r->h;
01771 if ((w >= 800) && (h >= 600))
01772 {
01773
01774 if ( (mNumSupportedResolutions == 0) ||
01775 ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) &&
01776 (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) )
01777 {
01778 mSupportedResolutions[mNumSupportedResolutions].mWidth = w;
01779 mSupportedResolutions[mNumSupportedResolutions].mHeight = h;
01780 mNumSupportedResolutions++;
01781 }
01782 }
01783 }
01784 }
01785 }
01786
01787 num_resolutions = mNumSupportedResolutions;
01788 return mSupportedResolutions;
01789 }
01790
01791 BOOL LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to)
01792 {
01793 if (!to)
01794 return FALSE;
01795
01796 to->mX = from.mX;
01797 to->mY = mWindow->h - from.mY - 1;
01798
01799 return TRUE;
01800 }
01801
01802 BOOL LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to)
01803 {
01804 if (!to)
01805 return FALSE;
01806
01807 to->mX = from.mX;
01808 to->mY = mWindow->h - from.mY - 1;
01809
01810 return TRUE;
01811 }
01812
01813 BOOL LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordWindow* to)
01814 {
01815 if (!to)
01816 return FALSE;
01817
01818
01819 to->mX = from.mX;
01820 to->mY = from.mY;
01821 return (TRUE);
01822 }
01823
01824 BOOL LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordScreen *to)
01825 {
01826 if (!to)
01827 return FALSE;
01828
01829
01830 to->mX = from.mX;
01831 to->mY = from.mY;
01832 return (TRUE);
01833 }
01834
01835 BOOL LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordGL *to)
01836 {
01837 LLCoordWindow window_coord;
01838
01839 return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
01840 }
01841
01842 BOOL LLWindowSDL::convertCoords(LLCoordGL from, LLCoordScreen *to)
01843 {
01844 LLCoordWindow window_coord;
01845
01846 return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
01847 }
01848
01849
01850
01851
01852 void LLWindowSDL::setupFailure(const char* text, const char* caption, U32 type)
01853 {
01854 destroyContext();
01855
01856 OSMessageBox(text, caption, type);
01857 }
01858
01859 BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
01860 {
01861
01862
01863
01864 if (capture)
01865 mReallyCapturedCount = 1;
01866 else
01867 mReallyCapturedCount = 0;
01868
01869 SDL_GrabMode wantmode, newmode;
01870 if (mReallyCapturedCount <= 0)
01871 {
01872 wantmode = SDL_GRAB_OFF;
01873 } else
01874 {
01875 wantmode = SDL_GRAB_ON;
01876 }
01877
01878 if (mReallyCapturedCount < 0)
01879 {
01880 mReallyCapturedCount = 0;
01881 llwarns << "ReallyCapture count was < 0" << llendl;
01882 }
01883
01884 if (!mFullscreen)
01885 {
01886 #if LL_X11
01887 if (mSDL_Display)
01888 {
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898 int result;
01899 if (wantmode == SDL_GRAB_ON)
01900 {
01901
01902
01903 maybe_lock_display();
01904 result = XGrabPointer(mSDL_Display, mSDL_XWindowID,
01905 True, 0, GrabModeAsync,
01906 GrabModeAsync,
01907 None, None, CurrentTime);
01908 maybe_unlock_display();
01909 if (GrabSuccess == result)
01910 newmode = SDL_GRAB_ON;
01911 else
01912 newmode = SDL_GRAB_OFF;
01913 } else if (wantmode == SDL_GRAB_OFF)
01914 {
01915
01916 newmode = SDL_GRAB_OFF;
01917
01918
01919 maybe_lock_display();
01920 XUngrabPointer(mSDL_Display, CurrentTime);
01921
01922 XSync(mSDL_Display, False);
01923 maybe_unlock_display();
01924 } else
01925 {
01926 newmode = SDL_GRAB_QUERY;
01927 }
01928 } else
01929 newmode = wantmode;
01930 #endif // LL_X11
01931 } else {
01932
01933 newmode = wantmode;
01934 }
01935
01936
01937 return (capture && SDL_GRAB_ON==newmode) ||
01938 (!capture && SDL_GRAB_OFF==newmode);
01939 }
01940
01941 U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain)
01942 {
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956 U32 mask = 0;
01957 switch (keysym)
01958 {
01959 case SDLK_LALT:
01960 mask = 1U << 0; break;
01961 case SDLK_LCTRL:
01962 mask = 1U << 1; break;
01963 case SDLK_RCTRL:
01964 mask = 1U << 2; break;
01965 default:
01966 break;
01967 }
01968
01969 if (gain)
01970 mGrabbyKeyFlags |= mask;
01971 else
01972 mGrabbyKeyFlags &= ~mask;
01973
01974
01975
01976
01977 return mGrabbyKeyFlags;
01978 }
01979
01980 void LLWindowSDL::gatherInput()
01981 {
01982 const Uint32 CLICK_THRESHOLD = 300;
01983 static int leftClick = 0;
01984 static int rightClick = 0;
01985 static Uint32 lastLeftDown = 0;
01986 static Uint32 lastRightDown = 0;
01987 SDL_Event event;
01988
01989 #if LL_GTK && LL_LIBXUL_ENABLED
01990
01991 if (ll_try_gtk_init())
01992 {
01993
01994
01995
01996
01997 std::string saved_locale = setlocale(LC_ALL, NULL);
01998
01999
02000
02001 gtk_main_iteration_do(0);
02002 for (int iter=0; iter<10; ++iter)
02003 if (gtk_events_pending())
02004 gtk_main_iteration();
02005
02006 setlocale(LC_ALL, saved_locale.c_str() );
02007 }
02008 #endif // LL_GTK && LL_LIBXUL_ENABLED
02009
02010
02011 while (SDL_PollEvent(&event))
02012 {
02013 switch (event.type)
02014 {
02015 case SDL_MOUSEMOTION:
02016 {
02017 LLCoordWindow winCoord(event.button.x, event.button.y);
02018 LLCoordGL openGlCoord;
02019 convertCoords(winCoord, &openGlCoord);
02020 MASK mask = gKeyboard->currentMask(TRUE);
02021 mCallbacks->handleMouseMove(this, openGlCoord, mask);
02022 break;
02023 }
02024
02025 case SDL_KEYDOWN:
02026 gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
02027
02028 if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
02029 SDLReallyCaptureInput(TRUE);
02030
02031 if (event.key.keysym.unicode)
02032 {
02033 handleUnicodeUTF16(event.key.keysym.unicode,
02034 gKeyboard->currentMask(FALSE));
02035 }
02036 break;
02037
02038 case SDL_KEYUP:
02039 if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0)
02040 SDLReallyCaptureInput(FALSE);
02041
02042 gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
02043 break;
02044
02045 case SDL_MOUSEBUTTONDOWN:
02046 {
02047 bool isDoubleClick = false;
02048 LLCoordWindow winCoord(event.button.x, event.button.y);
02049 LLCoordGL openGlCoord;
02050 convertCoords(winCoord, &openGlCoord);
02051 MASK mask = gKeyboard->currentMask(TRUE);
02052
02053 if (event.button.button == SDL_BUTTON_LEFT)
02054 {
02055 Uint32 now = SDL_GetTicks();
02056 if ((now - lastLeftDown) > CLICK_THRESHOLD)
02057 leftClick = 1;
02058 else
02059 {
02060 if (++leftClick >= 2)
02061 {
02062 leftClick = 0;
02063 isDoubleClick = true;
02064 }
02065 }
02066 lastLeftDown = now;
02067 }
02068 else if (event.button.button == SDL_BUTTON_RIGHT)
02069 {
02070 Uint32 now = SDL_GetTicks();
02071 if ((now - lastRightDown) > CLICK_THRESHOLD)
02072 rightClick = 1;
02073 else
02074 {
02075 if (++rightClick >= 2)
02076 {
02077 rightClick = 0;
02078 isDoubleClick = true;
02079 }
02080 }
02081 lastRightDown = now;
02082 }
02083
02084 if (event.button.button == SDL_BUTTON_LEFT)
02085 {
02086 if (isDoubleClick)
02087 mCallbacks->handleDoubleClick(this, openGlCoord, mask);
02088 else
02089 mCallbacks->handleMouseDown(this, openGlCoord, mask);
02090 }
02091
02092 else if (event.button.button == SDL_BUTTON_RIGHT)
02093 {
02094
02095 mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
02096 }
02097
02098 else if (event.button.button == SDL_BUTTON_MIDDLE)
02099 {
02100 mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
02101 }
02102 else if (event.button.button == 4)
02103 mCallbacks->handleScrollWheel(this, -1);
02104 else if (event.button.button == 5)
02105 mCallbacks->handleScrollWheel(this, 1);
02106
02107 break;
02108 }
02109
02110 case SDL_MOUSEBUTTONUP:
02111 {
02112 LLCoordWindow winCoord(event.button.x, event.button.y);
02113 LLCoordGL openGlCoord;
02114 convertCoords(winCoord, &openGlCoord);
02115 MASK mask = gKeyboard->currentMask(TRUE);
02116
02117 if (event.button.button == SDL_BUTTON_LEFT)
02118 mCallbacks->handleMouseUp(this, openGlCoord, mask);
02119 else if (event.button.button == SDL_BUTTON_RIGHT)
02120 mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
02121 else if (event.button.button == SDL_BUTTON_MIDDLE)
02122 {
02123 mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
02124 }
02125
02126
02127 break;
02128 }
02129
02130 case SDL_VIDEOEXPOSE:
02131 mCallbacks->handlePaint(this, 0, 0, mWindow->w, mWindow->h);
02132 break;
02133
02134 case SDL_VIDEORESIZE:
02135 llinfos << "Handling a resize event: " << event.resize.w <<
02136 "x" << event.resize.h << llendl;
02137
02138
02139 mWindow = SDL_SetVideoMode(event.resize.w, event.resize.h, 32, mSDLFlags);
02140 if (!mWindow)
02141 {
02142
02143 llinfos << "Could not recreate context after resize! Quitting..." << llendl;
02144 if(mCallbacks->handleCloseRequest(this))
02145 {
02146
02147 mCallbacks->handleQuit(this);
02148
02149 }
02150 break;
02151 }
02152
02153 mCallbacks->handleResize(this, event.resize.w, event.resize.h );
02154 break;
02155
02156 case SDL_ACTIVEEVENT:
02157 if (event.active.state & SDL_APPINPUTFOCUS)
02158 {
02159
02160
02161
02162
02163
02164
02165
02166 if (event.active.gain != mHaveInputFocus)
02167 {
02168 if (event.active.gain)
02169 mCallbacks->handleFocus(this);
02170 else
02171 mCallbacks->handleFocusLost(this);
02172
02173 mHaveInputFocus = !!event.active.gain;
02174 }
02175 }
02176 if (event.active.state & SDL_APPACTIVE)
02177 {
02178
02179 if ((!event.active.gain) != mIsMinimized)
02180 {
02181 mCallbacks->handleActivate(this, !!event.active.gain);
02182 llinfos << "SDL deiconification state switched to " << BOOL(event.active.gain) << llendl;
02183
02184 mIsMinimized = (!event.active.gain);
02185 }
02186 else
02187 {
02188 llinfos << "Ignored bogus redundant SDL deiconification state switch to " << BOOL(event.active.gain) << llendl;
02189 }
02190 }
02191 break;
02192
02193 case SDL_QUIT:
02194 if(mCallbacks->handleCloseRequest(this))
02195 {
02196
02197 mCallbacks->handleQuit(this);
02198
02199 }
02200 break;
02201 default:
02202
02203 break;
02204 }
02205 }
02206
02207 #if LL_X11
02208
02209
02210 if (mFlashing && mFlashTimer.hasExpired())
02211 {
02212 x11_set_urgent(FALSE);
02213 mFlashing = FALSE;
02214 }
02215 #endif // LL_X11
02216 }
02217
02218 static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty)
02219 {
02220 SDL_Cursor *sdlcursor = NULL;
02221 SDL_Surface *bmpsurface;
02222
02223
02224 bmpsurface = Load_BMP_Resource(filename);
02225 if (bmpsurface && bmpsurface->w%8==0)
02226 {
02227 SDL_Surface *cursurface;
02228 lldebugs << "Loaded cursor file " << filename << " "
02229 << bmpsurface->w << "x" << bmpsurface->h << llendl;
02230 cursurface = SDL_CreateRGBSurface (SDL_SWSURFACE,
02231 bmpsurface->w,
02232 bmpsurface->h,
02233 32,
02234 0xFFU,
02235 0xFF00U,
02236 0xFF0000U,
02237 0xFF000000U);
02238 SDL_FillRect(cursurface, NULL, 0x00000000U);
02239
02240
02241
02242 if (0 == SDL_BlitSurface(bmpsurface, NULL,
02243 cursurface, NULL))
02244 {
02245
02246 const int bitmap_bytes = (cursurface->w * cursurface->h) / 8;
02247 unsigned char *cursor_data = new unsigned char[bitmap_bytes];
02248 unsigned char *cursor_mask = new unsigned char[bitmap_bytes];
02249 memset(cursor_data, 0, bitmap_bytes);
02250 memset(cursor_mask, 0, bitmap_bytes);
02251 int i,j;
02252
02253
02254
02255 for (i=0; i<cursurface->h; ++i) {
02256 for (j=0; j<cursurface->w; ++j) {
02257 unsigned char *pixelp =
02258 ((unsigned char *)cursurface->pixels)
02259 + cursurface->pitch * i
02260 + j*cursurface->format->BytesPerPixel;
02261 unsigned char srcred = pixelp[0];
02262 unsigned char srcgreen = pixelp[1];
02263 unsigned char srcblue = pixelp[2];
02264 BOOL mask_bit = (srcred != 200)
02265 || (srcgreen != 200)
02266 || (srcblue != 200);
02267 BOOL data_bit = mask_bit && (srcgreen <= 80);
02268 unsigned char bit_offset = (cursurface->w/8) * i
02269 + j/8;
02270 cursor_data[bit_offset] |= (data_bit) << (7 - (j&7));
02271 cursor_mask[bit_offset] |= (mask_bit) << (7 - (j&7));
02272 }
02273 }
02274 sdlcursor = SDL_CreateCursor((Uint8*)cursor_data,
02275 (Uint8*)cursor_mask,
02276 cursurface->w, cursurface->h,
02277 hotx, hoty);
02278 delete[] cursor_data;
02279 delete[] cursor_mask;
02280 } else {
02281 llwarns << "CURSOR BLIT FAILURE, cursurface: " << cursurface << llendl;
02282 }
02283 SDL_FreeSurface(cursurface);
02284 SDL_FreeSurface(bmpsurface);
02285 } else {
02286 llwarns << "CURSOR LOAD FAILURE " << filename << llendl;
02287 }
02288
02289 return sdlcursor;
02290 }
02291
02292 void LLWindowSDL::setCursor(ECursorType cursor)
02293 {
02294 if (mCurrentCursor != cursor)
02295 {
02296 if (cursor < UI_CURSOR_COUNT)
02297 {
02298 SDL_Cursor *sdlcursor = mSDLCursors[cursor];
02299
02300
02301 if (!sdlcursor && mSDLCursors[UI_CURSOR_ARROW])
02302 sdlcursor = mSDLCursors[UI_CURSOR_ARROW];
02303 if (sdlcursor)
02304 SDL_SetCursor(sdlcursor);
02305 } else {
02306 llwarns << "Tried to set invalid cursor number " << cursor << llendl;
02307 }
02308 mCurrentCursor = cursor;
02309 }
02310 }
02311
02312 ECursorType LLWindowSDL::getCursor()
02313 {
02314 return mCurrentCursor;
02315 }
02316
02317 void LLWindowSDL::initCursors()
02318 {
02319 int i;
02320
02321 for (i=0; i<UI_CURSOR_COUNT; ++i)
02322 {
02323 mSDLCursors[i] = NULL;
02324 }
02325
02326
02327
02328
02329 mSDLCursors[UI_CURSOR_ARROW] = makeSDLCursorFromBMP("llarrow.BMP",0,0);
02330 mSDLCursors[UI_CURSOR_WAIT] = makeSDLCursorFromBMP("wait.BMP",12,15);
02331 mSDLCursors[UI_CURSOR_HAND] = makeSDLCursorFromBMP("hand.BMP",7,10);
02332 mSDLCursors[UI_CURSOR_IBEAM] = makeSDLCursorFromBMP("ibeam.BMP",15,16);
02333 mSDLCursors[UI_CURSOR_CROSS] = makeSDLCursorFromBMP("cross.BMP",16,14);
02334 mSDLCursors[UI_CURSOR_SIZENWSE] = makeSDLCursorFromBMP("sizenwse.BMP",14,17);
02335 mSDLCursors[UI_CURSOR_SIZENESW] = makeSDLCursorFromBMP("sizenesw.BMP",17,17);
02336 mSDLCursors[UI_CURSOR_SIZEWE] = makeSDLCursorFromBMP("sizewe.BMP",16,14);
02337 mSDLCursors[UI_CURSOR_SIZENS] = makeSDLCursorFromBMP("sizens.BMP",17,16);
02338 mSDLCursors[UI_CURSOR_NO] = makeSDLCursorFromBMP("llno.BMP",8,8);
02339 mSDLCursors[UI_CURSOR_WORKING] = makeSDLCursorFromBMP("working.BMP",12,15);
02340 mSDLCursors[UI_CURSOR_TOOLGRAB] = makeSDLCursorFromBMP("lltoolgrab.BMP",2,13);
02341 mSDLCursors[UI_CURSOR_TOOLLAND] = makeSDLCursorFromBMP("lltoolland.BMP",1,6);
02342 mSDLCursors[UI_CURSOR_TOOLFOCUS] = makeSDLCursorFromBMP("lltoolfocus.BMP",8,5);
02343 mSDLCursors[UI_CURSOR_TOOLCREATE] = makeSDLCursorFromBMP("lltoolcreate.BMP",7,7);
02344 mSDLCursors[UI_CURSOR_ARROWDRAG] = makeSDLCursorFromBMP("arrowdrag.BMP",0,0);
02345 mSDLCursors[UI_CURSOR_ARROWCOPY] = makeSDLCursorFromBMP("arrowcop.BMP",0,0);
02346 mSDLCursors[UI_CURSOR_ARROWDRAGMULTI] = makeSDLCursorFromBMP("llarrowdragmulti.BMP",0,0);
02347 mSDLCursors[UI_CURSOR_ARROWCOPYMULTI] = makeSDLCursorFromBMP("arrowcopmulti.BMP",0,0);
02348 mSDLCursors[UI_CURSOR_NOLOCKED] = makeSDLCursorFromBMP("llnolocked.BMP",8,8);
02349 mSDLCursors[UI_CURSOR_ARROWLOCKED] = makeSDLCursorFromBMP("llarrowlocked.BMP",0,0);
02350 mSDLCursors[UI_CURSOR_GRABLOCKED] = makeSDLCursorFromBMP("llgrablocked.BMP",2,13);
02351 mSDLCursors[UI_CURSOR_TOOLTRANSLATE] = makeSDLCursorFromBMP("lltooltranslate.BMP",0,0);
02352 mSDLCursors[UI_CURSOR_TOOLROTATE] = makeSDLCursorFromBMP("lltoolrotate.BMP",0,0);
02353 mSDLCursors[UI_CURSOR_TOOLSCALE] = makeSDLCursorFromBMP("lltoolscale.BMP",0,0);
02354 mSDLCursors[UI_CURSOR_TOOLCAMERA] = makeSDLCursorFromBMP("lltoolcamera.BMP",7,5);
02355 mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromBMP("lltoolpan.BMP",7,5);
02356 mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromBMP("lltoolzoomin.BMP",7,5);
02357 mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromBMP("toolpickobject3.BMP",0,0);
02358 mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromBMP("toolsit.BMP",0,0);
02359 mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromBMP("toolbuy.BMP",0,0);
02360 mSDLCursors[UI_CURSOR_TOOLPAY] = makeSDLCursorFromBMP("toolpay.BMP",0,0);
02361 mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromBMP("toolopen.BMP",0,0);
02362 mSDLCursors[UI_CURSOR_PIPETTE] = makeSDLCursorFromBMP("lltoolpipette.BMP",2,28);
02363 }
02364
02365 void LLWindowSDL::quitCursors()
02366 {
02367 int i;
02368 if (mWindow)
02369 {
02370 for (i=0; i<UI_CURSOR_COUNT; ++i)
02371 {
02372 if (mSDLCursors[i])
02373 {
02374 SDL_FreeCursor(mSDLCursors[i]);
02375 mSDLCursors[i] = NULL;
02376 }
02377 }
02378 } else {
02379
02380
02381 llinfos << "Skipping quitCursors: mWindow already gone." << llendl;
02382 for (i=0; i<UI_CURSOR_COUNT; ++i)
02383 mSDLCursors[i] = NULL;
02384 }
02385 }
02386
02387 void LLWindowSDL::captureMouse()
02388 {
02389
02390
02391
02392
02393
02394
02395
02396 }
02397
02398 void LLWindowSDL::releaseMouse()
02399 {
02400
02401
02402
02403 }
02404
02405 void LLWindowSDL::hideCursor()
02406 {
02407 if(!mCursorHidden)
02408 {
02409
02410 mCursorHidden = TRUE;
02411 mHideCursorPermanent = TRUE;
02412 SDL_ShowCursor(0);
02413 }
02414 else
02415 {
02416
02417 }
02418
02419 adjustCursorDecouple();
02420 }
02421
02422 void LLWindowSDL::showCursor()
02423 {
02424 if(mCursorHidden)
02425 {
02426
02427 mCursorHidden = FALSE;
02428 mHideCursorPermanent = FALSE;
02429 SDL_ShowCursor(1);
02430 }
02431 else
02432 {
02433
02434 }
02435
02436 adjustCursorDecouple();
02437 }
02438
02439 void LLWindowSDL::showCursorFromMouseMove()
02440 {
02441 if (!mHideCursorPermanent)
02442 {
02443 showCursor();
02444 }
02445 }
02446
02447 void LLWindowSDL::hideCursorUntilMouseMove()
02448 {
02449 if (!mHideCursorPermanent)
02450 {
02451 hideCursor();
02452 mHideCursorPermanent = FALSE;
02453 }
02454 }
02455
02456
02457
02458
02459
02460
02461
02462 LLSplashScreenSDL::LLSplashScreenSDL()
02463 {
02464 }
02465
02466 LLSplashScreenSDL::~LLSplashScreenSDL()
02467 {
02468 }
02469
02470 void LLSplashScreenSDL::showImpl()
02471 {
02472 }
02473
02474 void LLSplashScreenSDL::updateImpl(const char* mesg)
02475 {
02476 }
02477
02478 void LLSplashScreenSDL::hideImpl()
02479 {
02480 }
02481
02482
02483
02484 #if LL_GTK
02485 static void response_callback (GtkDialog *dialog,
02486 gint arg1,
02487 gpointer user_data)
02488 {
02489 gint *response = (gint*)user_data;
02490 *response = arg1;
02491 gtk_widget_destroy(GTK_WIDGET(dialog));
02492 gtk_main_quit();
02493 }
02494
02495 S32 OSMessageBoxSDL(const char* text, const char* caption, U32 type)
02496 {
02497 S32 rtn = OSBTN_CANCEL;
02498
02499 ll_try_gtk_init();
02500
02501 if(gWindowImplementation != NULL)
02502 gWindowImplementation->beforeDialog();
02503
02504 if (ll_try_gtk_init()
02505
02506 && ((NULL==gWindowImplementation) || (!was_fullscreen))
02507 )
02508 {
02509 GtkWidget *win = NULL;
02510
02511 llinfos << "Creating a dialog because we're in windowed mode and GTK is happy." << llendl;
02512
02513 GtkDialogFlags flags = GTK_DIALOG_MODAL;
02514 GtkMessageType messagetype;
02515 GtkButtonsType buttons;
02516 switch (type)
02517 {
02518 default:
02519 case OSMB_OK:
02520 messagetype = GTK_MESSAGE_WARNING;
02521 buttons = GTK_BUTTONS_OK;
02522 break;
02523 case OSMB_OKCANCEL:
02524 messagetype = GTK_MESSAGE_QUESTION;
02525 buttons = GTK_BUTTONS_OK_CANCEL;
02526 break;
02527 case OSMB_YESNO:
02528 messagetype = GTK_MESSAGE_QUESTION;
02529 buttons = GTK_BUTTONS_YES_NO;
02530 break;
02531 }
02532 win = gtk_message_dialog_new(NULL,
02533 flags, messagetype, buttons,
02534 text);
02535
02536 # if LL_X11
02537
02538
02539
02540 if (gWindowImplementation &&
02541 gWindowImplementation->mSDL_XWindowID != None)
02542 {
02543 gtk_widget_realize(GTK_WIDGET(win));
02544 GdkWindow *gdkwin = gdk_window_foreign_new(gWindowImplementation->mSDL_XWindowID);
02545 gdk_window_set_transient_for(GTK_WIDGET(win)->window,
02546 gdkwin);
02547 }
02548 # endif //LL_X11
02549
02550 gtk_window_set_position(GTK_WINDOW(win),
02551 GTK_WIN_POS_CENTER_ON_PARENT);
02552
02553 gtk_window_set_type_hint(GTK_WINDOW(win),
02554 GDK_WINDOW_TYPE_HINT_DIALOG);
02555
02556 if (caption)
02557 gtk_window_set_title(GTK_WINDOW(win), caption);
02558
02559 gint response = GTK_RESPONSE_NONE;
02560 g_signal_connect (win,
02561 "response",
02562 G_CALLBACK (response_callback),
02563 &response);
02564
02565
02566
02567
02568 gtk_widget_show_all (win);
02569 gtk_main();
02570
02571
02572 switch (response)
02573 {
02574 case GTK_RESPONSE_OK: rtn = OSBTN_OK; break;
02575 case GTK_RESPONSE_YES: rtn = OSBTN_YES; break;
02576 case GTK_RESPONSE_NO: rtn = OSBTN_NO; break;
02577 case GTK_RESPONSE_APPLY: rtn = OSBTN_OK; break;
02578 case GTK_RESPONSE_NONE:
02579 case GTK_RESPONSE_CANCEL:
02580 case GTK_RESPONSE_CLOSE:
02581 case GTK_RESPONSE_DELETE_EVENT:
02582 default: rtn = OSBTN_CANCEL;
02583 }
02584 }
02585 else
02586 {
02587 llinfos << "MSGBOX: " << caption << ": " << text << llendl;
02588 llinfos << "Skipping dialog because we're in fullscreen mode or GTK is not happy." << llendl;
02589 rtn = OSBTN_OK;
02590 }
02591
02592 if(gWindowImplementation != NULL)
02593 gWindowImplementation->afterDialog();
02594
02595 return rtn;
02596 }
02597
02598 static void color_changed_callback(GtkWidget *widget,
02599 gpointer user_data)
02600 {
02601 GtkColorSelection *colorsel = GTK_COLOR_SELECTION(widget);
02602 GdkColor *colorp = (GdkColor*)user_data;
02603
02604 gtk_color_selection_get_current_color(colorsel, colorp);
02605 }
02606
02607 BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
02608 {
02609 BOOL rtn = FALSE;
02610
02611 beforeDialog();
02612
02613 if (ll_try_gtk_init()
02614
02615 && !was_fullscreen
02616 )
02617 {
02618 GtkWidget *win = NULL;
02619
02620 win = gtk_color_selection_dialog_new(NULL);
02621
02622 # if LL_X11
02623
02624
02625
02626 if (mSDL_XWindowID != None)
02627 {
02628 gtk_widget_realize(GTK_WIDGET(win));
02629 GdkWindow *gdkwin = gdk_window_foreign_new(mSDL_XWindowID);
02630 gdk_window_set_transient_for(GTK_WIDGET(win)->window,
02631 gdkwin);
02632 }
02633 # endif //LL_X11
02634
02635 GtkColorSelection *colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG(win)->colorsel);
02636
02637 GdkColor color, orig_color;
02638 orig_color.red = guint16(65535 * *r);
02639 orig_color.green= guint16(65535 * *g);
02640 orig_color.blue = guint16(65535 * *b);
02641 color = orig_color;
02642
02643 gtk_color_selection_set_previous_color (colorsel, &color);
02644 gtk_color_selection_set_current_color (colorsel, &color);
02645 gtk_color_selection_set_has_palette (colorsel, TRUE);
02646 gtk_color_selection_set_has_opacity_control(colorsel, FALSE);
02647
02648 gint response = GTK_RESPONSE_NONE;
02649 g_signal_connect (win,
02650 "response",
02651 G_CALLBACK (response_callback),
02652 &response);
02653
02654 g_signal_connect (G_OBJECT (colorsel), "color_changed",
02655 G_CALLBACK (color_changed_callback),
02656 &color);
02657
02658 gtk_window_set_modal(GTK_WINDOW(win), TRUE);
02659 gtk_widget_show_all(win);
02660
02661 gtk_widget_hide(GTK_COLOR_SELECTION_DIALOG(win)->help_button);
02662 gtk_main();
02663
02664 if (response == GTK_RESPONSE_OK &&
02665 (orig_color.red != color.red
02666 || orig_color.green != color.green
02667 || orig_color.blue != color.blue) )
02668 {
02669 *r = color.red / 65535.0f;
02670 *g = color.green / 65535.0f;
02671 *b = color.blue / 65535.0f;
02672 rtn = TRUE;
02673 }
02674 }
02675
02676 afterDialog();
02677
02678 return rtn;
02679 }
02680 #else
02681 S32 OSMessageBoxSDL(const char* text, const char* caption, U32 type)
02682 {
02683 llinfos << "MSGBOX: " << caption << ": " << text << llendl;
02684 return 0;
02685 }
02686
02687 BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
02688 {
02689 return (FALSE);
02690 }
02691 #endif // LL_GTK
02692
02693
02694
02695 void spawn_web_browser(const char* escaped_url)
02696 {
02697 llinfos << "spawn_web_browser: " << escaped_url << llendl;
02698
02699 #if LL_LINUX || LL_SOLARIS
02700 # if LL_X11
02701 if (gWindowImplementation && gWindowImplementation->mSDL_Display)
02702 {
02703 maybe_lock_display();
02704
02705 XSync(gWindowImplementation->mSDL_Display, False);
02706 maybe_unlock_display();
02707 }
02708 # endif // LL_X11
02709
02710 std::string cmd;
02711 cmd = gDirUtilp->getAppRODataDir().c_str();
02712 cmd += gDirUtilp->getDirDelimiter().c_str();
02713 cmd += "launch_url.sh";
02714 char* const argv[] = {(char*)cmd.c_str(), (char*)escaped_url, NULL};
02715
02716 fflush(NULL);
02717 pid_t pid = fork();
02718 if (pid == 0)
02719 {
02720
02721
02722 close(0);
02723 close(1);
02724 close(2);
02725
02726 execv(cmd.c_str(), argv);
02727
02728 llwarns << "execv failure when trying to start " << cmd << llendl;
02729 _exit(1);
02730 } else {
02731 if (pid > 0)
02732 {
02733
02734 int childExitStatus;
02735 waitpid(pid, &childExitStatus, 0);
02736 } else {
02737 llwarns << "fork failure." << llendl;
02738 }
02739 }
02740 #endif // LL_LINUX || LL_SOLARIS
02741
02742 llinfos << "spawn_web_browser returning." << llendl;
02743 }
02744
02745 void shell_open( const char* file_path )
02746 {
02747
02748 llwarns << "Deprecated shell_open(): " << file_path << llendl;
02749 }
02750
02751 void *LLWindowSDL::getPlatformWindow()
02752 {
02753 #if LL_GTK && LL_LIBXUL_ENABLED
02754 if (ll_try_gtk_init())
02755 {
02756 maybe_lock_display();
02757 GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
02758
02759
02760
02761
02762 gtk_widget_realize(GTK_WIDGET(win));
02763 maybe_unlock_display();
02764 return win;
02765 }
02766 #endif // LL_GTK && LL_LIBXUL_ENABLED
02767
02768 return NULL;
02769 }
02770
02771 void LLWindowSDL::bringToFront()
02772 {
02773
02774
02775 llinfos << "bringToFront" << llendl;
02776 #if LL_X11
02777 if (mSDL_Display && !mFullscreen)
02778 {
02779 maybe_lock_display();
02780 XRaiseWindow(mSDL_Display, mSDL_XWindowID);
02781 XSync(mSDL_Display, False);
02782 maybe_unlock_display();
02783 }
02784 #endif // LL_X11
02785 }
02786
02787 #endif // LL_SDL