aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llwindow/llwindowsdl.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llwindow/llwindowsdl.cpp767
1 files changed, 163 insertions, 604 deletions
diff --git a/linden/indra/llwindow/llwindowsdl.cpp b/linden/indra/llwindow/llwindowsdl.cpp
index 777b32d..d6ee7ac 100644
--- a/linden/indra/llwindow/llwindowsdl.cpp
+++ b/linden/indra/llwindow/llwindowsdl.cpp
@@ -1,6 +1,7 @@
1/** 1/**
2 * @file llwindowsdl.cpp 2 * @file llwindowsdl.cpp
3 * @brief SDL implementation of LLWindow class 3 * @brief SDL implementation of LLWindow class
4 * @author This module has many fathers, and it shows.
4 * 5 *
5 * $LicenseInfo:firstyear=2001&license=viewergpl$ 6 * $LicenseInfo:firstyear=2001&license=viewergpl$
6 * 7 *
@@ -17,7 +18,8 @@
17 * There are special exceptions to the terms and conditions of the GPL as 18 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 19 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 20 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception 21 * online at
22 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 23 *
22 * By copying, modifying or distributing this software, you acknowledge 24 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 25 * that you have read and understood your obligations described above,
@@ -83,8 +85,6 @@ static bool ATIbug = false;
83// be only one object of this class at any time. Currently this is true. 85// be only one object of this class at any time. Currently this is true.
84static LLWindowSDL *gWindowImplementation = NULL; 86static LLWindowSDL *gWindowImplementation = NULL;
85 87
86static BOOL was_fullscreen = FALSE;
87
88 88
89void maybe_lock_display(void) 89void maybe_lock_display(void)
90{ 90{
@@ -154,6 +154,8 @@ bool LLWindowSDL::ll_try_gtk_init(void)
154 llwarns << "- GTK COMPATIBILITY WARNING: " << 154 llwarns << "- GTK COMPATIBILITY WARNING: " <<
155 gtk_warning << llendl; 155 gtk_warning << llendl;
156 gtk_is_good = FALSE; 156 gtk_is_good = FALSE;
157 } else {
158 llinfos << "- GTK version is good." << llendl;
157 } 159 }
158 160
159 done_gtk_diag = TRUE; 161 done_gtk_diag = TRUE;
@@ -186,11 +188,12 @@ Display* LLWindowSDL::get_SDL_Display(void)
186 188
187 189
188LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width, 190LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width,
189 S32 height, U32 flags, 191 S32 height, U32 flags,
190 BOOL fullscreen, BOOL clearBg, 192 BOOL fullscreen, BOOL clearBg,
191 BOOL disable_vsync, BOOL use_gl, 193 BOOL disable_vsync, BOOL use_gl,
192 BOOL ignore_pixel_depth, U32 fsaa_samples) 194 BOOL ignore_pixel_depth, U32 fsaa_samples)
193 : LLWindow(fullscreen, flags), mGamma(1.0f) 195 : LLWindow(fullscreen, flags), Lock_Display(NULL),
196 Unlock_Display(NULL), mGamma(1.0f)
194{ 197{
195 // Initialize the keyboard 198 // Initialize the keyboard
196 gKeyboard = new LLKeyboardSDL(); 199 gKeyboard = new LLKeyboardSDL();
@@ -198,10 +201,6 @@ LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width,
198 201
199 // Ignore use_gl for now, only used for drones on PC 202 // Ignore use_gl for now, only used for drones on PC
200 mWindow = NULL; 203 mWindow = NULL;
201 mCursorDecoupled = FALSE;
202 mCursorLastEventDeltaX = 0;
203 mCursorLastEventDeltaY = 0;
204 mCursorIgnoreNextDelta = FALSE;
205 mNeedsResize = FALSE; 204 mNeedsResize = FALSE;
206 mOverrideAspectRatio = 0.f; 205 mOverrideAspectRatio = 0.f;
207 mGrabbyKeyFlags = 0; 206 mGrabbyKeyFlags = 0;
@@ -270,7 +269,7 @@ static SDL_Surface *Load_BMP_Resource(const char *basename)
270#if LL_X11 269#if LL_X11
271// This is an XFree86/XOrg-specific hack for detecting the amount of Video RAM 270// This is an XFree86/XOrg-specific hack for detecting the amount of Video RAM
272// on this machine. It works by searching /var/log/var/log/Xorg.?.log or 271// on this machine. It works by searching /var/log/var/log/Xorg.?.log or
273// /var/log/XFree86.?.log for a ': (VideoRAM|Memory): (%d+) kB' regex, where 272// /var/log/XFree86.?.log for a ': (VideoRAM ?|Memory): (%d+) kB' regex, where
274// '?' is the X11 display number derived from $DISPLAY 273// '?' is the X11 display number derived from $DISPLAY
275static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str) 274static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str)
276{ 275{
@@ -284,6 +283,8 @@ static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str)
284 // favourite regex implementation - libboost_regex - is 283 // favourite regex implementation - libboost_regex - is
285 // quite a heavy and troublesome dependency for the client, so 284 // quite a heavy and troublesome dependency for the client, so
286 // it seems a shame to introduce it for such a simple task. 285 // it seems a shame to introduce it for such a simple task.
286 // *FIXME: libboost_regex is a dependency now anyway, so we may
287 // as well use it instead of this hand-rolled nonsense.
287 const char *part1_template = prefix_str; 288 const char *part1_template = prefix_str;
288 const char part2_template[] = " kB"; 289 const char part2_template[] = " kB";
289 char *part1 = strstr(line_buf, part1_template); 290 char *part1 = strstr(line_buf, part1_template);
@@ -321,8 +322,7 @@ static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str)
321 322
322static int x11_detect_VRAM_kb() 323static int x11_detect_VRAM_kb()
323{ 324{
324#if LL_SOLARIS 325#if LL_SOLARIS && defined(__sparc)
325#error Can this be done without an explicit architecture test, ie a test FOR xorg? Was followed by: && defined(__sparc)
326 // NOTE: there's no Xorg server on SPARC so just return 0 326 // NOTE: there's no Xorg server on SPARC so just return 0
327 // and allow SDL to attempt to get the amount of VRAM 327 // and allow SDL to attempt to get the amount of VRAM
328 return(0); 328 return(0);
@@ -361,8 +361,17 @@ static int x11_detect_VRAM_kb()
361 fp = fopen(fname.c_str(), "r"); 361 fp = fopen(fname.c_str(), "r");
362 if (fp) 362 if (fp)
363 { 363 {
364 rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: "); 364 rtn = x11_detect_VRAM_kb_fp(fp, ": Video RAM: ");
365 fclose(fp); 365 fclose(fp);
366 if (0 == rtn)
367 {
368 fp = fopen(fname.c_str(), "r");
369 if (fp)
370 {
371 rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
372 fclose(fp);
373 }
374 }
366 } 375 }
367 } 376 }
368 } 377 }
@@ -418,7 +427,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
418 if (SDL_Init(SDL_INIT_VIDEO) < 0) 427 if (SDL_Init(SDL_INIT_VIDEO) < 0)
419 { 428 {
420 llinfos << "sdl_init() failed! " << SDL_GetError() << llendl; 429 llinfos << "sdl_init() failed! " << SDL_GetError() << llendl;
421 setupFailure("window creation error", "error", OSMB_OK); 430 setupFailure("sdl_init() failure, window creation error", "error", OSMB_OK);
422 return false; 431 return false;
423 } 432 }
424 433
@@ -439,7 +448,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
439 if (!videoInfo) 448 if (!videoInfo)
440 { 449 {
441 llinfos << "SDL_GetVideoInfo() failed! " << SDL_GetError() << llendl; 450 llinfos << "SDL_GetVideoInfo() failed! " << SDL_GetError() << llendl;
442 setupFailure("Window creation error", "Error", OSMB_OK); 451 setupFailure("SDL_GetVideoInfo() failed, Window creation error", "Error", OSMB_OK);
443 return FALSE; 452 return FALSE;
444 } 453 }
445 454
@@ -495,7 +504,6 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
495 // *FIX: try to toggle vsync here? 504 // *FIX: try to toggle vsync here?
496 505
497 mFullscreen = fullscreen; 506 mFullscreen = fullscreen;
498 was_fullscreen = fullscreen;
499 507
500 int sdlflags = SDL_OPENGL | SDL_RESIZABLE | SDL_ANYFORMAT; 508 int sdlflags = SDL_OPENGL | SDL_RESIZABLE | SDL_ANYFORMAT;
501 509
@@ -571,7 +579,6 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
571 if (mWindow) 579 if (mWindow)
572 { 580 {
573 mFullscreen = TRUE; 581 mFullscreen = TRUE;
574 was_fullscreen = TRUE;
575 mFullscreenWidth = mWindow->w; 582 mFullscreenWidth = mWindow->w;
576 mFullscreenHeight = mWindow->h; 583 mFullscreenHeight = mWindow->h;
577 mFullscreenBits = mWindow->format->BitsPerPixel; 584 mFullscreenBits = mWindow->format->BitsPerPixel;
@@ -588,7 +595,6 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
588 llwarns << "createContext: fullscreen creation failure. SDL: " << SDL_GetError() << llendl; 595 llwarns << "createContext: fullscreen creation failure. SDL: " << SDL_GetError() << llendl;
589 // No fullscreen support 596 // No fullscreen support
590 mFullscreen = FALSE; 597 mFullscreen = FALSE;
591 was_fullscreen = FALSE;
592 mFullscreenWidth = -1; 598 mFullscreenWidth = -1;
593 mFullscreenHeight = -1; 599 mFullscreenHeight = -1;
594 mFullscreenBits = -1; 600 mFullscreenBits = -1;
@@ -670,8 +676,8 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
670 // fixme: actually, it's REALLY important for picking that we get at 676 // fixme: actually, it's REALLY important for picking that we get at
671 // least 8 bits each of red,green,blue. Alpha we can be a bit more 677 // least 8 bits each of red,green,blue. Alpha we can be a bit more
672 // relaxed about if we have to. 678 // relaxed about if we have to.
673#if LL_SOLARIS 679#if LL_SOLARIS && defined(__sparc)
674#error && defined(__sparc) 680// again the __sparc required because Xsun support, 32bit are very pricey on SPARC
675 if(colorBits < 24) //HACK: on SPARC allow 24-bit color 681 if(colorBits < 24) //HACK: on SPARC allow 24-bit color
676#else 682#else
677 if (colorBits < 32) 683 if (colorBits < 32)
@@ -679,8 +685,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
679 { 685 {
680 close(); 686 close();
681 setupFailure( 687 setupFailure(
682#if LL_SOLARIS 688#if LL_SOLARIS && defined(__sparc)
683#error && defined(__sparc)
684 "Second Life requires at least 24-bit color on SPARC to run in a window.\n" 689 "Second Life requires at least 24-bit color on SPARC to run in a window.\n"
685 "Please use fbconfig to set your default color depth to 24 bits.\n" 690 "Please use fbconfig to set your default color depth to 24 bits.\n"
686 "You may also need to adjust the X11 setting in SMF. To do so use\n" 691 "You may also need to adjust the X11 setting in SMF. To do so use\n"
@@ -715,9 +720,33 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
715#endif 720#endif
716 721
717#if LL_X11 722#if LL_X11
718 init_x11clipboard(); 723 /* Grab the window manager specific information */
724 SDL_SysWMinfo info;
725 SDL_VERSION(&info.version);
726 if ( SDL_GetWMInfo(&info) )
727 {
728 /* Save the information for later use */
729 if ( info.subsystem == SDL_SYSWM_X11 )
730 {
731 mSDL_Display = info.info.x11.display;
732 mSDL_XWindowID = info.info.x11.wmwindow;
733 Lock_Display = info.info.x11.lock_func;
734 Unlock_Display = info.info.x11.unlock_func;
735 }
736 else
737 {
738 llwarns << "We're not running under X11? Wild."
739 << llendl;
740 }
741 }
742 else
743 {
744 llwarns << "We're not running under any known WM. Wild."
745 << llendl;
746 }
719#endif // LL_X11 747#endif // LL_X11
720 748
749
721 //make sure multisampling is disabled by default 750 //make sure multisampling is disabled by default
722 glDisable(GL_MULTISAMPLE_ARB); 751 glDisable(GL_MULTISAMPLE_ARB);
723 752
@@ -761,8 +790,12 @@ BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL
761void LLWindowSDL::destroyContext() 790void LLWindowSDL::destroyContext()
762{ 791{
763 llinfos << "destroyContext begins" << llendl; 792 llinfos << "destroyContext begins" << llendl;
793
764#if LL_X11 794#if LL_X11
765 quit_x11clipboard(); 795 mSDL_Display = NULL;
796 mSDL_XWindowID = None;
797 Lock_Display = NULL;
798 Unlock_Display = NULL;
766#endif // LL_X11 799#endif // LL_X11
767 800
768 // Clean up remaining GL state before blowing away window 801 // Clean up remaining GL state before blowing away window
@@ -896,7 +929,6 @@ BOOL LLWindowSDL::getSize(LLCoordScreen *size)
896 return (TRUE); 929 return (TRUE);
897 } 930 }
898 931
899 llwarns << "LLWindowSDL::getPosition(): no window and not fullscreen!" << llendl;
900 return (FALSE); 932 return (FALSE);
901} 933}
902 934
@@ -909,7 +941,6 @@ BOOL LLWindowSDL::getSize(LLCoordWindow *size)
909 return (TRUE); 941 return (TRUE);
910 } 942 }
911 943
912 llwarns << "LLWindowSDL::getPosition(): no window and not fullscreen!" << llendl;
913 return (FALSE); 944 return (FALSE);
914} 945}
915 946
@@ -928,11 +959,18 @@ BOOL LLWindowSDL::setSize(const LLCoordScreen size)
928{ 959{
929 if(mWindow) 960 if(mWindow)
930 { 961 {
931 // *FIX: (???) 962 // Push a resize event onto SDL's queue - we'll handle it
932 //SizeWindow(mWindow, size.mX, size.mY, true); 963 // when it comes out again.
933 } 964 SDL_Event event;
965 event.type = SDL_VIDEORESIZE;
966 event.resize.w = size.mX;
967 event.resize.h = size.mY;
968 SDL_PushEvent(&event); // copied into queue
934 969
935 return TRUE; 970 return TRUE;
971 }
972
973 return FALSE;
936} 974}
937 975
938void LLWindowSDL::swapBuffers() 976void LLWindowSDL::swapBuffers()
@@ -982,11 +1020,7 @@ BOOL LLWindowSDL::isCursorHidden()
982// Constrains the mouse to the window. 1020// Constrains the mouse to the window.
983void LLWindowSDL::setMouseClipping( BOOL b ) 1021void LLWindowSDL::setMouseClipping( BOOL b )
984{ 1022{
985 //llinfos << "LLWindowSDL::setMouseClipping " << b << llendl;
986 // Just stash the requested state. We'll simulate this when the cursor is hidden by decoupling.
987 mIsMouseClipping = b;
988 //SDL_WM_GrabInput(b ? SDL_GRAB_ON : SDL_GRAB_OFF); 1023 //SDL_WM_GrabInput(b ? SDL_GRAB_ON : SDL_GRAB_OFF);
989 adjustCursorDecouple();
990} 1024}
991 1025
992BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position) 1026BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
@@ -1001,10 +1035,10 @@ BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
1001 1035
1002 //llinfos << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << llendl; 1036 //llinfos << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << llendl;
1003 1037
1004 SDL_WarpMouse(screen_pos.mX, screen_pos.mY); 1038 // do the actual forced cursor move.
1005 1039 SDL_WarpMouse(screen_pos.mX, screen_pos.mY);
1006 // Under certain circumstances, this will trigger us to decouple the cursor. 1040
1007 adjustCursorDecouple(true); 1041 //llinfos << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << llendl;
1008 1042
1009 return result; 1043 return result;
1010} 1044}
@@ -1024,33 +1058,6 @@ BOOL LLWindowSDL::getCursorPosition(LLCoordWindow *position)
1024 return convertCoords(screen_pos, position); 1058 return convertCoords(screen_pos, position);
1025} 1059}
1026 1060
1027void LLWindowSDL::adjustCursorDecouple(bool warpingMouse)
1028{
1029 if(mIsMouseClipping && mCursorHidden)
1030 {
1031 if(warpingMouse)
1032 {
1033 // The cursor should be decoupled. Make sure it is.
1034 if(!mCursorDecoupled)
1035 {
1036 // llinfos << "adjustCursorDecouple: decoupling cursor" << llendl;
1037 //CGAssociateMouseAndMouseCursorPosition(false);
1038 mCursorDecoupled = true;
1039 mCursorIgnoreNextDelta = TRUE;
1040 }
1041 }
1042 }
1043 else
1044 {
1045 // The cursor should not be decoupled. Make sure it isn't.
1046 if(mCursorDecoupled)
1047 {
1048 // llinfos << "adjustCursorDecouple: recoupling cursor" << llendl;
1049 //CGAssociateMouseAndMouseCursorPosition(true);
1050 mCursorDecoupled = false;
1051 }
1052 }
1053}
1054 1061
1055F32 LLWindowSDL::getNativeAspectRatio() 1062F32 LLWindowSDL::getNativeAspectRatio()
1056{ 1063{
@@ -1107,24 +1114,28 @@ F32 LLWindowSDL::getPixelAspectRatio()
1107} 1114}
1108 1115
1109 1116
1110// some of this stuff is to support 'temporarily windowed' mode so that 1117// This is to support 'temporarily windowed' mode so that
1111// dialogs are still usable in fullscreen. HOWEVER! - it's not enabled/working 1118// dialogs are still usable in fullscreen.
1112// yet.
1113static LLCoordScreen old_size;
1114static BOOL old_fullscreen;
1115void LLWindowSDL::beforeDialog() 1119void LLWindowSDL::beforeDialog()
1116{ 1120{
1121 bool running_x11 = false;
1122#if LL_X11
1123 running_x11 = (mSDL_XWindowID != None);
1124#endif //LL_X11
1125
1117 llinfos << "LLWindowSDL::beforeDialog()" << llendl; 1126 llinfos << "LLWindowSDL::beforeDialog()" << llendl;
1118 1127
1119 if (SDLReallyCaptureInput(FALSE) // must ungrab input so popup works! 1128 if (SDLReallyCaptureInput(FALSE)) // must ungrab input so popup works!
1120 && getSize(&old_size))
1121 { 1129 {
1122 old_fullscreen = was_fullscreen; 1130 if (mFullscreen)
1123
1124 if (old_fullscreen)
1125 { 1131 {
1126 // NOT YET WORKING 1132 // need to temporarily go non-fullscreen; bless SDL
1127 //switchContext(FALSE, old_size, TRUE); 1133 // for providing a SDL_WM_ToggleFullScreen() - though
1134 // it only works in X11
1135 if (running_x11 && mWindow)
1136 {
1137 SDL_WM_ToggleFullScreen(mWindow);
1138 }
1128 } 1139 }
1129 } 1140 }
1130 1141
@@ -1150,17 +1161,24 @@ void LLWindowSDL::beforeDialog()
1150 1161
1151void LLWindowSDL::afterDialog() 1162void LLWindowSDL::afterDialog()
1152{ 1163{
1164 bool running_x11 = false;
1165#if LL_X11
1166 running_x11 = (mSDL_XWindowID != None);
1167#endif //LL_X11
1168
1153 llinfos << "LLWindowSDL::afterDialog()" << llendl; 1169 llinfos << "LLWindowSDL::afterDialog()" << llendl;
1154 1170
1155 maybe_unlock_display(); 1171 maybe_unlock_display();
1156 1172
1157 if (old_fullscreen && !was_fullscreen) 1173 if (mFullscreen)
1158 { 1174 {
1159 // *FIX: NOT YET WORKING (see below) 1175 // need to restore fullscreen mode after dialog - only works
1160 //switchContext(TRUE, old_size, TRUE); 1176 // in X11
1177 if (running_x11 && mWindow)
1178 {
1179 SDL_WM_ToggleFullScreen(mWindow);
1180 }
1161 } 1181 }
1162 // *FIX: we need to restore the GL context using
1163 // LLViewerWindow::restoreGL() - but how??
1164} 1182}
1165 1183
1166 1184
@@ -1210,506 +1228,50 @@ void LLWindowSDL::flashIcon(F32 seconds)
1210#endif // LL_X11 1228#endif // LL_X11
1211} 1229}
1212 1230
1213#if LL_X11
1214/* Lots of low-level X11 stuff to handle X11 copy-and-paste */
1215
1216/* Our X11 clipboard support is a bit bizarre in various
1217 organically-grown ways. Ideally it should be fixed to do
1218 real string-type negotiation (this would make pasting to
1219 xterm faster and pasting to UTF-8 emacs work properly), but
1220 right now it has the rare and desirable trait of being
1221 generally stable and working. */
1222
1223typedef Atom x11clipboard_type;
1224
1225/* PRIMARY and CLIPBOARD are the two main kinds of
1226 X11 clipboard. A third are the CUT_BUFFERs which an
1227 obsolete holdover from X10 days and use a quite orthogonal
1228 mechanism. CLIPBOARD is the type whose design most
1229 closely matches SL's own win32-alike explicit copy-and-paste
1230 paradigm.
1231
1232 Pragmatically we support all three to varying degrees. When
1233 we paste into SL, it is strictly from CLIPBOARD. When we copy,
1234 we support (to as full an extent as the clipboard content type
1235 allows) CLIPBOARD, PRIMARY, and CUT_BUFFER0.
1236 */
1237static x11clipboard_type get_x11_readwrite_clipboard_type(void)
1238{
1239 return XInternAtom(LLWindowSDL::get_SDL_Display(), "CLIPBOARD", False);
1240}
1241
1242static x11clipboard_type get_x11_write_clipboard_type(void)
1243{
1244 return XA_PRIMARY;
1245}
1246
1247/* This is where our own private cutbuffer goes - we don't use
1248 a regular cutbuffer (XA_CUT_BUFFER0 etc) for intermediate
1249 storage because their use isn't really defined for holding UTF8. */
1250static x11clipboard_type get_x11_cutbuffer_clipboard_type(void)
1251{
1252 return XInternAtom(LLWindowSDL::get_SDL_Display(), "SECONDLIFE_CUTBUFFER", False);
1253}
1254
1255/* Some X11 atom-generators */
1256static Atom get_x11_targets_atom(void)
1257{
1258 return XInternAtom(LLWindowSDL::get_SDL_Display(), "TARGETS", False);
1259}
1260
1261static Atom get_x11_text_atom(void)
1262{
1263 return XInternAtom(LLWindowSDL::get_SDL_Display(), "TEXT", False);
1264}
1265
1266/* These defines, and convert_data/convert_x11clipboard,
1267 mostly exist to support non-text or unusually-encoded
1268 clipboard data, which we don't really have a need for at
1269 the moment. */
1270#define SDLCLIPTYPE(A, B, C, D) (int)(((A)<<24)|((B)<<16)|((C)<<8)|((D)<<0))
1271#define FORMAT_PREFIX "SECONDLIFE_x11clipboard_0x"
1272
1273static
1274x11clipboard_type convert_format(int type)
1275{
1276 if (!gWindowImplementation)
1277 {
1278 llwarns << "!gWindowImplementation in convert_format()"
1279 << llendl;
1280 return XA_STRING;
1281 }
1282
1283 switch (type)
1284 {
1285 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
1286 // old-style X11 clipboard, strictly only ISO 8859-1 encoding
1287 return XA_STRING;
1288 case SDLCLIPTYPE('U', 'T', 'F', '8'):
1289 // newer de-facto UTF8 clipboard atom
1290 return XInternAtom(gWindowImplementation->mSDL_Display,
1291 "UTF8_STRING", False);
1292 default:
1293 {
1294 /* completely arbitrary clipboard types... we don't actually use
1295 these right now, and support is skeletal. */
1296 char format[sizeof(FORMAT_PREFIX)+8+1]; /* Flawfinder: ignore */
1297
1298 snprintf(format, sizeof(format), "%s%08lx", FORMAT_PREFIX, (unsigned long)type);
1299 return XInternAtom(gWindowImplementation->mSDL_Display,
1300 format, False);
1301 }
1302 }
1303}
1304
1305/* convert platform string to x11 clipboard format. for our
1306 purposes this is pretty trivial right now. */
1307static int
1308convert_data(int type, char *dst, const char *src, int srclen)
1309{
1310 int dstlen;
1311
1312 dstlen = 0;
1313 switch (type)
1314 {
1315 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
1316 case SDLCLIPTYPE('U', 'T', 'F', '8'):
1317 if (src == NULL)
1318 {
1319 break;
1320 }
1321 if ( srclen == 0 )
1322 srclen = strlen(src); /* Flawfinder: ignore */
1323
1324 dstlen = srclen + 1;
1325
1326 if ( dst ) // assume caller made it big enough by asking us
1327 {
1328 memcpy(dst, src, srclen); /* Flawfinder: ignore */
1329 dst[srclen] = '\0';
1330 }
1331 break;
1332
1333 default:
1334 llwarns << "convert_data: Unknown medium type" << llendl;
1335 break;
1336 }
1337 return(dstlen);
1338}
1339
1340/* Convert x11clipboard data to platform string. This too is
1341 pretty trivial for our needs right now, and just about identical
1342 to above. */
1343static int
1344convert_x11clipboard(int type, char *dst, const char *src, int srclen)
1345{
1346 int dstlen;
1347
1348 dstlen = 0;
1349 switch (type)
1350 {
1351 case SDLCLIPTYPE('U', 'T', 'F', '8'):
1352 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
1353 if (src == NULL)
1354 {
1355 break;
1356 }
1357 if ( srclen == 0 )
1358 srclen = strlen(src); /* Flawfinder: ignore */
1359
1360 dstlen = srclen + 1;
1361
1362 if ( dst ) // assume caller made it big enough by asking us
1363 {
1364 memcpy(dst, src, srclen); /* Flawfinder: ignore */
1365 dst[srclen] = '\0';
1366 }
1367 break;
1368
1369 default:
1370 llwarns << "convert_x11clipboard: Unknown medium type" << llendl;
1371 break;
1372 }
1373 return dstlen;
1374}
1375
1376int
1377LLWindowSDL::is_empty_x11clipboard(void)
1378{
1379 int retval;
1380
1381 maybe_lock_display();
1382 retval = ( XGetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type()) == None );
1383 maybe_unlock_display();
1384
1385 return(retval);
1386}
1387 1231
1388void 1232#if LL_GTK
1389LLWindowSDL::put_x11clipboard(int type, int srclen, const char *src) 1233BOOL LLWindowSDL::isClipboardTextAvailable()
1390{ 1234{
1391 x11clipboard_type format; 1235 if (ll_try_gtk_init())
1392 int dstlen;
1393 char *dst;
1394
1395 format = convert_format(type);
1396 dstlen = convert_data(type, NULL, src, srclen);
1397
1398 dst = (char *)malloc(dstlen);
1399 if ( dst != NULL )
1400 { 1236 {
1401 maybe_lock_display(); 1237 GtkClipboard * const clipboard =
1402 Window root = DefaultRootWindow(mSDL_Display); 1238 gtk_clipboard_get(GDK_NONE);
1403 convert_data(type, dst, src, srclen); 1239 return gtk_clipboard_wait_is_text_available(clipboard) ?
1404 // Cutbuffers are only allowed to have STRING atom types, 1240 TRUE : FALSE;
1405 // but Emacs puts UTF8 inside them anyway. We cautiously
1406 // don't.
1407 if (type == SDLCLIPTYPE('T','E','X','T'))
1408 {
1409 // dstlen-1 so we don't include the trailing \0
1410 llinfos << "X11: Populating cutbuffer." <<llendl;
1411 XChangeProperty(mSDL_Display, root,
1412 XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace,
1413 (unsigned char*)dst, dstlen-1);
1414 } else {
1415 // Should we clear the cutbuffer if we can't put the selection in
1416 // it because it's a UTF8 selection? Eh, no great reason I think.
1417 //XDeleteProperty(SDL_Display, root, XA_CUT_BUFFER0);
1418 }
1419 // Private cutbuffer of an appropriate type.
1420 XChangeProperty(mSDL_Display, root,
1421 get_x11_cutbuffer_clipboard_type(), format, 8, PropModeReplace,
1422 (unsigned char*)dst, dstlen-1);
1423 free(dst);
1424
1425 /* Claim ownership of both PRIMARY and CLIPBOARD */
1426 XSetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type(),
1427 mSDL_XWindowID, CurrentTime);
1428 XSetSelectionOwner(mSDL_Display, get_x11_write_clipboard_type(),
1429 mSDL_XWindowID, CurrentTime);
1430
1431 maybe_unlock_display();
1432 } 1241 }
1242 return FALSE; // failure
1433} 1243}
1434 1244
1435void 1245BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &text)
1436LLWindowSDL::get_x11clipboard(int type, int *dstlen, char **dst)
1437{ 1246{
1438 x11clipboard_type format; 1247 if (ll_try_gtk_init())
1439
1440 *dstlen = 0;
1441 format = convert_format(type);
1442
1443 Window owner;
1444 Atom selection;
1445 Atom seln_type;
1446 int seln_format;
1447 unsigned long nbytes;
1448 unsigned long overflow;
1449 char *src;
1450
1451 maybe_lock_display();
1452 owner = XGetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type());
1453 maybe_unlock_display();
1454 if (owner == None)
1455 { 1248 {
1456 // Fall right back to ancient X10 cut-buffers 1249 GtkClipboard * const clipboard =
1457 owner = DefaultRootWindow(mSDL_Display); 1250 gtk_clipboard_get(GDK_NONE);
1458 selection = XA_CUT_BUFFER0; 1251 gchar * const data = gtk_clipboard_wait_for_text(clipboard);
1459 } else if (owner == mSDL_XWindowID) 1252 if (data)
1460 {
1461 // Use our own uncooked opaque string property
1462 owner = DefaultRootWindow(mSDL_Display);
1463 selection = get_x11_cutbuffer_clipboard_type();
1464 }
1465 else
1466 {
1467 // Use full-on X11-style clipboard negotiation with the owning app
1468 int selection_response = 0;
1469 SDL_Event event;
1470
1471 owner = mSDL_XWindowID;
1472 maybe_lock_display();
1473 selection = XInternAtom(mSDL_Display, "SDL_SELECTION", False);
1474 XConvertSelection(mSDL_Display, get_x11_readwrite_clipboard_type(), format,
1475 selection, owner, CurrentTime);
1476 maybe_unlock_display();
1477 llinfos << "X11: Waiting for clipboard to arrive." <<llendl;
1478 while ( ! selection_response )
1479 { 1253 {
1480 // Only look for SYSWMEVENTs, or we may lose keypresses 1254 text = LLWString(utf8str_to_wstring(data));
1481 // etc. 1255 g_free(data);
1482 SDL_PumpEvents(); 1256 return TRUE;
1483 if (1 == SDL_PeepEvents(&event, 1, SDL_GETEVENT,
1484 SDL_SYSWMEVENTMASK) )
1485 {
1486 if ( event.type == SDL_SYSWMEVENT )
1487 {
1488 XEvent xevent =
1489 event.syswm.msg->event.xevent;
1490
1491 if ( (xevent.type == SelectionNotify)&&
1492 (xevent.xselection.requestor == owner) )
1493 selection_response = 1;
1494 }
1495 } else {
1496 llinfos << "X11: Waiting for SYSWM event..." << llendl;
1497 }
1498 }
1499 llinfos << "X11: Clipboard arrived." <<llendl;
1500 }
1501
1502 maybe_lock_display();
1503 if ( XGetWindowProperty(mSDL_Display, owner, selection, 0, INT_MAX/4,
1504 False, format, &seln_type, &seln_format,
1505 &nbytes, &overflow, (unsigned char **)&src) == Success )
1506 {
1507 if ( seln_type == format )
1508 {
1509 *dstlen = convert_x11clipboard(type, NULL, src, nbytes);
1510 *dst = (char *)realloc(*dst, *dstlen);
1511 if ( *dst == NULL )
1512 *dstlen = 0;
1513 else
1514 convert_x11clipboard(type, *dst, src, nbytes);
1515 }
1516 XFree(src);
1517 }
1518 maybe_unlock_display();
1519}
1520
1521int clipboard_filter_callback(const SDL_Event *event)
1522{
1523 /* Post all non-window manager specific events */
1524 if ( event->type != SDL_SYSWMEVENT )
1525 {
1526 return(1);
1527 }
1528
1529 /* Handle window-manager specific clipboard events */
1530 switch (event->syswm.msg->event.xevent.type) {
1531 /* Copy the selection from SECONDLIFE_CUTBUFFER to the requested property */
1532 case SelectionRequest: {
1533 XSelectionRequestEvent *req;
1534 XEvent sevent;
1535 int seln_format;
1536 unsigned long nbytes;
1537 unsigned long overflow;
1538 unsigned char *seln_data;
1539
1540 req = &event->syswm.msg->event.xevent.xselectionrequest;
1541 sevent.xselection.type = SelectionNotify;
1542 sevent.xselection.display = req->display;
1543 sevent.xselection.selection = req->selection;
1544 sevent.xselection.target = None;
1545 sevent.xselection.property = None;
1546 sevent.xselection.requestor = req->requestor;
1547 sevent.xselection.time = req->time;
1548 if ( XGetWindowProperty(LLWindowSDL::get_SDL_Display(), DefaultRootWindow(LLWindowSDL::get_SDL_Display()),
1549 get_x11_cutbuffer_clipboard_type(), 0, INT_MAX/4, False, req->target,
1550 &sevent.xselection.target, &seln_format,
1551 &nbytes, &overflow, &seln_data) == Success )
1552 {
1553 if ( sevent.xselection.target == req->target)
1554 {
1555 if ( sevent.xselection.target == XA_STRING ||
1556 sevent.xselection.target ==
1557 convert_format(SDLCLIPTYPE('U','T','F','8')) )
1558 {
1559 if ( seln_data[nbytes-1] == '\0' )
1560 --nbytes;
1561 }
1562 XChangeProperty(LLWindowSDL::get_SDL_Display(), req->requestor, req->property,
1563 req->target, seln_format, PropModeReplace,
1564 seln_data, nbytes);
1565 sevent.xselection.property = req->property;
1566 } else if (get_x11_targets_atom() == req->target) {
1567 /* only advertise what we currently support */
1568 const int num_supported = 3;
1569 Atom supported[num_supported] = {
1570 XA_STRING, // will be over-written below
1571 get_x11_text_atom(),
1572 get_x11_targets_atom()
1573 };
1574 supported[0] = sevent.xselection.target;
1575 XChangeProperty(LLWindowSDL::get_SDL_Display(), req->requestor,
1576 req->property, XA_ATOM, 32, PropModeReplace,
1577 (unsigned char*)supported,
1578 num_supported);
1579 sevent.xselection.property = req->property;
1580 llinfos << "Clipboard: An app asked us what selections format we offer." << llendl;
1581 } else {
1582 llinfos << "Clipboard: An app requested an unsupported selection format " << req->target << ", we have " << sevent.xselection.target << llendl;
1583 sevent.xselection.target = None;
1584 }
1585 XFree(seln_data);
1586 } 1257 }
1587 int sendret =
1588 XSendEvent(LLWindowSDL::get_SDL_Display(),req->requestor,False,0,&sevent);
1589 if ((sendret==BadValue) || (sendret==BadWindow))
1590 llwarns << "Clipboard SendEvent failed" << llendl;
1591 XSync(LLWindowSDL::get_SDL_Display(), False);
1592 }
1593 break;
1594 } 1258 }
1595 1259 return FALSE; // failure
1596 /* Post the event for X11 clipboard reading above */
1597 return(1);
1598} 1260}
1599 1261
1600int 1262BOOL LLWindowSDL::copyTextToClipboard(const LLWString &text)
1601LLWindowSDL::init_x11clipboard(void)
1602{ 1263{
1603 SDL_SysWMinfo info; 1264 if (ll_try_gtk_init())
1604 int retval;
1605
1606 /* Grab the window manager specific information */
1607 retval = -1;
1608 SDL_SetError("SDL is not running on known window manager");
1609
1610 SDL_VERSION(&info.version);
1611 if ( SDL_GetWMInfo(&info) )
1612 { 1265 {
1613 /* Save the information for later use */ 1266 const std::string utf8 = wstring_to_utf8str(text);
1614 if ( info.subsystem == SDL_SYSWM_X11 ) 1267 GtkClipboard * const clipboard =
1615 { 1268 gtk_clipboard_get(GDK_NONE);
1616 mSDL_Display = info.info.x11.display; 1269 gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length());
1617 mSDL_XWindowID = info.info.x11.wmwindow; 1270 return TRUE;
1618 Lock_Display = info.info.x11.lock_func;
1619 Unlock_Display = info.info.x11.unlock_func;
1620
1621 /* Enable the special window hook events */
1622 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
1623 SDL_SetEventFilter(clipboard_filter_callback);
1624
1625 retval = 0;
1626 }
1627 else
1628 {
1629 SDL_SetError("SDL is not running on X11");
1630 }
1631 }
1632 return(retval);
1633}
1634
1635void
1636LLWindowSDL::quit_x11clipboard(void)
1637{
1638 mSDL_Display = NULL;
1639 mSDL_XWindowID = None;
1640 Lock_Display = NULL;
1641 Unlock_Display = NULL;
1642
1643 SDL_SetEventFilter(NULL); // Stop custom event filtering
1644}
1645
1646/************************************************/
1647
1648BOOL LLWindowSDL::isClipboardTextAvailable()
1649{
1650 return !is_empty_x11clipboard();
1651}
1652
1653BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
1654{
1655 int cliplen; // seems 1 or 2 bytes longer than expected
1656 char *cliptext = NULL;
1657 get_x11clipboard(SDLCLIPTYPE('U','T','F','8'), &cliplen, &cliptext);
1658 if (cliptext)
1659 {
1660 llinfos << "X11: Got UTF8 clipboard text." << llendl;
1661 // at some future time we can use cliplen instead of relying on \0,
1662 // if we ever grok non-ascii, non-utf8 encodings on the clipboard.
1663 std::string clip_str(cliptext);
1664 // we can't necessarily trust the incoming text to be valid UTF-8,
1665 // but utf8str_to_wstring() seems to do an appropriate level of
1666 // validation for avoiding over-reads.
1667 dst = utf8str_to_wstring(clip_str);
1668 /*llinfos << "X11 pasteTextFromClipboard: cliplen=" << cliplen <<
1669 " strlen(cliptext)=" << strlen(cliptext) <<
1670 " clip_str.length()=" << clip_str.length() <<
1671 " dst.length()=" << dst.length() <<
1672 llendl;*/
1673 free(cliptext);
1674 return TRUE; // success
1675 }
1676 get_x11clipboard(SDLCLIPTYPE('T','E','X','T'), &cliplen, &cliptext);
1677 if (cliptext)
1678 {
1679 llinfos << "X11: Got ISO 8859-1 clipboard text." << llendl;
1680 std::string clip_str(cliptext);
1681 std::string utf8_str = rawstr_to_utf8(clip_str);
1682 dst = utf8str_to_wstring(utf8_str);
1683 free(cliptext);
1684 } 1271 }
1685 return FALSE; // failure 1272 return FALSE; // failure
1686} 1273}
1687 1274
1688BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
1689{
1690 std::string utf8text = wstring_to_utf8str(s);
1691 const char* cstr = utf8text.c_str();
1692 if (cstr == NULL)
1693 {
1694 return FALSE;
1695 }
1696 int cstrlen = strlen(cstr); /* Flawfinder: ignore */
1697 int i;
1698 for (i=0; i<cstrlen; ++i)
1699 {
1700 if (0x80 & (unsigned char)cstr[i])
1701 {
1702 // Found an 8-bit character; use new-style UTF8 clipboard
1703 llinfos << "X11: UTF8 copyTextToClipboard" << llendl;
1704 put_x11clipboard(SDLCLIPTYPE('U','T','F','8'), cstrlen, cstr);
1705 return TRUE;
1706 }
1707 }
1708 // Didn't find any 8-bit characters; use old-style ISO 8859-1 clipboard
1709 llinfos << "X11: ISO 8859-1 copyTextToClipboard" << llendl;
1710 put_x11clipboard(SDLCLIPTYPE('T','E','X','T'), cstrlen, cstr);
1711 return TRUE;
1712}
1713#else 1275#else
1714 1276
1715BOOL LLWindowSDL::isClipboardTextAvailable() 1277BOOL LLWindowSDL::isClipboardTextAvailable()
@@ -1726,7 +1288,7 @@ BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
1726{ 1288{
1727 return FALSE; // unsupported 1289 return FALSE; // unsupported
1728} 1290}
1729#endif // LL_X11 1291#endif // LL_GTK
1730 1292
1731LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions) 1293LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions)
1732{ 1294{
@@ -1926,7 +1488,7 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain)
1926 /* part of the fix for SL-13243: Some popular window managers like 1488 /* part of the fix for SL-13243: Some popular window managers like
1927 to totally eat alt-drag for the purposes of moving windows. We 1489 to totally eat alt-drag for the purposes of moving windows. We
1928 spoil their day by acquiring the exclusive X11 mouse lock for as 1490 spoil their day by acquiring the exclusive X11 mouse lock for as
1929 long as LALT is held down, so the window manager can't easily 1491 long as ALT is held down, so the window manager can't easily
1930 see what's happening. Tested successfully with Metacity. 1492 see what's happening. Tested successfully with Metacity.
1931 And... do the same with CTRL, for other darn WMs. We don't 1493 And... do the same with CTRL, for other darn WMs. We don't
1932 care about other metakeys as SL doesn't use them with dragging 1494 care about other metakeys as SL doesn't use them with dragging
@@ -1941,10 +1503,12 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain)
1941 { 1503 {
1942 case SDLK_LALT: 1504 case SDLK_LALT:
1943 mask = 1U << 0; break; 1505 mask = 1U << 0; break;
1944 case SDLK_LCTRL: 1506 case SDLK_RALT:
1945 mask = 1U << 1; break; 1507 mask = 1U << 1; break;
1946 case SDLK_RCTRL: 1508 case SDLK_LCTRL:
1947 mask = 1U << 2; break; 1509 mask = 1U << 2; break;
1510 case SDLK_RCTRL:
1511 mask = 1U << 3; break;
1948 default: 1512 default:
1949 break; 1513 break;
1950 } 1514 }
@@ -1963,7 +1527,7 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain)
1963// virtual 1527// virtual
1964void LLWindowSDL::processMiscNativeEvents() 1528void LLWindowSDL::processMiscNativeEvents()
1965{ 1529{
1966#if LL_GTK && (LL_LLMOZLIB_ENABLED || LL_DBUS_ENABLED) 1530#if LL_GTK
1967 // Pump GTK events to avoid starvation for: 1531 // Pump GTK events to avoid starvation for:
1968 // * Embedded Gecko 1532 // * Embedded Gecko
1969 // * DBUS servicing 1533 // * DBUS servicing
@@ -1990,7 +1554,7 @@ void LLWindowSDL::processMiscNativeEvents()
1990 1554
1991 setlocale(LC_ALL, saved_locale.c_str() ); 1555 setlocale(LC_ALL, saved_locale.c_str() );
1992 } 1556 }
1993#endif // LL_GTK && (LL_LLMOZLIB_ENABLED || LL_DBUS_ENABLED) 1557#endif // LL_GTK
1994} 1558}
1995 1559
1996void LLWindowSDL::gatherInput() 1560void LLWindowSDL::gatherInput()
@@ -2084,10 +1648,9 @@ void LLWindowSDL::gatherInput()
2084 mCallbacks->handleMouseDown(this, openGlCoord, mask); 1648 mCallbacks->handleMouseDown(this, openGlCoord, mask);
2085 } 1649 }
2086 1650
2087 else if (event.button.button == SDL_BUTTON_RIGHT) // right ... yes, it's 3, not 2, in SDL... 1651 else if (event.button.button == SDL_BUTTON_RIGHT) // right
2088 { 1652 {
2089 // right double click isn't handled right now in Second Life ... if (isDoubleClick) 1653 mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
2090 mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
2091 } 1654 }
2092 1655
2093 else if (event.button.button == SDL_BUTTON_MIDDLE) // middle 1656 else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
@@ -2110,13 +1673,11 @@ void LLWindowSDL::gatherInput()
2110 MASK mask = gKeyboard->currentMask(TRUE); 1673 MASK mask = gKeyboard->currentMask(TRUE);
2111 1674
2112 if (event.button.button == SDL_BUTTON_LEFT) // left 1675 if (event.button.button == SDL_BUTTON_LEFT) // left
2113 mCallbacks->handleMouseUp(this, openGlCoord, mask); 1676 mCallbacks->handleMouseUp(this, openGlCoord, mask);
2114 else if (event.button.button == SDL_BUTTON_RIGHT) // right ... yes, it's 3, not 2, in SDL... 1677 else if (event.button.button == SDL_BUTTON_RIGHT) // right
2115 mCallbacks->handleRightMouseUp(this, openGlCoord, mask); 1678 mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
2116 else if (event.button.button == SDL_BUTTON_MIDDLE) // middle 1679 else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
2117 {
2118 mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); 1680 mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
2119 }
2120 // don't handle mousewheel here... 1681 // don't handle mousewheel here...
2121 1682
2122 break; 1683 break;
@@ -2160,12 +1721,12 @@ void LLWindowSDL::gatherInput()
2160 // which confuses the focus code [SL-24071]. 1721 // which confuses the focus code [SL-24071].
2161 if (event.active.gain != mHaveInputFocus) 1722 if (event.active.gain != mHaveInputFocus)
2162 { 1723 {
2163 if (event.active.gain) 1724 mHaveInputFocus = !!event.active.gain;
1725
1726 if (mHaveInputFocus)
2164 mCallbacks->handleFocus(this); 1727 mCallbacks->handleFocus(this);
2165 else 1728 else
2166 mCallbacks->handleFocusLost(this); 1729 mCallbacks->handleFocusLost(this);
2167
2168 mHaveInputFocus = !!event.active.gain;
2169 } 1730 }
2170 } 1731 }
2171 if (event.active.state & SDL_APPACTIVE) 1732 if (event.active.state & SDL_APPACTIVE)
@@ -2173,10 +1734,10 @@ void LLWindowSDL::gatherInput()
2173 // Change in iconification/minimization state. 1734 // Change in iconification/minimization state.
2174 if ((!event.active.gain) != mIsMinimized) 1735 if ((!event.active.gain) != mIsMinimized)
2175 { 1736 {
2176 mCallbacks->handleActivate(this, !!event.active.gain);
2177 llinfos << "SDL deiconification state switched to " << BOOL(event.active.gain) << llendl;
2178
2179 mIsMinimized = (!event.active.gain); 1737 mIsMinimized = (!event.active.gain);
1738
1739 mCallbacks->handleActivate(this, !mIsMinimized);
1740 llinfos << "SDL deiconification state switched to " << BOOL(event.active.gain) << llendl;
2180 } 1741 }
2181 else 1742 else
2182 { 1743 {
@@ -2424,8 +1985,6 @@ void LLWindowSDL::hideCursor()
2424 { 1985 {
2425 // llinfos << "hideCursor: already hidden" << llendl; 1986 // llinfos << "hideCursor: already hidden" << llendl;
2426 } 1987 }
2427
2428 adjustCursorDecouple();
2429} 1988}
2430 1989
2431void LLWindowSDL::showCursor() 1990void LLWindowSDL::showCursor()
@@ -2441,8 +2000,6 @@ void LLWindowSDL::showCursor()
2441 { 2000 {
2442 // llinfos << "showCursor: already visible" << llendl; 2001 // llinfos << "showCursor: already visible" << llendl;
2443 } 2002 }
2444
2445 adjustCursorDecouple();
2446} 2003}
2447 2004
2448void LLWindowSDL::showCursorFromMouseMove() 2005void LLWindowSDL::showCursorFromMouseMove()
@@ -2508,10 +2065,7 @@ S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 typ
2508 if(gWindowImplementation != NULL) 2065 if(gWindowImplementation != NULL)
2509 gWindowImplementation->beforeDialog(); 2066 gWindowImplementation->beforeDialog();
2510 2067
2511 if (LLWindowSDL::ll_try_gtk_init() 2068 if (LLWindowSDL::ll_try_gtk_init())
2512 // We can NOT expect to combine GTK and SDL's aggressive fullscreen
2513 && ((NULL==gWindowImplementation) || (!was_fullscreen))
2514 )
2515 { 2069 {
2516 GtkWidget *win = NULL; 2070 GtkWidget *win = NULL;
2517 2071
@@ -2616,10 +2170,7 @@ BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
2616 2170
2617 beforeDialog(); 2171 beforeDialog();
2618 2172
2619 if (ll_try_gtk_init() 2173 if (ll_try_gtk_init())
2620 // We can NOT expect to combine GTK and SDL's aggressive fullscreen
2621 && !was_fullscreen
2622 )
2623 { 2174 {
2624 GtkWidget *win = NULL; 2175 GtkWidget *win = NULL;
2625 2176
@@ -2802,7 +2353,7 @@ void LLWindowSDL::bringToFront()
2802} 2353}
2803 2354
2804//static 2355//static
2805std::string LLWindowSDL::getFontListSans() 2356std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
2806{ 2357{
2807 // Use libfontconfig to find us a nice ordered list of fallback fonts 2358 // Use libfontconfig to find us a nice ordered list of fallback fonts
2808 // specific to this system. 2359 // specific to this system.
@@ -2819,7 +2370,7 @@ std::string LLWindowSDL::getFontListSans()
2819 // renderable range if for some reason our FreeType actually fails 2370 // renderable range if for some reason our FreeType actually fails
2820 // to use some of the fonts we want it to. 2371 // to use some of the fonts we want it to.
2821 const bool elide_unicode_coverage = true; 2372 const bool elide_unicode_coverage = true;
2822 std::string rtn; 2373 std::vector<std::string> rtns;
2823 FcFontSet *fs = NULL; 2374 FcFontSet *fs = NULL;
2824 FcPattern *sortpat = NULL; 2375 FcPattern *sortpat = NULL;
2825 int font_count = 0; 2376 int font_count = 0;
@@ -2853,7 +2404,8 @@ std::string LLWindowSDL::getFontListSans()
2853 if (!FcInit()) 2404 if (!FcInit())
2854 { 2405 {
2855 llwarns << "FontConfig failed to initialize." << llendl; 2406 llwarns << "FontConfig failed to initialize." << llendl;
2856 return final_fallback; 2407 rtns.push_back(final_fallback);
2408 return rtns;
2857 } 2409 }
2858 2410
2859 sortpat = FcNameParse((FcChar8*) sort_order.c_str()); 2411 sortpat = FcNameParse((FcChar8*) sort_order.c_str());
@@ -2878,17 +2430,24 @@ std::string LLWindowSDL::getFontListSans()
2878 &filename) 2430 &filename)
2879 && filename) 2431 && filename)
2880 { 2432 {
2881 rtn += std::string((const char*)filename)+";"; 2433 rtns.push_back(std::string((const char*)filename));
2882 ++font_count; 2434 ++font_count;
2883 } 2435 }
2884 } 2436 }
2885 FcFontSetDestroy (fs); 2437 FcFontSetDestroy (fs);
2886 } 2438 }
2887 2439
2888 lldebugs << "Using font list: " << rtn << llendl; 2440 lldebugs << "Using font list: " << llendl;
2441 for (std::vector<std::string>::iterator it = rtns.begin();
2442 it != rtns.end();
2443 ++it)
2444 {
2445 lldebugs << " file: " << *it << llendl;
2446 }
2889 llinfos << "Using " << font_count << " system font(s)." << llendl; 2447 llinfos << "Using " << font_count << " system font(s)." << llendl;
2890 2448
2891 return rtn + final_fallback; 2449 rtns.push_back(final_fallback);
2450 return rtns;
2892} 2451}
2893 2452
2894#endif // LL_SDL 2453#endif // LL_SDL