402 lines
8.2 KiB
C++
402 lines
8.2 KiB
C++
/**
|
|
* @file llwindow.cpp
|
|
* @brief Basic graphical window class
|
|
*
|
|
* Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
|
|
* $License$
|
|
*/
|
|
|
|
#include "linden_common.h"
|
|
#include "llwindowheadless.h"
|
|
|
|
#if LL_MESA_HEADLESS
|
|
#include "llwindowmesaheadless.h"
|
|
#elif LL_SDL
|
|
#include "llwindowsdl.h"
|
|
#elif LL_WINDOWS
|
|
#include "llwindowwin32.h"
|
|
#elif LL_DARWIN
|
|
#include "llwindowmacosx.h"
|
|
#elif LL_LINUX
|
|
#include "llwindowlinux.h" // currently just a dummy wrapper
|
|
#endif
|
|
|
|
#include "llerror.h"
|
|
#include "llkeyboard.h"
|
|
#include "linked_lists.h"
|
|
|
|
//static instance for default callbacks
|
|
LLWindowCallbacks LLWindow::sDefaultCallbacks;
|
|
|
|
//
|
|
// LLWindowCallbacks
|
|
//
|
|
|
|
LLSplashScreen *gSplashScreenp = NULL;
|
|
BOOL gDebugClicks = FALSE;
|
|
BOOL gDebugWindowProc = FALSE;
|
|
|
|
const S32 gURLProtocolWhitelistCount = 3;
|
|
const char* gURLProtocolWhitelist[] = { "file", "http", "https" };
|
|
|
|
// CP: added a handler list - this is what's used to open the protocol and is based on registry entry
|
|
// only meaningful difference currently is that file: protocols are opened using http:
|
|
// since no protocol handler exists in registry for file:
|
|
// Important - these lists should match - protocol to handler
|
|
const char* gURLProtocolWhitelistHandler[] = { "http", "http", "https" };
|
|
|
|
BOOL LLWindowCallbacks::handleTranslatedKeyDown(const KEY key, const MASK mask, BOOL repeated)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL LLWindowCallbacks::handleTranslatedKeyUp(const KEY key, const MASK mask)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
void LLWindowCallbacks::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
|
|
{
|
|
}
|
|
|
|
BOOL LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL LLWindowCallbacks::handleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BOOL LLWindowCallbacks::handleCloseRequest(LLWindow *window)
|
|
{
|
|
//allow the window to close
|
|
return TRUE;
|
|
}
|
|
|
|
void LLWindowCallbacks::handleQuit(LLWindow *window)
|
|
{
|
|
if(LLWindowManager::destroyWindow(window) == FALSE)
|
|
{
|
|
llerrs << "LLWindowCallbacks::handleQuit() : Couldn't destroy window" << llendl;
|
|
}
|
|
}
|
|
|
|
BOOL LLWindowCallbacks::handleRightMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
void LLWindowCallbacks::handleMouseMove(LLWindow *window, const LLCoordGL pos, MASK mask)
|
|
{
|
|
}
|
|
|
|
void LLWindowCallbacks::handleScrollWheel(LLWindow *window, S32 clicks)
|
|
{
|
|
}
|
|
|
|
void LLWindowCallbacks::handleResize(LLWindow *window, const S32 width, const S32 height)
|
|
{
|
|
}
|
|
|
|
void LLWindowCallbacks::handleFocus(LLWindow *window)
|
|
{
|
|
}
|
|
|
|
void LLWindowCallbacks::handleFocusLost(LLWindow *window)
|
|
{
|
|
}
|
|
|
|
void LLWindowCallbacks::handleMenuSelect(LLWindow *window, const S32 menu_item)
|
|
{
|
|
}
|
|
|
|
BOOL LLWindowCallbacks::handlePaint(LLWindow *window, const S32 x, const S32 y,
|
|
const S32 width, const S32 height)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL LLWindowCallbacks::handleDoubleClick(LLWindow *window, const LLCoordGL pos, MASK mask)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
void LLWindowCallbacks::handleWindowBlock(LLWindow *window)
|
|
{
|
|
}
|
|
|
|
void LLWindowCallbacks::handleWindowUnblock(LLWindow *window)
|
|
{
|
|
}
|
|
|
|
void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *data)
|
|
{
|
|
}
|
|
|
|
|
|
S32 OSMessageBox(const char* text, const char* caption, U32 type)
|
|
{
|
|
// Properly hide the splash screen when displaying the message box
|
|
BOOL was_visible = FALSE;
|
|
if (LLSplashScreen::isVisible())
|
|
{
|
|
was_visible = TRUE;
|
|
LLSplashScreen::hide();
|
|
}
|
|
|
|
S32 result = 0;
|
|
#if LL_MESA_HEADLESS // !!! *FIX: (???)
|
|
llwarns << "OSMessageBox: " << text << llendl;
|
|
return OSBTN_OK;
|
|
#elif LL_WINDOWS
|
|
result = OSMessageBoxWin32(text, caption, type);
|
|
#elif LL_DARWIN
|
|
result = OSMessageBoxMacOSX(text, caption, type);
|
|
#elif LL_SDL
|
|
result = OSMessageBoxSDL(text, caption, type);
|
|
#else
|
|
#error("OSMessageBox not implemented for this platform!")
|
|
#endif
|
|
|
|
if (was_visible)
|
|
{
|
|
LLSplashScreen::show();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
//
|
|
// LLWindow
|
|
//
|
|
|
|
LLWindow::LLWindow(BOOL fullscreen, U32 flags)
|
|
: mCallbacks(&sDefaultCallbacks),
|
|
mPostQuit(TRUE),
|
|
mFullscreen(fullscreen),
|
|
mFullscreenWidth(0),
|
|
mFullscreenHeight(0),
|
|
mFullscreenBits(0),
|
|
mFullscreenRefresh(0),
|
|
mSupportedResolutions(NULL),
|
|
mNumSupportedResolutions(0),
|
|
mCurrentCursor(UI_CURSOR_ARROW),
|
|
mCursorHidden(FALSE),
|
|
mBusyCount(0),
|
|
mIsMouseClipping(FALSE),
|
|
mSwapMethod(SWAP_METHOD_UNDEFINED),
|
|
mHideCursorPermanent(FALSE),
|
|
mFlags(flags)
|
|
{
|
|
}
|
|
|
|
// virtual
|
|
void LLWindow::incBusyCount()
|
|
{
|
|
++mBusyCount;
|
|
}
|
|
|
|
// virtual
|
|
void LLWindow::decBusyCount()
|
|
{
|
|
if (mBusyCount > 0)
|
|
{
|
|
--mBusyCount;
|
|
}
|
|
}
|
|
|
|
void LLWindow::setCallbacks(LLWindowCallbacks *callbacks)
|
|
{
|
|
mCallbacks = callbacks;
|
|
if (gKeyboard)
|
|
{
|
|
gKeyboard->setCallbacks(callbacks);
|
|
}
|
|
}
|
|
|
|
//
|
|
// LLSplashScreen
|
|
//
|
|
|
|
// static
|
|
bool LLSplashScreen::isVisible()
|
|
{
|
|
return gSplashScreenp ? true: false;
|
|
}
|
|
|
|
// static
|
|
LLSplashScreen *LLSplashScreen::create()
|
|
{
|
|
#if LL_MESA_HEADLESS || LL_SDL // !!! *FIX: (???)
|
|
return 0;
|
|
#elif LL_WINDOWS
|
|
return new LLSplashScreenWin32;
|
|
#elif LL_DARWIN
|
|
return new LLSplashScreenMacOSX;
|
|
#else
|
|
#error("LLSplashScreen not implemented on this platform!")
|
|
#endif
|
|
}
|
|
|
|
|
|
//static
|
|
void LLSplashScreen::show()
|
|
{
|
|
if (!gSplashScreenp)
|
|
{
|
|
#if LL_WINDOWS && !LL_MESA_HEADLESS
|
|
gSplashScreenp = new LLSplashScreenWin32;
|
|
#elif LL_DARWIN
|
|
gSplashScreenp = new LLSplashScreenMacOSX;
|
|
#endif
|
|
if (gSplashScreenp)
|
|
{
|
|
gSplashScreenp->showImpl();
|
|
}
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLSplashScreen::update(const char* str)
|
|
{
|
|
LLSplashScreen::show();
|
|
if (gSplashScreenp)
|
|
{
|
|
gSplashScreenp->updateImpl(str);
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLSplashScreen::hide()
|
|
{
|
|
if (gSplashScreenp)
|
|
{
|
|
gSplashScreenp->hideImpl();
|
|
}
|
|
delete gSplashScreenp;
|
|
gSplashScreenp = NULL;
|
|
}
|
|
|
|
//
|
|
// LLWindowManager
|
|
//
|
|
|
|
// TODO: replace with std::set
|
|
static LLLinkedList<LLWindow> sWindowList;
|
|
|
|
LLWindow* LLWindowManager::createWindow(
|
|
char *title,
|
|
char *name,
|
|
LLCoordScreen upper_left,
|
|
LLCoordScreen size,
|
|
U32 flags,
|
|
BOOL fullscreen,
|
|
BOOL clearBg,
|
|
BOOL disable_vsync,
|
|
BOOL use_gl,
|
|
BOOL ignore_pixel_depth)
|
|
{
|
|
return createWindow(
|
|
title, name, upper_left.mX, upper_left.mY, size.mX, size.mY, flags,
|
|
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
|
}
|
|
|
|
LLWindow* LLWindowManager::createWindow(
|
|
char *title, char *name, S32 x, S32 y, S32 width, S32 height, U32 flags,
|
|
BOOL fullscreen,
|
|
BOOL clearBg,
|
|
BOOL disable_vsync,
|
|
BOOL use_gl,
|
|
BOOL ignore_pixel_depth)
|
|
{
|
|
LLWindow* new_window;
|
|
|
|
if (use_gl)
|
|
{
|
|
#if LL_MESA_HEADLESS
|
|
new_window = new LLWindowMesaHeadless(
|
|
title, name, x, y, width, height, flags,
|
|
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
|
#elif LL_SDL
|
|
new_window = new LLWindowSDL(
|
|
title, x, y, width, height, flags,
|
|
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
|
#elif LL_WINDOWS
|
|
new_window = new LLWindowWin32(
|
|
title, name, x, y, width, height, flags,
|
|
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
|
#elif LL_DARWIN
|
|
new_window = new LLWindowMacOSX(
|
|
title, name, x, y, width, height, flags,
|
|
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
|
#elif LL_LINUX
|
|
new_window = new LLWindowLinux(
|
|
title, name, x, y, width, height, flags,
|
|
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
new_window = new LLWindowHeadless(
|
|
title, name, x, y, width, height, flags,
|
|
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
|
}
|
|
|
|
if (FALSE == new_window->isValid())
|
|
{
|
|
delete new_window;
|
|
llwarns << "LLWindowManager::create() : Error creating window." << llendl;
|
|
return NULL;
|
|
}
|
|
sWindowList.addDataAtEnd(new_window);
|
|
return new_window;
|
|
}
|
|
|
|
BOOL LLWindowManager::destroyWindow(LLWindow* window)
|
|
{
|
|
if (!sWindowList.checkData(window))
|
|
{
|
|
llerrs << "LLWindowManager::destroyWindow() : Window pointer not valid, this window doesn't exist!"
|
|
<< llendl;
|
|
return FALSE;
|
|
}
|
|
|
|
window->close();
|
|
|
|
sWindowList.removeData(window);
|
|
|
|
delete window;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL LLWindowManager::isWindowValid(LLWindow *window)
|
|
{
|
|
return sWindowList.checkData(window);
|
|
}
|