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"
00045 #endif
00046
00047 #include "llerror.h"
00048 #include "llkeyboard.h"
00049 #include "linked_lists.h"
00050
00051
00052 LLWindowCallbacks LLWindow::sDefaultCallbacks;
00053
00054
00055
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
00066
00067
00068
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
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
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
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
00263 void LLWindow::incBusyCount()
00264 {
00265 ++mBusyCount;
00266 }
00267
00268
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
00311
00312
00313
00314
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
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
00338 mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
00339 mHighSurrogate = utf16;
00340 }
00341 else
00342 {
00343
00344 mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
00345 mHighSurrogate = 0;
00346 mCallbacks->handleUnicodeChar(utf16, mask);
00347 }
00348 }
00349 }
00350
00351
00352
00353
00354
00355
00356 bool LLSplashScreen::isVisible()
00357 {
00358 return gSplashScreenp ? true: false;
00359 }
00360
00361
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
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
00394 void LLSplashScreen::update(const char* str)
00395 {
00396 LLSplashScreen::show();
00397 if (gSplashScreenp)
00398 {
00399 gSplashScreenp->updateImpl(str);
00400 }
00401 }
00402
00403
00404 void LLSplashScreen::hide()
00405 {
00406 if (gSplashScreenp)
00407 {
00408 gSplashScreenp->hideImpl();
00409 }
00410 delete gSplashScreenp;
00411 gSplashScreenp = NULL;
00412 }
00413
00414
00415
00416
00417
00418
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 }