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