PageRenderTime 124ms CodeModel.GetById 102ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llwindow/llwindow.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 438 lines | 313 code | 53 blank | 72 comment | 27 complexity | aaa24c8d37ad60399bd8f797e204f10a MD5 | raw file
  1/** 
  2 * @file llwindow.cpp
  3 * @brief Basic graphical window class
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "linden_common.h"
 28#include "llwindowheadless.h"
 29
 30#if LL_MESA_HEADLESS
 31#include "llwindowmesaheadless.h"
 32#elif LL_SDL
 33#include "llwindowsdl.h"
 34#elif LL_WINDOWS
 35#include "llwindowwin32.h"
 36#elif LL_DARWIN
 37#include "llwindowmacosx.h"
 38#endif
 39
 40#include "llerror.h"
 41#include "llkeyboard.h"
 42#include "linked_lists.h"
 43#include "llwindowcallbacks.h"
 44
 45
 46//
 47// Globals
 48//
 49LLSplashScreen *gSplashScreenp = NULL;
 50BOOL gDebugClicks = FALSE;
 51BOOL gDebugWindowProc = FALSE;
 52
 53const S32 gURLProtocolWhitelistCount = 3;
 54const std::string gURLProtocolWhitelist[] = { "file:", "http:", "https:" };
 55
 56// CP: added a handler list - this is what's used to open the protocol and is based on registry entry
 57//	   only meaningful difference currently is that file: protocols are opened using http:
 58//	   since no protocol handler exists in registry for file:
 59//     Important - these lists should match - protocol to handler
 60const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" };	
 61
 62
 63S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
 64{
 65	// Properly hide the splash screen when displaying the message box
 66	BOOL was_visible = FALSE;
 67	if (LLSplashScreen::isVisible())
 68	{
 69		was_visible = TRUE;
 70		LLSplashScreen::hide();
 71	}
 72
 73	S32 result = 0;
 74#if LL_MESA_HEADLESS // !!! *FIX: (???)
 75	llwarns << "OSMessageBox: " << text << llendl;
 76	return OSBTN_OK;
 77#elif LL_WINDOWS
 78	result = OSMessageBoxWin32(text, caption, type);
 79#elif LL_DARWIN
 80	result = OSMessageBoxMacOSX(text, caption, type);
 81#elif LL_SDL
 82	result = OSMessageBoxSDL(text, caption, type);
 83#else
 84#error("OSMessageBox not implemented for this platform!")
 85#endif
 86
 87	if (was_visible)
 88	{
 89		LLSplashScreen::show();
 90	}
 91
 92	return result;
 93}
 94
 95
 96//
 97// LLWindow
 98//
 99
100LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
101	: mCallbacks(callbacks),
102	  mPostQuit(TRUE),
103	  mFullscreen(fullscreen),
104	  mFullscreenWidth(0),
105	  mFullscreenHeight(0),
106	  mFullscreenBits(0),
107	  mFullscreenRefresh(0),
108	  mSupportedResolutions(NULL),
109	  mNumSupportedResolutions(0),
110	  mCurrentCursor(UI_CURSOR_ARROW),
111	  mNextCursor(UI_CURSOR_ARROW),
112	  mCursorHidden(FALSE),
113	  mBusyCount(0),
114	  mIsMouseClipping(FALSE),
115	  mMinWindowWidth(0),
116	  mMinWindowHeight(0),
117	  mSwapMethod(SWAP_METHOD_UNDEFINED),
118	  mHideCursorPermanent(FALSE),
119	  mFlags(flags),
120	  mHighSurrogate(0)
121{
122}
123
124LLWindow::~LLWindow()
125{
126}
127
128//virtual
129BOOL LLWindow::isValid()
130{
131	return TRUE;
132}
133
134//virtual
135BOOL LLWindow::canDelete()
136{
137	return TRUE;
138}
139
140// virtual
141void LLWindow::incBusyCount()
142{
143	++mBusyCount;
144}
145
146// virtual
147void LLWindow::decBusyCount()
148{
149	if (mBusyCount > 0)
150	{
151		--mBusyCount;
152	}
153}
154
155//virtual
156void LLWindow::resetBusyCount()
157{
158	mBusyCount = 0;
159}
160
161//virtual
162S32 LLWindow::getBusyCount() const
163{
164	return mBusyCount;
165}
166
167//virtual
168ECursorType LLWindow::getCursor() const
169{
170	return mCurrentCursor;
171}
172
173//virtual
174BOOL LLWindow::dialogColorPicker(F32 *r, F32 *g, F32 *b)
175{
176	return FALSE;
177}
178
179void *LLWindow::getMediaWindow()
180{
181	// Default to returning the platform window.
182	return getPlatformWindow();
183}
184
185BOOL LLWindow::setSize(LLCoordScreen size)
186{
187	if (!getMaximized())
188	{
189		size.mX = llmax(size.mX, mMinWindowWidth);
190		size.mY = llmax(size.mY, mMinWindowHeight);
191	}
192	return setSizeImpl(size);
193}
194
195
196// virtual
197void LLWindow::setMinSize(U32 min_width, U32 min_height, bool enforce_immediately)
198{
199	mMinWindowWidth = min_width;
200	mMinWindowHeight = min_height;
201
202	if (enforce_immediately)
203	{
204		LLCoordScreen cur_size;
205		if (!getMaximized() && getSize(&cur_size))
206		{
207			if (cur_size.mX < mMinWindowWidth || cur_size.mY < mMinWindowHeight)
208			{
209				setSizeImpl(LLCoordScreen(llmin(cur_size.mX, mMinWindowWidth), llmin(cur_size.mY, mMinWindowHeight)));
210			}
211		}
212	}
213}
214
215//virtual
216void LLWindow::processMiscNativeEvents()
217{
218	// do nothing unless subclassed
219}
220
221//virtual
222BOOL LLWindow::isPrimaryTextAvailable()
223{
224	return FALSE; // no
225}
226//virtual
227BOOL LLWindow::pasteTextFromPrimary(LLWString &dst)
228{
229	return FALSE; // fail
230}
231// virtual
232BOOL LLWindow::copyTextToPrimary(const LLWString &src)
233{
234	return FALSE; // fail
235}
236
237// static
238std::vector<std::string> LLWindow::getDynamicFallbackFontList()
239{
240#if LL_WINDOWS
241	return LLWindowWin32::getDynamicFallbackFontList();
242#elif LL_DARWIN
243	return LLWindowMacOSX::getDynamicFallbackFontList();
244#elif LL_SDL
245	return LLWindowSDL::getDynamicFallbackFontList();
246#else
247	return std::vector<std::string>();
248#endif
249}
250
251#define UTF16_IS_HIGH_SURROGATE(U) ((U16)((U) - 0xD800) < 0x0400)
252#define UTF16_IS_LOW_SURROGATE(U)  ((U16)((U) - 0xDC00) < 0x0400)
253#define UTF16_SURROGATE_PAIR_TO_UTF32(H,L) (((H) << 10) + (L) - (0xD800 << 10) - 0xDC00 + 0x00010000)
254
255void LLWindow::handleUnicodeUTF16(U16 utf16, MASK mask)
256{
257	// Note that we could discard unpaired surrogates, but I'm
258	// following the Unicode Consortium's recommendation here;
259	// that is, to preserve those unpaired surrogates in UTF-32
260	// values.  _To_preserve_ means to pass to the callback in our
261	// context.
262
263	if (mHighSurrogate == 0)
264	{
265		if (UTF16_IS_HIGH_SURROGATE(utf16))
266		{
267			mHighSurrogate = utf16;
268		}
269		else
270		{
271			mCallbacks->handleUnicodeChar(utf16, mask);
272		}
273	}
274	else
275	{
276		if (UTF16_IS_LOW_SURROGATE(utf16))
277		{
278			/* A legal surrogate pair.  */			
279			mCallbacks->handleUnicodeChar(UTF16_SURROGATE_PAIR_TO_UTF32(mHighSurrogate, utf16), mask);
280			mHighSurrogate = 0;
281		}
282		else if (UTF16_IS_HIGH_SURROGATE(utf16))
283		{
284			/* Two consecutive high surrogates.  */
285			mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
286			mHighSurrogate = utf16;
287		}
288		else
289		{
290			/* A non-low-surrogate preceeded by a high surrogate. */
291			mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
292			mHighSurrogate = 0;
293			mCallbacks->handleUnicodeChar(utf16, mask);
294		}
295	}
296}
297
298//
299// LLSplashScreen
300//
301
302// static
303bool LLSplashScreen::isVisible()
304{
305	return gSplashScreenp ? true: false;
306}
307
308// static
309LLSplashScreen *LLSplashScreen::create()
310{
311#if LL_MESA_HEADLESS || LL_SDL  // !!! *FIX: (???)
312	return 0;
313#elif LL_WINDOWS
314	return new LLSplashScreenWin32;
315#elif LL_DARWIN
316	return new LLSplashScreenMacOSX;
317#else
318#error("LLSplashScreen not implemented on this platform!")
319#endif
320}
321
322
323//static
324void LLSplashScreen::show()
325{
326	if (!gSplashScreenp)
327	{
328#if LL_WINDOWS && !LL_MESA_HEADLESS
329		gSplashScreenp = new LLSplashScreenWin32;
330#elif LL_DARWIN
331		gSplashScreenp = new LLSplashScreenMacOSX;
332#endif
333		if (gSplashScreenp)
334		{
335			gSplashScreenp->showImpl();
336		}
337	}
338}
339
340//static
341void LLSplashScreen::update(const std::string& str)
342{
343	LLSplashScreen::show();
344	if (gSplashScreenp)
345	{
346		gSplashScreenp->updateImpl(str);
347	}
348}
349
350//static
351void LLSplashScreen::hide()
352{
353	if (gSplashScreenp)
354	{
355		gSplashScreenp->hideImpl();
356	}
357	delete gSplashScreenp;
358	gSplashScreenp = NULL;
359}
360
361//
362// LLWindowManager
363//
364
365// TODO: replace with std::set
366static std::set<LLWindow*> sWindowList;
367
368LLWindow* LLWindowManager::createWindow(
369	LLWindowCallbacks* callbacks,
370	const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags,
371	BOOL fullscreen, 
372	BOOL clearBg,
373	BOOL disable_vsync,
374	BOOL use_gl,
375	BOOL ignore_pixel_depth,
376	U32 fsaa_samples)
377{
378	LLWindow* new_window;
379
380	if (use_gl)
381	{
382#if LL_MESA_HEADLESS
383		new_window = new LLWindowMesaHeadless(callbacks,
384			title, name, x, y, width, height, flags, 
385			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
386#elif LL_SDL
387		new_window = new LLWindowSDL(callbacks,
388			title, x, y, width, height, flags, 
389			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
390#elif LL_WINDOWS
391		new_window = new LLWindowWin32(callbacks,
392			title, name, x, y, width, height, flags, 
393			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
394#elif LL_DARWIN
395		new_window = new LLWindowMacOSX(callbacks,
396			title, name, x, y, width, height, flags, 
397			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
398#endif
399	}
400	else
401	{
402		new_window = new LLWindowHeadless(callbacks,
403			title, name, x, y, width, height, flags, 
404			fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
405	}
406
407	if (FALSE == new_window->isValid())
408	{
409		delete new_window;
410		llwarns << "LLWindowManager::create() : Error creating window." << llendl;
411		return NULL;
412	}
413	sWindowList.insert(new_window);
414	return new_window;
415}
416
417BOOL LLWindowManager::destroyWindow(LLWindow* window)
418{
419	if (sWindowList.find(window) == sWindowList.end())
420	{
421		llerrs << "LLWindowManager::destroyWindow() : Window pointer not valid, this window doesn't exist!" 
422			<< llendl;
423		return FALSE;
424	}
425
426	window->close();
427
428	sWindowList.erase(window);
429
430	delete window;
431
432	return TRUE;
433}
434
435BOOL LLWindowManager::isWindowValid(LLWindow *window)
436{
437	return sWindowList.find(window) != sWindowList.end();
438}