diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llwindow/llwindowsdl.cpp | 767 |
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. |
84 | static LLWindowSDL *gWindowImplementation = NULL; | 86 | static LLWindowSDL *gWindowImplementation = NULL; |
85 | 87 | ||
86 | static BOOL was_fullscreen = FALSE; | ||
87 | |||
88 | 88 | ||
89 | void maybe_lock_display(void) | 89 | void 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 | ||
188 | LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width, | 190 | LLWindowSDL::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 |
275 | static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str) | 274 | static 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 | ||
322 | static int x11_detect_VRAM_kb() | 323 | static 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 | |||
761 | void LLWindowSDL::destroyContext() | 790 | void 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 | ||
938 | void LLWindowSDL::swapBuffers() | 976 | void LLWindowSDL::swapBuffers() |
@@ -982,11 +1020,7 @@ BOOL LLWindowSDL::isCursorHidden() | |||
982 | // Constrains the mouse to the window. | 1020 | // Constrains the mouse to the window. |
983 | void LLWindowSDL::setMouseClipping( BOOL b ) | 1021 | void 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 | ||
992 | BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position) | 1026 | BOOL 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 | ||
1027 | void 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 | ||
1055 | F32 LLWindowSDL::getNativeAspectRatio() | 1062 | F32 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. | ||
1113 | static LLCoordScreen old_size; | ||
1114 | static BOOL old_fullscreen; | ||
1115 | void LLWindowSDL::beforeDialog() | 1119 | void 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 | ||
1151 | void LLWindowSDL::afterDialog() | 1162 | void 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 | |||
1223 | typedef 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 | */ | ||
1237 | static x11clipboard_type get_x11_readwrite_clipboard_type(void) | ||
1238 | { | ||
1239 | return XInternAtom(LLWindowSDL::get_SDL_Display(), "CLIPBOARD", False); | ||
1240 | } | ||
1241 | |||
1242 | static 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. */ | ||
1250 | static 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 */ | ||
1256 | static Atom get_x11_targets_atom(void) | ||
1257 | { | ||
1258 | return XInternAtom(LLWindowSDL::get_SDL_Display(), "TARGETS", False); | ||
1259 | } | ||
1260 | |||
1261 | static 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 | |||
1273 | static | ||
1274 | x11clipboard_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. */ | ||
1307 | static int | ||
1308 | convert_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. */ | ||
1343 | static int | ||
1344 | convert_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 | |||
1376 | int | ||
1377 | LLWindowSDL::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 | ||
1388 | void | 1232 | #if LL_GTK |
1389 | LLWindowSDL::put_x11clipboard(int type, int srclen, const char *src) | 1233 | BOOL 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 | ||
1435 | void | 1245 | BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &text) |
1436 | LLWindowSDL::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 | |||
1521 | int 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 | ||
1600 | int | 1262 | BOOL LLWindowSDL::copyTextToClipboard(const LLWString &text) |
1601 | LLWindowSDL::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 | |||
1635 | void | ||
1636 | LLWindowSDL::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 | |||
1648 | BOOL LLWindowSDL::isClipboardTextAvailable() | ||
1649 | { | ||
1650 | return !is_empty_x11clipboard(); | ||
1651 | } | ||
1652 | |||
1653 | BOOL 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 | ||
1688 | BOOL 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 | ||
1715 | BOOL LLWindowSDL::isClipboardTextAvailable() | 1277 | BOOL 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 | ||
1731 | LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions) | 1293 | LLWindow::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 |
1964 | void LLWindowSDL::processMiscNativeEvents() | 1528 | void 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 | ||
1996 | void LLWindowSDL::gatherInput() | 1560 | void 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 | ||
2431 | void LLWindowSDL::showCursor() | 1990 | void 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 | ||
2448 | void LLWindowSDL::showCursorFromMouseMove() | 2005 | void 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 |
2805 | std::string LLWindowSDL::getFontListSans() | 2356 | std::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 |