aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llwindow/llwindowsdl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llwindow/llwindowsdl.cpp')
-rw-r--r--linden/indra/llwindow/llwindowsdl.cpp376
1 files changed, 261 insertions, 115 deletions
diff --git a/linden/indra/llwindow/llwindowsdl.cpp b/linden/indra/llwindow/llwindowsdl.cpp
index a94284e..85836af 100644
--- a/linden/indra/llwindow/llwindowsdl.cpp
+++ b/linden/indra/llwindow/llwindowsdl.cpp
@@ -68,20 +68,12 @@ const S32 MAX_NUM_RESOLUTIONS = 32;
68 68
69#if LL_X11 69#if LL_X11
70# include <X11/Xutil.h> 70# include <X11/Xutil.h>
71// A global! Well, SDL isn't really designed for communicating
72// with multiple physical X11 displays. Heck, it's not really
73// designed for multiple X11 windows.
74// So, we need this for the SDL/X11 event filter callback (which
75// doesnt have a userdata parameter) and more.
76static Display *SDL_Display = NULL;
77static Window SDL_XWindowID = None;
78#endif //LL_X11 71#endif //LL_X11
79 72
80// TOFU HACK -- (*exactly* the same hack as LLWindowMacOSX for the same reasons) 73// TOFU HACK -- (*exactly* the same hack as LLWindowMacOSX for a similar
81// For SDL, to put up an OS dialog in full screen mode, we must first switch OUT of full screen mode. 74// set of reasons): Stash a pointer to the LLWindowSDL object here and
82// The proper way to do this is to bracket the dialog with calls to beforeDialog() and afterDialog(), but these 75// maintain in the constructor and destructor. This assumes that there will
83// require a pointer to the LLWindowMacSDL object. Stash it here and maintain in the constructor and destructor. 76// be only one object of this class at any time. Hopefully this is true.
84// This assumes that there will be only one object of this class at any time. Hopefully this is true.
85static LLWindowSDL *gWindowImplementation = NULL; 77static LLWindowSDL *gWindowImplementation = NULL;
86 78
87static BOOL was_fullscreen = FALSE; 79static BOOL was_fullscreen = FALSE;
@@ -113,14 +105,51 @@ void show_window_creation_error(const char* title)
113} 105}
114 106
115 107
108void maybe_lock_display(void)
109{
110 if (gWindowImplementation) {
111 gWindowImplementation->Lock_Display();
112 }
113}
114
115
116void maybe_unlock_display(void)
117{
118 if (gWindowImplementation) {
119 gWindowImplementation->Unlock_Display();
120 }
121}
122
123
116#if LL_GTK 124#if LL_GTK
117// Check the runtime GTK version for goodness. 125// Lazily initialize and check the runtime GTK version for goodness.
118static BOOL maybe_do_gtk_diagnostics(void) 126BOOL ll_try_gtk_init(void)
119{ 127{
120 static BOOL done_gtk_diag = FALSE; 128 static BOOL done_gtk_diag = FALSE;
121 static BOOL is_good = TRUE; 129 static BOOL gtk_is_good = FALSE;
122 gtk_disable_setlocale(); 130 static BOOL done_setlocale = FALSE;
123 if ((!done_gtk_diag) && gtk_init_check(NULL, NULL)) 131 static BOOL tried_gtk_init = FALSE;
132
133 if (!done_setlocale)
134 {
135 llinfos << "Starting GTK Initialization." << llendl;
136 maybe_lock_display();
137 gtk_disable_setlocale();
138 maybe_unlock_display();
139 done_setlocale = TRUE;
140 }
141
142 if (!tried_gtk_init)
143 {
144 tried_gtk_init = TRUE;
145 maybe_lock_display();
146 gtk_is_good = gtk_init_check(NULL, NULL);
147 maybe_unlock_display();
148 if (!gtk_is_good)
149 llwarns << "GTK Initialization failed." << llendl;
150 }
151
152 if (gtk_is_good && !done_gtk_diag)
124 { 153 {
125 llinfos << "GTK Initialized." << llendl; 154 llinfos << "GTK Initialized." << llendl;
126 llinfos << "- Compiled against GTK version " 155 llinfos << "- Compiled against GTK version "
@@ -132,29 +161,51 @@ static BOOL maybe_do_gtk_diagnostics(void)
132 << gtk_minor_version << "." 161 << gtk_minor_version << "."
133 << gtk_micro_version << llendl; 162 << gtk_micro_version << llendl;
134 gchar *gtk_warning; 163 gchar *gtk_warning;
164 maybe_lock_display();
135 gtk_warning = gtk_check_version(GTK_MAJOR_VERSION, 165 gtk_warning = gtk_check_version(GTK_MAJOR_VERSION,
136 GTK_MINOR_VERSION, 166 GTK_MINOR_VERSION,
137 GTK_MICRO_VERSION); 167 GTK_MICRO_VERSION);
168 maybe_unlock_display();
138 if (gtk_warning) 169 if (gtk_warning)
139 { 170 {
140 llwarns << "- GTK COMPATIBILITY WARNING: " << 171 llwarns << "- GTK COMPATIBILITY WARNING: " <<
141 gtk_warning << llendl; 172 gtk_warning << llendl;
142 is_good = FALSE; 173 gtk_is_good = FALSE;
143 } 174 }
144 175
145 done_gtk_diag = TRUE; 176 done_gtk_diag = TRUE;
146 } 177 }
147 return is_good; 178
179 return gtk_is_good;
148} 180}
149#endif // LL_GTK 181#endif // LL_GTK
150 182
151 183
184#if LL_X11
185Window get_SDL_XWindowID(void)
186{
187 if (gWindowImplementation) {
188 return gWindowImplementation->mSDL_XWindowID;
189 }
190 return None;
191}
192
193Display* get_SDL_Display(void)
194{
195 if (gWindowImplementation) {
196 return gWindowImplementation->mSDL_Display;
197 }
198 return NULL;
199}
200#endif // LL_X11
201
202
152BOOL check_for_card(const char* RENDERER, const char* bad_card) 203BOOL check_for_card(const char* RENDERER, const char* bad_card)
153{ 204{
154 if (!strncasecmp(RENDERER, bad_card, strlen(bad_card))) 205 if (!strncasecmp(RENDERER, bad_card, strlen(bad_card)))
155 { 206 {
156 char buffer[1024]; 207 char buffer[1024]; /* Flawfinder: ignore */
157 sprintf(buffer, 208 snprintf(buffer, sizeof(buffer), /* Flawfinder: ignore */
158 "Your video card appears to be a %s, which Second Life does not support.\n" 209 "Your video card appears to be a %s, which Second Life does not support.\n"
159 "\n" 210 "\n"
160 "Second Life requires a video card with 32 Mb of memory or more, as well as\n" 211 "Second Life requires a video card with 32 Mb of memory or more, as well as\n"
@@ -209,6 +260,19 @@ LLWindowSDL::LLWindowSDL(char *title, S32 x, S32 y, S32 width,
209 mHaveInputFocus = -1; 260 mHaveInputFocus = -1;
210 mIsMinimized = -1; 261 mIsMinimized = -1;
211 262
263#if LL_X11
264 mSDL_XWindowID = None;
265 mSDL_Display = NULL;
266#endif // LL_X11
267
268#if LL_GTK
269 // We MUST be the first to initialize GTK, i.e. we have to beat
270 // our embedded Mozilla to the punch so that GTK doesn't get badly
271 // initialized with a non-C locale and cause lots of serious random
272 // weirdness.
273 ll_try_gtk_init();
274#endif // LL_GTK
275
212 // Get the original aspect ratio of the main device. 276 // Get the original aspect ratio of the main device.
213 mOriginalAspectRatio = 1024.0 / 768.0; // !!! FIXME //(double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay); 277 mOriginalAspectRatio = 1024.0 / 768.0; // !!! FIXME //(double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay);
214 278
@@ -216,9 +280,14 @@ LLWindowSDL::LLWindowSDL(char *title, S32 x, S32 y, S32 width,
216 title = "SDL Window"; // *FIX: (???) 280 title = "SDL Window"; // *FIX: (???)
217 281
218 // Stash the window title 282 // Stash the window title
219 mWindowTitle = new char[strlen(title) + 1]; 283 mWindowTitle = new char[strlen(title) + 1]; /* Flawfinder: ignore */
220 strcpy(mWindowTitle, title); 284 if(mWindowTitle == NULL)
285 {
286 llerrs << "Memory allocation failure" << llendl;
287 return;
288 }
221 289
290 strcpy(mWindowTitle, title); /* Flawfinder: ignore */
222 // Create the GL context and set it up for windowed or fullscreen, as appropriate. 291 // Create the GL context and set it up for windowed or fullscreen, as appropriate.
223 if(createContext(x, y, width, height, 32, fullscreen, disable_vsync)) 292 if(createContext(x, y, width, height, 32, fullscreen, disable_vsync))
224 { 293 {
@@ -242,10 +311,10 @@ LLWindowSDL::LLWindowSDL(char *title, S32 x, S32 y, S32 width,
242static SDL_Surface *Load_BMP_Resource(const char *basename) 311static SDL_Surface *Load_BMP_Resource(const char *basename)
243{ 312{
244 const int PATH_BUFFER_SIZE=1000; 313 const int PATH_BUFFER_SIZE=1000;
245 char path_buffer[PATH_BUFFER_SIZE]; 314 char path_buffer[PATH_BUFFER_SIZE]; /* Flawfinder: ignore */
246 315
247 // Figure out where our BMP is living on the disk 316 // Figure out where our BMP is living on the disk
248 snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s", 317 snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s", /* Flawfinder: ignore */
249 gDirUtilp->getAppRODataDir().c_str(), 318 gDirUtilp->getAppRODataDir().c_str(),
250 gDirUtilp->getDirDelimiter().c_str(), 319 gDirUtilp->getDirDelimiter().c_str(),
251 gDirUtilp->getDirDelimiter().c_str(), 320 gDirUtilp->getDirDelimiter().c_str(),
@@ -271,7 +340,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
271 { 340 {
272 llinfos << "sdl_init() failed! " << SDL_GetError() << llendl; 341 llinfos << "sdl_init() failed! " << SDL_GetError() << llendl;
273 setupFailure("window creation error", "error", OSMB_OK); 342 setupFailure("window creation error", "error", OSMB_OK);
274 return false; 343 return false;
275 } 344 }
276 345
277 SDL_version c_sdl_version; 346 SDL_version c_sdl_version;
@@ -415,8 +484,8 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
415 mFullscreenBits = -1; 484 mFullscreenBits = -1;
416 mFullscreenRefresh = -1; 485 mFullscreenRefresh = -1;
417 486
418 char error[256]; 487 char error[256]; /* Flawfinder: ignore */
419 sprintf(error, "Unable to run fullscreen at %d x %d.\nRunning in window.", width, height); 488 snprintf(error, sizeof(error), "Unable to run fullscreen at %d x %d.\nRunning in window.", width, height); /* Flawfinder: ignore */
420 OSMessageBox(error, "Error", OSMB_OK); 489 OSMessageBox(error, "Error", OSMB_OK);
421 } 490 }
422 } 491 }
@@ -948,24 +1017,29 @@ void LLWindowSDL::beforeDialog()
948 } 1017 }
949 1018
950#if LL_X11 1019#if LL_X11
951 if (SDL_Display) 1020 if (mSDL_Display)
952 { 1021 {
953 // Everything that we/SDL asked for should happen before we 1022 // Everything that we/SDL asked for should happen before we
954 // potentially hand control over to GTK. 1023 // potentially hand control over to GTK.
955 XSync(SDL_Display, False); 1024 XSync(mSDL_Display, False);
956 } 1025 }
957#endif // LL_X11 1026#endif // LL_X11
958 1027
959#if LL_GTK 1028#if LL_GTK
960 // this is a good time to grab some GTK version information for 1029 // this is a good time to grab some GTK version information for
961 // diagnostics 1030 // diagnostics, if not already done.
962 maybe_do_gtk_diagnostics(); 1031 ll_try_gtk_init();
963#endif // LL_GTK 1032#endif // LL_GTK
1033
1034 maybe_lock_display();
964} 1035}
965 1036
966void LLWindowSDL::afterDialog() 1037void LLWindowSDL::afterDialog()
967{ 1038{
968 llinfos << "LLWindowSDL::afterDialog()" << llendl; 1039 llinfos << "LLWindowSDL::afterDialog()" << llendl;
1040
1041 maybe_unlock_display();
1042
969 if (old_fullscreen && !was_fullscreen) 1043 if (old_fullscreen && !was_fullscreen)
970 { 1044 {
971 // *FIX: NOT YET WORKING (see below) 1045 // *FIX: NOT YET WORKING (see below)
@@ -985,13 +1059,13 @@ S32 LLWindowSDL::stat(const char* file_name, struct stat* stat_info)
985// set/reset the XWMHints flag for 'urgency' that usually makes the icon flash 1059// set/reset the XWMHints flag for 'urgency' that usually makes the icon flash
986void LLWindowSDL::x11_set_urgent(BOOL urgent) 1060void LLWindowSDL::x11_set_urgent(BOOL urgent)
987{ 1061{
988 if (SDL_Display && !mFullscreen) 1062 if (mSDL_Display && !mFullscreen)
989 { 1063 {
990 XWMHints *wm_hints; 1064 XWMHints *wm_hints;
991 1065
992 llinfos << "X11 hint for urgency, " << urgent << llendl; 1066 llinfos << "X11 hint for urgency, " << urgent << llendl;
993 1067
994 wm_hints = XGetWMHints(SDL_Display, mSDL_XWindowID); 1068 wm_hints = XGetWMHints(mSDL_Display, mSDL_XWindowID);
995 if (!wm_hints) 1069 if (!wm_hints)
996 wm_hints = XAllocWMHints(); 1070 wm_hints = XAllocWMHints();
997 1071
@@ -1000,9 +1074,9 @@ void LLWindowSDL::x11_set_urgent(BOOL urgent)
1000 else 1074 else
1001 wm_hints->flags &= ~XUrgencyHint; 1075 wm_hints->flags &= ~XUrgencyHint;
1002 1076
1003 XSetWMHints(SDL_Display, mSDL_XWindowID, wm_hints); 1077 XSetWMHints(mSDL_Display, mSDL_XWindowID, wm_hints);
1004 XFree(wm_hints); 1078 XFree(wm_hints);
1005 XSync(SDL_Display, False); 1079 XSync(mSDL_Display, False);
1006 } 1080 }
1007} 1081}
1008#endif // LL_X11 1082#endif // LL_X11
@@ -1035,6 +1109,8 @@ void LLWindowSDL::flashIcon(F32 seconds)
1035 right now it has the rare and desirable trait of being 1109 right now it has the rare and desirable trait of being
1036 generally stable and working. */ 1110 generally stable and working. */
1037 1111
1112typedef Atom x11clipboard_type;
1113
1038/* PRIMARY and CLIPBOARD are the two main kinds of 1114/* PRIMARY and CLIPBOARD are the two main kinds of
1039 X11 clipboard. A third are the CUT_BUFFERs which an 1115 X11 clipboard. A third are the CUT_BUFFERs which an
1040 obsolete holdover from X10 days and use a quite orthogonal 1116 obsolete holdover from X10 days and use a quite orthogonal
@@ -1047,26 +1123,52 @@ void LLWindowSDL::flashIcon(F32 seconds)
1047 we support (to as full an extent as the clipboard content type 1123 we support (to as full an extent as the clipboard content type
1048 allows) CLIPBOARD, PRIMARY, and CUT_BUFFER0. 1124 allows) CLIPBOARD, PRIMARY, and CUT_BUFFER0.
1049 */ 1125 */
1050#define SL_READWRITE_XCLIPBOARD_TYPE XInternAtom(SDL_Display, "CLIPBOARD", False) 1126static x11clipboard_type get_x11_readwrite_clipboard_type(void)
1051#define SL_WRITE_XCLIPBOARD_TYPE XA_PRIMARY 1127{
1128 return XInternAtom(get_SDL_Display(), "CLIPBOARD", False);
1129}
1130
1131static x11clipboard_type get_x11_write_clipboard_type(void)
1132{
1133 return XA_PRIMARY;
1134}
1052 1135
1053/* This is where our own private cutbuffer goes - we don't use 1136/* This is where our own private cutbuffer goes - we don't use
1054 a regular cutbuffer (XA_CUT_BUFFER0 etc) for intermediate 1137 a regular cutbuffer (XA_CUT_BUFFER0 etc) for intermediate
1055 storage because their use isn't really defined for holding UTF8. */ 1138 storage because their use isn't really defined for holding UTF8. */
1056#define SL_CUTBUFFER_TYPE XInternAtom(SDL_Display, "SECONDLIFE_CUTBUFFER", False) 1139static x11clipboard_type get_x11_cutbuffer_clipboard_type(void)
1140{
1141 return XInternAtom(get_SDL_Display(), "SECONDLIFE_CUTBUFFER", False);
1142}
1143
1144/* Some X11 atom-generators */
1145static Atom get_x11_targets_atom(void)
1146{
1147 return XInternAtom(get_SDL_Display(), "TARGETS", False);
1148}
1149
1150static Atom get_x11_text_atom(void)
1151{
1152 return XInternAtom(get_SDL_Display(), "TEXT", False);
1153}
1057 1154
1058/* These defines, and convert_data/convert_x11clipboard, 1155/* These defines, and convert_data/convert_x11clipboard,
1059 mostly exist to support non-text or unusually-encoded 1156 mostly exist to support non-text or unusually-encoded
1060 clipboard data, which we don't really have a need for at 1157 clipboard data, which we don't really have a need for at
1061 the moment. */ 1158 the moment. */
1062#define SDLCLIPTYPE(A, B, C, D) (int)((A<<24)|(B<<16)|(C<<8)|(D<<0)) 1159#define SDLCLIPTYPE(A, B, C, D) (int)(((A)<<24)|((B)<<16)|((C)<<8)|((D)<<0))
1063#define FORMAT_PREFIX "SECONDLIFE_x11clipboard_0x" 1160#define FORMAT_PREFIX "SECONDLIFE_x11clipboard_0x"
1064 1161
1065typedef Atom x11clipboard_type;
1066
1067static 1162static
1068x11clipboard_type convert_format(int type) 1163x11clipboard_type convert_format(int type)
1069{ 1164{
1165 if (!gWindowImplementation)
1166 {
1167 llwarns << "!gWindowImplementation in convert_format()"
1168 << llendl;
1169 return XA_STRING;
1170 }
1171
1070 switch (type) 1172 switch (type)
1071 { 1173 {
1072 case SDLCLIPTYPE('T', 'E', 'X', 'T'): 1174 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
@@ -1074,15 +1176,17 @@ x11clipboard_type convert_format(int type)
1074 return XA_STRING; 1176 return XA_STRING;
1075 case SDLCLIPTYPE('U', 'T', 'F', '8'): 1177 case SDLCLIPTYPE('U', 'T', 'F', '8'):
1076 // newer de-facto UTF8 clipboard atom 1178 // newer de-facto UTF8 clipboard atom
1077 return XInternAtom(SDL_Display, "UTF8_STRING", False); 1179 return XInternAtom(gWindowImplementation->mSDL_Display,
1180 "UTF8_STRING", False);
1078 default: 1181 default:
1079 { 1182 {
1080 /* completely arbitrary clipboard types... we don't actually use 1183 /* completely arbitrary clipboard types... we don't actually use
1081 these right now, and support is skeletal. */ 1184 these right now, and support is skeletal. */
1082 char format[sizeof(FORMAT_PREFIX)+8+1]; 1185 char format[sizeof(FORMAT_PREFIX)+8+1]; /* Flawfinder: ignore */
1083 1186
1084 sprintf(format, "%s%08lx", FORMAT_PREFIX, (unsigned long)type); 1187 snprintf(format, sizeof(format), "%s%08lx", FORMAT_PREFIX, (unsigned long)type); /* Flawfinder: ignore */
1085 return XInternAtom(SDL_Display, format, False); 1188 return XInternAtom(gWindowImplementation->mSDL_Display,
1189 format, False);
1086 } 1190 }
1087 } 1191 }
1088} 1192}
@@ -1099,14 +1203,18 @@ convert_data(int type, char *dst, const char *src, int srclen)
1099 { 1203 {
1100 case SDLCLIPTYPE('T', 'E', 'X', 'T'): 1204 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
1101 case SDLCLIPTYPE('U', 'T', 'F', '8'): 1205 case SDLCLIPTYPE('U', 'T', 'F', '8'):
1206 if (src == NULL)
1207 {
1208 break;
1209 }
1102 if ( srclen == 0 ) 1210 if ( srclen == 0 )
1103 srclen = strlen(src); 1211 srclen = strlen(src); /* Flawfinder: ignore */
1104 1212
1105 dstlen = srclen + 1; 1213 dstlen = srclen + 1;
1106 1214
1107 if ( dst ) // assume caller made it big enough by asking us 1215 if ( dst ) // assume caller made it big enough by asking us
1108 { 1216 {
1109 memcpy(dst, src, srclen); 1217 memcpy(dst, src, srclen); /* Flawfinder: ignore */
1110 dst[srclen] = '\0'; 1218 dst[srclen] = '\0';
1111 } 1219 }
1112 break; 1220 break;
@@ -1131,14 +1239,18 @@ convert_x11clipboard(int type, char *dst, const char *src, int srclen)
1131 { 1239 {
1132 case SDLCLIPTYPE('U', 'T', 'F', '8'): 1240 case SDLCLIPTYPE('U', 'T', 'F', '8'):
1133 case SDLCLIPTYPE('T', 'E', 'X', 'T'): 1241 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
1242 if (src == NULL)
1243 {
1244 break;
1245 }
1134 if ( srclen == 0 ) 1246 if ( srclen == 0 )
1135 srclen = strlen(src); 1247 srclen = strlen(src); /* Flawfinder: ignore */
1136 1248
1137 dstlen = srclen + 1; 1249 dstlen = srclen + 1;
1138 1250
1139 if ( dst ) // assume caller made it big enough by asking us 1251 if ( dst ) // assume caller made it big enough by asking us
1140 { 1252 {
1141 memcpy(dst, src, srclen); 1253 memcpy(dst, src, srclen); /* Flawfinder: ignore */
1142 dst[srclen] = '\0'; 1254 dst[srclen] = '\0';
1143 } 1255 }
1144 break; 1256 break;
@@ -1155,9 +1267,9 @@ LLWindowSDL::is_empty_x11clipboard(void)
1155{ 1267{
1156 int retval; 1268 int retval;
1157 1269
1158 Lock_Display(); 1270 maybe_lock_display();
1159 retval = ( XGetSelectionOwner(SDL_Display, SL_READWRITE_XCLIPBOARD_TYPE) == None ); 1271 retval = ( XGetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type()) == None );
1160 Unlock_Display(); 1272 maybe_unlock_display();
1161 1273
1162 return(retval); 1274 return(retval);
1163} 1275}
@@ -1175,8 +1287,8 @@ LLWindowSDL::put_x11clipboard(int type, int srclen, const char *src)
1175 dst = (char *)malloc(dstlen); 1287 dst = (char *)malloc(dstlen);
1176 if ( dst != NULL ) 1288 if ( dst != NULL )
1177 { 1289 {
1178 Window root = DefaultRootWindow(SDL_Display); 1290 maybe_lock_display();
1179 Lock_Display(); 1291 Window root = DefaultRootWindow(mSDL_Display);
1180 convert_data(type, dst, src, srclen); 1292 convert_data(type, dst, src, srclen);
1181 // Cutbuffers are only allowed to have STRING atom types, 1293 // Cutbuffers are only allowed to have STRING atom types,
1182 // but Emacs puts UTF8 inside them anyway. We cautiously 1294 // but Emacs puts UTF8 inside them anyway. We cautiously
@@ -1185,7 +1297,7 @@ LLWindowSDL::put_x11clipboard(int type, int srclen, const char *src)
1185 { 1297 {
1186 // dstlen-1 so we don't include the trailing \0 1298 // dstlen-1 so we don't include the trailing \0
1187 llinfos << "X11: Populating cutbuffer." <<llendl; 1299 llinfos << "X11: Populating cutbuffer." <<llendl;
1188 XChangeProperty(SDL_Display, root, 1300 XChangeProperty(mSDL_Display, root,
1189 XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace, 1301 XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace,
1190 (unsigned char*)dst, dstlen-1); 1302 (unsigned char*)dst, dstlen-1);
1191 } else { 1303 } else {
@@ -1194,18 +1306,18 @@ LLWindowSDL::put_x11clipboard(int type, int srclen, const char *src)
1194 //XDeleteProperty(SDL_Display, root, XA_CUT_BUFFER0); 1306 //XDeleteProperty(SDL_Display, root, XA_CUT_BUFFER0);
1195 } 1307 }
1196 // Private cutbuffer of an appropriate type. 1308 // Private cutbuffer of an appropriate type.
1197 XChangeProperty(SDL_Display, root, 1309 XChangeProperty(mSDL_Display, root,
1198 SL_CUTBUFFER_TYPE, format, 8, PropModeReplace, 1310 get_x11_cutbuffer_clipboard_type(), format, 8, PropModeReplace,
1199 (unsigned char*)dst, dstlen-1); 1311 (unsigned char*)dst, dstlen-1);
1200 free(dst); 1312 free(dst);
1201 1313
1202 /* Claim ownership of both PRIMARY and CLIPBOARD */ 1314 /* Claim ownership of both PRIMARY and CLIPBOARD */
1203 XSetSelectionOwner(SDL_Display, SL_READWRITE_XCLIPBOARD_TYPE, 1315 XSetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type(),
1204 mSDL_XWindowID, CurrentTime); 1316 mSDL_XWindowID, CurrentTime);
1205 XSetSelectionOwner(SDL_Display, SL_WRITE_XCLIPBOARD_TYPE, 1317 XSetSelectionOwner(mSDL_Display, get_x11_write_clipboard_type(),
1206 mSDL_XWindowID, CurrentTime); 1318 mSDL_XWindowID, CurrentTime);
1207 1319
1208 Unlock_Display(); 1320 maybe_unlock_display();
1209 } 1321 }
1210} 1322}
1211 1323
@@ -1225,19 +1337,19 @@ LLWindowSDL::get_x11clipboard(int type, int *dstlen, char **dst)
1225 unsigned long overflow; 1337 unsigned long overflow;
1226 char *src; 1338 char *src;
1227 1339
1228 Lock_Display(); 1340 maybe_lock_display();
1229 owner = XGetSelectionOwner(SDL_Display, SL_READWRITE_XCLIPBOARD_TYPE); 1341 owner = XGetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type());
1230 Unlock_Display(); 1342 maybe_unlock_display();
1231 if (owner == None) 1343 if (owner == None)
1232 { 1344 {
1233 // Fall right back to ancient X10 cut-buffers 1345 // Fall right back to ancient X10 cut-buffers
1234 owner = DefaultRootWindow(SDL_Display); 1346 owner = DefaultRootWindow(mSDL_Display);
1235 selection = XA_CUT_BUFFER0; 1347 selection = XA_CUT_BUFFER0;
1236 } else if (owner == mSDL_XWindowID) 1348 } else if (owner == mSDL_XWindowID)
1237 { 1349 {
1238 // Use our own uncooked opaque string property 1350 // Use our own uncooked opaque string property
1239 owner = DefaultRootWindow(SDL_Display); 1351 owner = DefaultRootWindow(mSDL_Display);
1240 selection = SL_CUTBUFFER_TYPE; 1352 selection = get_x11_cutbuffer_clipboard_type();
1241 } 1353 }
1242 else 1354 else
1243 { 1355 {
@@ -1246,11 +1358,11 @@ LLWindowSDL::get_x11clipboard(int type, int *dstlen, char **dst)
1246 SDL_Event event; 1358 SDL_Event event;
1247 1359
1248 owner = mSDL_XWindowID; 1360 owner = mSDL_XWindowID;
1249 Lock_Display(); 1361 maybe_lock_display();
1250 selection = XInternAtom(SDL_Display, "SDL_SELECTION", False); 1362 selection = XInternAtom(mSDL_Display, "SDL_SELECTION", False);
1251 XConvertSelection(SDL_Display, SL_READWRITE_XCLIPBOARD_TYPE, format, 1363 XConvertSelection(mSDL_Display, get_x11_readwrite_clipboard_type(), format,
1252 selection, owner, CurrentTime); 1364 selection, owner, CurrentTime);
1253 Unlock_Display(); 1365 maybe_unlock_display();
1254 llinfos << "X11: Waiting for clipboard to arrive." <<llendl; 1366 llinfos << "X11: Waiting for clipboard to arrive." <<llendl;
1255 while ( ! selection_response ) 1367 while ( ! selection_response )
1256 { 1368 {
@@ -1276,8 +1388,8 @@ LLWindowSDL::get_x11clipboard(int type, int *dstlen, char **dst)
1276 llinfos << "X11: Clipboard arrived." <<llendl; 1388 llinfos << "X11: Clipboard arrived." <<llendl;
1277 } 1389 }
1278 1390
1279 Lock_Display(); 1391 maybe_lock_display();
1280 if ( XGetWindowProperty(SDL_Display, owner, selection, 0, INT_MAX/4, 1392 if ( XGetWindowProperty(mSDL_Display, owner, selection, 0, INT_MAX/4,
1281 False, format, &seln_type, &seln_format, 1393 False, format, &seln_type, &seln_format,
1282 &nbytes, &overflow, (unsigned char **)&src) == Success ) 1394 &nbytes, &overflow, (unsigned char **)&src) == Success )
1283 { 1395 {
@@ -1292,8 +1404,7 @@ LLWindowSDL::get_x11clipboard(int type, int *dstlen, char **dst)
1292 } 1404 }
1293 XFree(src); 1405 XFree(src);
1294 } 1406 }
1295 1407 maybe_unlock_display();
1296 Unlock_Display();
1297} 1408}
1298 1409
1299int clipboard_filter_callback(const SDL_Event *event) 1410int clipboard_filter_callback(const SDL_Event *event)
@@ -1306,7 +1417,7 @@ int clipboard_filter_callback(const SDL_Event *event)
1306 1417
1307 /* Handle window-manager specific clipboard events */ 1418 /* Handle window-manager specific clipboard events */
1308 switch (event->syswm.msg->event.xevent.type) { 1419 switch (event->syswm.msg->event.xevent.type) {
1309 /* Copy the selection from SL_CUTBUFFER_TYPE to the requested property */ 1420 /* Copy the selection from SECONDLIFE_CUTBUFFER to the requested property */
1310 case SelectionRequest: { 1421 case SelectionRequest: {
1311 XSelectionRequestEvent *req; 1422 XSelectionRequestEvent *req;
1312 XEvent sevent; 1423 XEvent sevent;
@@ -1323,8 +1434,8 @@ int clipboard_filter_callback(const SDL_Event *event)
1323 sevent.xselection.property = None; 1434 sevent.xselection.property = None;
1324 sevent.xselection.requestor = req->requestor; 1435 sevent.xselection.requestor = req->requestor;
1325 sevent.xselection.time = req->time; 1436 sevent.xselection.time = req->time;
1326 if ( XGetWindowProperty(SDL_Display, DefaultRootWindow(SDL_Display), 1437 if ( XGetWindowProperty(get_SDL_Display(), DefaultRootWindow(get_SDL_Display()),
1327 SL_CUTBUFFER_TYPE, 0, INT_MAX/4, False, req->target, 1438 get_x11_cutbuffer_clipboard_type(), 0, INT_MAX/4, False, req->target,
1328 &sevent.xselection.target, &seln_format, 1439 &sevent.xselection.target, &seln_format,
1329 &nbytes, &overflow, &seln_data) == Success ) 1440 &nbytes, &overflow, &seln_data) == Success )
1330 { 1441 {
@@ -1337,21 +1448,20 @@ int clipboard_filter_callback(const SDL_Event *event)
1337 if ( seln_data[nbytes-1] == '\0' ) 1448 if ( seln_data[nbytes-1] == '\0' )
1338 --nbytes; 1449 --nbytes;
1339 } 1450 }
1340 XChangeProperty(SDL_Display, req->requestor, req->property, 1451 XChangeProperty(get_SDL_Display(), req->requestor, req->property,
1341 req->target, seln_format, PropModeReplace, 1452 req->target, seln_format, PropModeReplace,
1342 seln_data, nbytes); 1453 seln_data, nbytes);
1343 sevent.xselection.property = req->property; 1454 sevent.xselection.property = req->property;
1344#define XA_TARGETS XInternAtom(SDL_Display, "TARGETS", False) 1455 } else if (get_x11_targets_atom() == req->target) {
1345 } else if (XA_TARGETS == req->target) {
1346 /* only advertise what we currently support */ 1456 /* only advertise what we currently support */
1347 const int num_supported = 3; 1457 const int num_supported = 3;
1348 Atom supported[num_supported] = { 1458 Atom supported[num_supported] = {
1349 XA_STRING, // will be over-written below 1459 XA_STRING, // will be over-written below
1350 XInternAtom(SDL_Display, "TEXT",False), 1460 get_x11_text_atom(),
1351 XA_TARGETS 1461 get_x11_targets_atom()
1352 }; 1462 };
1353 supported[0] = sevent.xselection.target; 1463 supported[0] = sevent.xselection.target;
1354 XChangeProperty(SDL_Display, req->requestor, 1464 XChangeProperty(get_SDL_Display(), req->requestor,
1355 req->property, XA_ATOM, 32, PropModeReplace, 1465 req->property, XA_ATOM, 32, PropModeReplace,
1356 (unsigned char*)supported, 1466 (unsigned char*)supported,
1357 num_supported); 1467 num_supported);
@@ -1364,10 +1474,10 @@ int clipboard_filter_callback(const SDL_Event *event)
1364 XFree(seln_data); 1474 XFree(seln_data);
1365 } 1475 }
1366 int sendret = 1476 int sendret =
1367 XSendEvent(SDL_Display,req->requestor,False,0,&sevent); 1477 XSendEvent(get_SDL_Display(),req->requestor,False,0,&sevent);
1368 if ((sendret==BadValue) || (sendret==BadWindow)) 1478 if ((sendret==BadValue) || (sendret==BadWindow))
1369 llwarns << "Clipboard SendEvent failed" << llendl; 1479 llwarns << "Clipboard SendEvent failed" << llendl;
1370 XSync(SDL_Display, False); 1480 XSync(get_SDL_Display(), False);
1371 } 1481 }
1372 break; 1482 break;
1373 } 1483 }
@@ -1392,8 +1502,7 @@ LLWindowSDL::init_x11clipboard(void)
1392 /* Save the information for later use */ 1502 /* Save the information for later use */
1393 if ( info.subsystem == SDL_SYSWM_X11 ) 1503 if ( info.subsystem == SDL_SYSWM_X11 )
1394 { 1504 {
1395 SDL_Display = info.info.x11.display; 1505 mSDL_Display = info.info.x11.display;
1396 SDL_XWindowID = info.info.x11.wmwindow;
1397 mSDL_XWindowID = info.info.x11.wmwindow; 1506 mSDL_XWindowID = info.info.x11.wmwindow;
1398 Lock_Display = info.info.x11.lock_func; 1507 Lock_Display = info.info.x11.lock_func;
1399 Unlock_Display = info.info.x11.unlock_func; 1508 Unlock_Display = info.info.x11.unlock_func;
@@ -1415,8 +1524,7 @@ LLWindowSDL::init_x11clipboard(void)
1415void 1524void
1416LLWindowSDL::quit_x11clipboard(void) 1525LLWindowSDL::quit_x11clipboard(void)
1417{ 1526{
1418 SDL_Display = NULL; 1527 mSDL_Display = NULL;
1419 SDL_XWindowID = None;
1420 mSDL_XWindowID = None; 1528 mSDL_XWindowID = None;
1421 Lock_Display = NULL; 1529 Lock_Display = NULL;
1422 Unlock_Display = NULL; 1530 Unlock_Display = NULL;
@@ -1470,7 +1578,11 @@ BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
1470{ 1578{
1471 std::string utf8text = wstring_to_utf8str(s); 1579 std::string utf8text = wstring_to_utf8str(s);
1472 const char* cstr = utf8text.c_str(); 1580 const char* cstr = utf8text.c_str();
1473 int cstrlen = strlen(cstr); 1581 if (cstr == NULL)
1582 {
1583 return FALSE;
1584 }
1585 int cstrlen = strlen(cstr); /* Flawfinder: ignore */
1474 int i; 1586 int i;
1475 for (i=0; i<cstrlen; ++i) 1587 for (i=0; i<cstrlen; ++i)
1476 { 1588 {
@@ -1653,7 +1765,7 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
1653 if (!mFullscreen) /* only bother if we're windowed anyway */ 1765 if (!mFullscreen) /* only bother if we're windowed anyway */
1654 { 1766 {
1655#if LL_X11 1767#if LL_X11
1656 if (SDL_Display) 1768 if (mSDL_Display)
1657 { 1769 {
1658 /* we dirtily mix raw X11 with SDL so that our pointer 1770 /* we dirtily mix raw X11 with SDL so that our pointer
1659 isn't (as often) constrained to the limits of the 1771 isn't (as often) constrained to the limits of the
@@ -1669,7 +1781,7 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
1669 { 1781 {
1670 //llinfos << "X11 POINTER GRABBY" << llendl; 1782 //llinfos << "X11 POINTER GRABBY" << llendl;
1671 //newmode = SDL_WM_GrabInput(wantmode); 1783 //newmode = SDL_WM_GrabInput(wantmode);
1672 result = XGrabPointer(SDL_Display, mSDL_XWindowID, 1784 result = XGrabPointer(mSDL_Display, mSDL_XWindowID,
1673 True, 0, GrabModeAsync, 1785 True, 0, GrabModeAsync,
1674 GrabModeAsync, 1786 GrabModeAsync,
1675 None, None, CurrentTime); 1787 None, None, CurrentTime);
@@ -1683,9 +1795,9 @@ BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
1683 newmode = SDL_GRAB_OFF; 1795 newmode = SDL_GRAB_OFF;
1684 //newmode = SDL_WM_GrabInput(SDL_GRAB_OFF); 1796 //newmode = SDL_WM_GrabInput(SDL_GRAB_OFF);
1685 1797
1686 XUngrabPointer(SDL_Display, CurrentTime); 1798 XUngrabPointer(mSDL_Display, CurrentTime);
1687 // Make sure the ungrab happens RIGHT NOW. 1799 // Make sure the ungrab happens RIGHT NOW.
1688 XSync(SDL_Display, False); 1800 XSync(mSDL_Display, False);
1689 } else 1801 } else
1690 { 1802 {
1691 newmode = SDL_GRAB_QUERY; // neutral 1803 newmode = SDL_GRAB_QUERY; // neutral
@@ -1751,6 +1863,29 @@ void LLWindowSDL::gatherInput()
1751 static Uint32 lastRightDown = 0; 1863 static Uint32 lastRightDown = 0;
1752 SDL_Event event; 1864 SDL_Event event;
1753 1865
1866#if LL_GTK && LL_LIBXUL_ENABLED
1867 // Pump GTK events so embedded Gecko doesn't starve.
1868 if (ll_try_gtk_init())
1869 {
1870 // Yuck, Mozilla's GTK callbacks play with the locale - push/pop
1871 // the locale to protect it, as exotic/non-C locales
1872 // causes our code lots of general critical weirdness
1873 // and crashness. (SL-35450)
1874 char *saved_locale = setlocale(LC_ALL, NULL);
1875
1876 // Do a limited number of pumps so SL doesn't starve!
1877 // FIXME - this should ideally be time-limited, not count-limited.
1878 gtk_main_iteration_do(0); // Always do one non-blocking pump
1879 for (int iter=0; iter<10; ++iter)
1880 if (gtk_events_pending())
1881 gtk_main_iteration();
1882
1883 if (saved_locale)
1884 setlocale(LC_ALL, saved_locale);
1885 }
1886#endif // LL_GTK && LL_LIBXUL_ENABLED
1887
1888 // Handle all outstanding SDL events
1754 while (SDL_PollEvent(&event)) 1889 while (SDL_PollEvent(&event))
1755 { 1890 {
1756 switch (event.type) 1891 switch (event.type)
@@ -2237,15 +2372,12 @@ S32 OSMessageBoxSDL(const char* text, const char* caption, U32 type)
2237{ 2372{
2238 S32 rtn = OSBTN_CANCEL; 2373 S32 rtn = OSBTN_CANCEL;
2239 2374
2240#if LL_GTK 2375 ll_try_gtk_init();
2241 maybe_do_gtk_diagnostics();
2242#endif // LL_GTK
2243 2376
2244 if(gWindowImplementation != NULL) 2377 if(gWindowImplementation != NULL)
2245 gWindowImplementation->beforeDialog(); 2378 gWindowImplementation->beforeDialog();
2246 2379
2247 gtk_disable_setlocale(); 2380 if (ll_try_gtk_init()
2248 if (gtk_init_check(NULL, NULL)
2249 // We can NOT expect to combine GTK and SDL's aggressive fullscreen 2381 // We can NOT expect to combine GTK and SDL's aggressive fullscreen
2250 && ((NULL==gWindowImplementation) || (!was_fullscreen)) 2382 && ((NULL==gWindowImplementation) || (!was_fullscreen))
2251 ) 2383 )
@@ -2281,10 +2413,11 @@ S32 OSMessageBoxSDL(const char* text, const char* caption, U32 type)
2281 // Make GTK tell the window manager to associate this 2413 // Make GTK tell the window manager to associate this
2282 // dialog with our non-GTK SDL window, which should try 2414 // dialog with our non-GTK SDL window, which should try
2283 // to keep it on top etc. 2415 // to keep it on top etc.
2284 if (SDL_XWindowID != None) 2416 if (gWindowImplementation &&
2417 gWindowImplementation->mSDL_XWindowID != None)
2285 { 2418 {
2286 gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin 2419 gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
2287 GdkWindow *gdkwin = gdk_window_foreign_new(SDL_XWindowID); 2420 GdkWindow *gdkwin = gdk_window_foreign_new(gWindowImplementation->mSDL_XWindowID);
2288 gdk_window_set_transient_for(GTK_WIDGET(win)->window, 2421 gdk_window_set_transient_for(GTK_WIDGET(win)->window,
2289 gdkwin); 2422 gdkwin);
2290 } 2423 }
@@ -2353,8 +2486,7 @@ BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
2353 2486
2354 beforeDialog(); 2487 beforeDialog();
2355 2488
2356 gtk_disable_setlocale(); 2489 if (ll_try_gtk_init()
2357 if (gtk_init_check(NULL, NULL)
2358 // We can NOT expect to combine GTK and SDL's aggressive fullscreen 2490 // We can NOT expect to combine GTK and SDL's aggressive fullscreen
2359 && !was_fullscreen 2491 && !was_fullscreen
2360 ) 2492 )
@@ -2367,10 +2499,10 @@ BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
2367 // Get GTK to tell the window manager to associate this 2499 // Get GTK to tell the window manager to associate this
2368 // dialog with our non-GTK SDL window, which should try 2500 // dialog with our non-GTK SDL window, which should try
2369 // to keep it on top etc. 2501 // to keep it on top etc.
2370 if (SDL_XWindowID != None) 2502 if (mSDL_XWindowID != None)
2371 { 2503 {
2372 gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin 2504 gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
2373 GdkWindow *gdkwin = gdk_window_foreign_new(SDL_XWindowID); 2505 GdkWindow *gdkwin = gdk_window_foreign_new(mSDL_XWindowID);
2374 gdk_window_set_transient_for(GTK_WIDGET(win)->window, 2506 gdk_window_set_transient_for(GTK_WIDGET(win)->window,
2375 gdkwin); 2507 gdkwin);
2376 } 2508 }
@@ -2442,8 +2574,9 @@ void spawn_web_browser(const char* escaped_url)
2442 2574
2443#if LL_LINUX 2575#if LL_LINUX
2444# if LL_X11 2576# if LL_X11
2445 if (SDL_Display) // Just in case - before forking. 2577 if (gWindowImplementation &&
2446 XSync(SDL_Display, False); 2578 gWindowImplementation->mSDL_Display) // Just in case - before forking.
2579 XSync(gWindowImplementation->mSDL_Display, False);
2447# endif // LL_X11 2580# endif // LL_X11
2448 2581
2449 std::string cmd; 2582 std::string cmd;
@@ -2461,7 +2594,7 @@ void spawn_web_browser(const char* escaped_url)
2461 close(1); 2594 close(1);
2462 close(2); 2595 close(2);
2463 // end ourself by running the command 2596 // end ourself by running the command
2464 execv(cmd.c_str(), argv); 2597 execv(cmd.c_str(), argv); /* Flawfinder: ignore */
2465 // if execv returns at all, there was a problem. 2598 // if execv returns at all, there was a problem.
2466 llwarns << "execv failure when trying to start " << cmd << llendl; 2599 llwarns << "execv failure when trying to start " << cmd << llendl;
2467 _exit(1); // _exit because we don't want atexit() clean-up! 2600 _exit(1); // _exit because we don't want atexit() clean-up!
@@ -2488,13 +2621,26 @@ void shell_open( const char* file_path )
2488 2621
2489void *LLWindowSDL::getPlatformWindow() 2622void *LLWindowSDL::getPlatformWindow()
2490{ 2623{
2491#if LL_X11 2624#if LL_GTK && LL_LIBXUL_ENABLED
2492 // pointer to our static raw X window 2625 if (ll_try_gtk_init())
2493 return (void*)&SDL_XWindowID; 2626 {
2494#else 2627 GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2495 // doubt we really want to return a high-level SDL structure here. 2628
2629 // These hacks were attempts to get Gecko to see the keyboard,
2630 // but I think they're doomed to fail.
2631 //GdkWindow *gdkwin = gdk_window_foreign_new(SDL_XWindowID);
2632 //GTK_WIDGET(win)->window = gdkwin;
2633 //gtk_widget_set_parent_window(win, gdkwin);
2634
2635 // show the hidden-widget while debugging (needs mozlib change)
2636 //gtk_widget_show_all(GTK_WIDGET(win));
2637
2638 gtk_widget_realize(GTK_WIDGET(win));
2639 return win;
2640 }
2641#endif // LL_GTK && LL_LIBXUL_ENABLED
2642 // Unixoid mozilla really needs GTK.
2496 return NULL; 2643 return NULL;
2497#endif
2498} 2644}
2499 2645
2500void LLWindowSDL::bringToFront() 2646void LLWindowSDL::bringToFront()