llwindow.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 #include "llwindowheadless.h"
00034 
00035 #if LL_MESA_HEADLESS
00036 #include "llwindowmesaheadless.h"
00037 #elif LL_SDL
00038 #include "llwindowsdl.h"
00039 #elif LL_WINDOWS
00040 #include "llwindowwin32.h"
00041 #elif LL_DARWIN
00042 #include "llwindowmacosx.h"
00043 #elif LL_LINUX
00044 #include "llwindowlinux.h" // currently just a dummy wrapper
00045 #endif
00046 
00047 #include "llerror.h"
00048 #include "llkeyboard.h"
00049 #include "linked_lists.h"
00050 
00051 //static instance for default callbacks
00052 LLWindowCallbacks       LLWindow::sDefaultCallbacks;
00053 
00054 //
00055 // LLWindowCallbacks
00056 //
00057 
00058 LLSplashScreen *gSplashScreenp = NULL;
00059 BOOL gDebugClicks = FALSE;
00060 BOOL gDebugWindowProc = FALSE;
00061 
00062 const S32 gURLProtocolWhitelistCount = 3;
00063 const char* gURLProtocolWhitelist[] = { "file", "http", "https" };
00064 
00065 // CP: added a handler list - this is what's used to open the protocol and is based on registry entry
00066 //         only meaningful difference currently is that file: protocols are opened using http:
00067 //         since no protocol handler exists in registry for file:
00068 //     Important - these lists should match - protocol to handler
00069 const char* gURLProtocolWhitelistHandler[] = { "http", "http", "https" };       
00070 
00071 BOOL LLWindowCallbacks::handleTranslatedKeyDown(const KEY key, const MASK mask, BOOL repeated)
00072 {
00073         return FALSE;
00074 }
00075 
00076 
00077 BOOL LLWindowCallbacks::handleTranslatedKeyUp(const KEY key, const MASK mask)
00078 {
00079         return FALSE;
00080 }
00081 
00082 void LLWindowCallbacks::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
00083 {
00084 }
00085 
00086 BOOL LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask)
00087 {
00088         return FALSE;
00089 }
00090 
00091 
00092 BOOL LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
00093 {
00094         return FALSE;
00095 }
00096 
00097 BOOL LLWindowCallbacks::handleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
00098 {
00099         return FALSE;
00100 }
00101 
00102 void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
00103 {
00104         return;
00105 }
00106 
00107 BOOL LLWindowCallbacks::handleCloseRequest(LLWindow *window)
00108 {
00109         //allow the window to close
00110         return TRUE;
00111 }
00112 
00113 void LLWindowCallbacks::handleQuit(LLWindow *window)
00114 {
00115         if(LLWindowManager::destroyWindow(window) == FALSE)     
00116         {
00117                 llerrs << "LLWindowCallbacks::handleQuit() : Couldn't destroy window" << llendl;
00118         }
00119 }
00120 
00121 BOOL LLWindowCallbacks::handleRightMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
00122 {
00123         return FALSE;
00124 }
00125 
00126 BOOL LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
00127 {
00128         return FALSE;
00129 }
00130 
00131 BOOL LLWindowCallbacks::handleMiddleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
00132 {
00133         return FALSE;
00134 }
00135 
00136 BOOL LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
00137 {
00138         return FALSE;
00139 }
00140 
00141 BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated)
00142 {
00143         return FALSE;
00144 }
00145 
00146 void LLWindowCallbacks::handleMouseMove(LLWindow *window, const LLCoordGL pos, MASK mask)
00147 {
00148 }
00149 
00150 void LLWindowCallbacks::handleScrollWheel(LLWindow *window, S32 clicks)
00151 {
00152 }
00153 
00154 void LLWindowCallbacks::handleResize(LLWindow *window, const S32 width, const S32 height)
00155 {
00156 }
00157 
00158 void LLWindowCallbacks::handleFocus(LLWindow *window)
00159 {
00160 }
00161 
00162 void LLWindowCallbacks::handleFocusLost(LLWindow *window)
00163 {
00164 }
00165 
00166 void LLWindowCallbacks::handleMenuSelect(LLWindow *window, const S32 menu_item)
00167 {
00168 }
00169 
00170 BOOL LLWindowCallbacks::handlePaint(LLWindow *window, const S32 x, const S32 y, 
00171                                                                         const S32 width, const S32 height)
00172 {
00173         return FALSE;
00174 }
00175 
00176 BOOL LLWindowCallbacks::handleDoubleClick(LLWindow *window, const LLCoordGL pos, MASK mask)
00177 {
00178         return FALSE;
00179 }
00180 
00181 void LLWindowCallbacks::handleWindowBlock(LLWindow *window)
00182 {
00183 }
00184 
00185 void LLWindowCallbacks::handleWindowUnblock(LLWindow *window)
00186 {
00187 }
00188 
00189 void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *data)
00190 {
00191 }
00192 
00193 
00194 S32 OSMessageBox(const char* text, const char* caption, U32 type)
00195 {
00196         // Properly hide the splash screen when displaying the message box
00197         BOOL was_visible = FALSE;
00198         if (LLSplashScreen::isVisible())
00199         {
00200                 was_visible = TRUE;
00201                 LLSplashScreen::hide();
00202         }
00203 
00204         S32 result = 0;
00205 #if LL_MESA_HEADLESS // !!! *FIX: (???)
00206         llwarns << "OSMessageBox: " << text << llendl;
00207         return OSBTN_OK;
00208 #elif LL_WINDOWS
00209         result = OSMessageBoxWin32(text, caption, type);
00210 #elif LL_DARWIN
00211         result = OSMessageBoxMacOSX(text, caption, type);
00212 #elif LL_SDL
00213         result = OSMessageBoxSDL(text, caption, type);
00214 #else
00215 #error("OSMessageBox not implemented for this platform!")
00216 #endif
00217 
00218         if (was_visible)
00219         {
00220                 LLSplashScreen::show();
00221         }
00222 
00223         return result;
00224 }
00225 
00226 
00227 //
00228 // LLWindow
00229 //
00230 
00231 LLWindow::LLWindow(BOOL fullscreen, U32 flags)
00232         : mCallbacks(&sDefaultCallbacks),
00233           mPostQuit(TRUE),
00234           mFullscreen(fullscreen),
00235           mFullscreenWidth(0),
00236           mFullscreenHeight(0),
00237           mFullscreenBits(0),
00238           mFullscreenRefresh(0),
00239           mSupportedResolutions(NULL),
00240           mNumSupportedResolutions(0),
00241           mCurrentCursor(UI_CURSOR_ARROW),
00242           mCursorHidden(FALSE),
00243           mBusyCount(0),
00244           mIsMouseClipping(FALSE),
00245           mSwapMethod(SWAP_METHOD_UNDEFINED),
00246           mHideCursorPermanent(FALSE),
00247           mFlags(flags),
00248           mHighSurrogate(0),
00249           mStereoMode(STEREO_MODE_NONE)
00250 {
00251         for (U32 i = 0; i < 6; i++)
00252         {
00253                 mJoyAxis[i] = 0;
00254         }
00255 
00256         for (U32 i = 0; i < 16; i++)
00257         {
00258                 mJoyButtonState[i] = 0;
00259         }
00260 }
00261         
00262 // virtual
00263 void LLWindow::incBusyCount()
00264 {
00265         ++mBusyCount;
00266 }
00267 
00268 // virtual
00269 void LLWindow::decBusyCount()
00270 {
00271         if (mBusyCount > 0)
00272         {
00273                 --mBusyCount;
00274         }
00275 }
00276 
00277 F32 LLWindow::getJoystickAxis(U32 axis)
00278 {
00279         if (axis < 6)
00280         {
00281                 return mJoyAxis[axis];
00282         }
00283         return 0.f;
00284 }
00285 
00286 U8 LLWindow::getJoystickButton(U32 button)
00287 {
00288         if (button < 16)
00289         {
00290                 return mJoyButtonState[button];
00291         }
00292         return 0;
00293 }
00294 
00295 void LLWindow::setCallbacks(LLWindowCallbacks *callbacks)
00296 {
00297         mCallbacks = callbacks;
00298         if (gKeyboard)
00299         {
00300                 gKeyboard->setCallbacks(callbacks);
00301         }
00302 }
00303 
00304 #define UTF16_IS_HIGH_SURROGATE(U) ((U16)((U) - 0xD800) < 0x0400)
00305 #define UTF16_IS_LOW_SURROGATE(U)  ((U16)((U) - 0xDC00) < 0x0400)
00306 #define UTF16_SURROGATE_PAIR_TO_UTF32(H,L) (((H) << 10) + (L) - (0xD800 << 10) - 0xDC00 + 0x00010000)
00307 
00308 void LLWindow::handleUnicodeUTF16(U16 utf16, MASK mask)
00309 {
00310         // Note that we could discard unpaired surrogates, but I'm
00311         // following the Unicode Consortium's recommendation here;
00312         // that is, to preserve those unpaired surrogates in UTF-32
00313         // values.  _To_preserve_ means to pass to the callback in our
00314         // context.
00315 
00316         if (mHighSurrogate == 0)
00317         {
00318                 if (UTF16_IS_HIGH_SURROGATE(utf16))
00319                 {
00320                         mHighSurrogate = utf16;
00321                 }
00322                 else
00323                 {
00324                         mCallbacks->handleUnicodeChar(utf16, mask);
00325                 }
00326         }
00327         else
00328         {
00329                 if (UTF16_IS_LOW_SURROGATE(utf16))
00330                 {
00331                         /* A legal surrogate pair.  */                  
00332                         mCallbacks->handleUnicodeChar(UTF16_SURROGATE_PAIR_TO_UTF32(mHighSurrogate, utf16), mask);
00333                         mHighSurrogate = 0;
00334                 }
00335                 else if (UTF16_IS_HIGH_SURROGATE(utf16))
00336                 {
00337                         /* Two consecutive high surrogates.  */
00338                         mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
00339                         mHighSurrogate = utf16;
00340                 }
00341                 else
00342                 {
00343                         /* A non-low-surrogate preceeded by a high surrogate. */
00344                         mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
00345                         mHighSurrogate = 0;
00346                         mCallbacks->handleUnicodeChar(utf16, mask);
00347                 }
00348         }
00349 }
00350 
00351 //
00352 // LLSplashScreen
00353 //
00354 
00355 // static
00356 bool LLSplashScreen::isVisible()
00357 {
00358         return gSplashScreenp ? true: false;
00359 }
00360 
00361 // static
00362 LLSplashScreen *LLSplashScreen::create()
00363 {
00364 #if LL_MESA_HEADLESS || LL_SDL  // !!! *FIX: (???)
00365         return 0;
00366 #elif LL_WINDOWS
00367         return new LLSplashScreenWin32;
00368 #elif LL_DARWIN
00369         return new LLSplashScreenMacOSX;
00370 #else
00371 #error("LLSplashScreen not implemented on this platform!")
00372 #endif
00373 }
00374 
00375 
00376 //static
00377 void LLSplashScreen::show()
00378 {
00379         if (!gSplashScreenp)
00380         {
00381 #if LL_WINDOWS && !LL_MESA_HEADLESS
00382                 gSplashScreenp = new LLSplashScreenWin32;
00383 #elif LL_DARWIN
00384                 gSplashScreenp = new LLSplashScreenMacOSX;
00385 #endif
00386                 if (gSplashScreenp)
00387                 {
00388                         gSplashScreenp->showImpl();
00389                 }
00390         }
00391 }
00392 
00393 //static
00394 void LLSplashScreen::update(const char* str)
00395 {
00396         LLSplashScreen::show();
00397         if (gSplashScreenp)
00398         {
00399                 gSplashScreenp->updateImpl(str);
00400         }
00401 }
00402 
00403 //static
00404 void LLSplashScreen::hide()
00405 {
00406         if (gSplashScreenp)
00407         {
00408                 gSplashScreenp->hideImpl();
00409         }
00410         delete gSplashScreenp;
00411         gSplashScreenp = NULL;
00412 }
00413 
00414 //
00415 // LLWindowManager
00416 //
00417 
00418 // TODO: replace with std::set
00419 static LLLinkedList<LLWindow> sWindowList;
00420 
00421 LLWindow* LLWindowManager::createWindow(
00422         char *title,
00423         char *name,
00424         LLCoordScreen upper_left,
00425         LLCoordScreen size,
00426         U32 flags,
00427         BOOL fullscreen, 
00428         BOOL clearBg,
00429         BOOL disable_vsync,
00430         BOOL use_gl,
00431         BOOL ignore_pixel_depth,
00432         S32 stereo_mode)
00433 {
00434         return createWindow(
00435                 title, name, upper_left.mX, upper_left.mY, size.mX, size.mY, flags, 
00436                 fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, stereo_mode);
00437 }
00438 
00439 LLWindow* LLWindowManager::createWindow(
00440         char *title, char *name, S32 x, S32 y, S32 width, S32 height, U32 flags,
00441         BOOL fullscreen, 
00442         BOOL clearBg,
00443         BOOL disable_vsync,
00444         BOOL use_gl,
00445         BOOL ignore_pixel_depth,
00446         S32 stereo_mode)
00447 {
00448         LLWindow* new_window;
00449 
00450         if (use_gl)
00451         {
00452 #if LL_MESA_HEADLESS
00453                 new_window = new LLWindowMesaHeadless(
00454                         title, name, x, y, width, height, flags, 
00455                         fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, stereo_mode);
00456 #elif LL_SDL
00457                 new_window = new LLWindowSDL(
00458                         title, x, y, width, height, flags, 
00459                         fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, stereo_mode);
00460 #elif LL_WINDOWS
00461                 new_window = new LLWindowWin32(
00462                         title, name, x, y, width, height, flags, 
00463                         fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, stereo_mode);
00464 #elif LL_DARWIN
00465                 new_window = new LLWindowMacOSX(
00466                         title, name, x, y, width, height, flags, 
00467                         fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, stereo_mode);
00468 #elif LL_LINUX
00469                 new_window = new LLWindowLinux(
00470                         title, name, x, y, width, height, flags, 
00471                         fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, stereo_mode);
00472 #endif
00473         }
00474         else
00475         {
00476                 new_window = new LLWindowHeadless(
00477                         title, name, x, y, width, height, flags, 
00478                         fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, stereo_mode);
00479         }
00480 
00481         if (FALSE == new_window->isValid())
00482         {
00483                 delete new_window;
00484                 llwarns << "LLWindowManager::create() : Error creating window." << llendl;
00485                 return NULL;
00486         }
00487         sWindowList.addDataAtEnd(new_window);
00488         return new_window;
00489 }
00490 
00491 BOOL LLWindowManager::destroyWindow(LLWindow* window)
00492 {
00493         if (!sWindowList.checkData(window))
00494         {
00495                 llerrs << "LLWindowManager::destroyWindow() : Window pointer not valid, this window doesn't exist!" 
00496                         << llendl;
00497                 return FALSE;
00498         }
00499 
00500         window->close();
00501 
00502         sWindowList.removeData(window);
00503 
00504         delete window;
00505 
00506         return TRUE;
00507 }
00508 
00509 BOOL LLWindowManager::isWindowValid(LLWindow *window)
00510 {
00511         return sWindowList.checkData(window);
00512 }

Generated on Thu Jul 1 06:09:45 2010 for Second Life Viewer by  doxygen 1.4.7