PageRenderTime 40ms CodeModel.GetById 16ms RepoModel.GetById 0ms 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
Possible License(s): LGPL-2.1
  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. #include "linden_common.h"
  27. #include "llwindowheadless.h"
  28. #if LL_MESA_HEADLESS
  29. #include "llwindowmesaheadless.h"
  30. #elif LL_SDL
  31. #include "llwindowsdl.h"
  32. #elif LL_WINDOWS
  33. #include "llwindowwin32.h"
  34. #elif LL_DARWIN
  35. #include "llwindowmacosx.h"
  36. #endif
  37. #include "llerror.h"
  38. #include "llkeyboard.h"
  39. #include "linked_lists.h"
  40. #include "llwindowcallbacks.h"
  41. //
  42. // Globals
  43. //
  44. LLSplashScreen *gSplashScreenp = NULL;
  45. BOOL gDebugClicks = FALSE;
  46. BOOL gDebugWindowProc = FALSE;
  47. const S32 gURLProtocolWhitelistCount = 3;
  48. const std::string gURLProtocolWhitelist[] = { "file:", "http:", "https:" };
  49. // CP: added a handler list - this is what's used to open the protocol and is based on registry entry
  50. // only meaningful difference currently is that file: protocols are opened using http:
  51. // since no protocol handler exists in registry for file:
  52. // Important - these lists should match - protocol to handler
  53. const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" };
  54. S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
  55. {
  56. // Properly hide the splash screen when displaying the message box
  57. BOOL was_visible = FALSE;
  58. if (LLSplashScreen::isVisible())
  59. {
  60. was_visible = TRUE;
  61. LLSplashScreen::hide();
  62. }
  63. S32 result = 0;
  64. #if LL_MESA_HEADLESS // !!! *FIX: (???)
  65. llwarns << "OSMessageBox: " << text << llendl;
  66. return OSBTN_OK;
  67. #elif LL_WINDOWS
  68. result = OSMessageBoxWin32(text, caption, type);
  69. #elif LL_DARWIN
  70. result = OSMessageBoxMacOSX(text, caption, type);
  71. #elif LL_SDL
  72. result = OSMessageBoxSDL(text, caption, type);
  73. #else
  74. #error("OSMessageBox not implemented for this platform!")
  75. #endif
  76. if (was_visible)
  77. {
  78. LLSplashScreen::show();
  79. }
  80. return result;
  81. }
  82. //
  83. // LLWindow
  84. //
  85. LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
  86. : mCallbacks(callbacks),
  87. mPostQuit(TRUE),
  88. mFullscreen(fullscreen),
  89. mFullscreenWidth(0),
  90. mFullscreenHeight(0),
  91. mFullscreenBits(0),
  92. mFullscreenRefresh(0),
  93. mSupportedResolutions(NULL),
  94. mNumSupportedResolutions(0),
  95. mCurrentCursor(UI_CURSOR_ARROW),
  96. mNextCursor(UI_CURSOR_ARROW),
  97. mCursorHidden(FALSE),
  98. mBusyCount(0),
  99. mIsMouseClipping(FALSE),
  100. mMinWindowWidth(0),
  101. mMinWindowHeight(0),
  102. mSwapMethod(SWAP_METHOD_UNDEFINED),
  103. mHideCursorPermanent(FALSE),
  104. mFlags(flags),
  105. mHighSurrogate(0)
  106. {
  107. }
  108. LLWindow::~LLWindow()
  109. {
  110. }
  111. //virtual
  112. BOOL LLWindow::isValid()
  113. {
  114. return TRUE;
  115. }
  116. //virtual
  117. BOOL LLWindow::canDelete()
  118. {
  119. return TRUE;
  120. }
  121. // virtual
  122. void LLWindow::incBusyCount()
  123. {
  124. ++mBusyCount;
  125. }
  126. // virtual
  127. void LLWindow::decBusyCount()
  128. {
  129. if (mBusyCount > 0)
  130. {
  131. --mBusyCount;
  132. }
  133. }
  134. //virtual
  135. void LLWindow::resetBusyCount()
  136. {
  137. mBusyCount = 0;
  138. }
  139. //virtual
  140. S32 LLWindow::getBusyCount() const
  141. {
  142. return mBusyCount;
  143. }
  144. //virtual
  145. ECursorType LLWindow::getCursor() const
  146. {
  147. return mCurrentCursor;
  148. }
  149. //virtual
  150. BOOL LLWindow::dialogColorPicker(F32 *r, F32 *g, F32 *b)
  151. {
  152. return FALSE;
  153. }
  154. void *LLWindow::getMediaWindow()
  155. {
  156. // Default to returning the platform window.
  157. return getPlatformWindow();
  158. }
  159. BOOL LLWindow::setSize(LLCoordScreen size)
  160. {
  161. if (!getMaximized())
  162. {
  163. size.mX = llmax(size.mX, mMinWindowWidth);
  164. size.mY = llmax(size.mY, mMinWindowHeight);
  165. }
  166. return setSizeImpl(size);
  167. }
  168. // virtual
  169. void LLWindow::setMinSize(U32 min_width, U32 min_height, bool enforce_immediately)
  170. {
  171. mMinWindowWidth = min_width;
  172. mMinWindowHeight = min_height;
  173. if (enforce_immediately)
  174. {
  175. LLCoordScreen cur_size;
  176. if (!getMaximized() && getSize(&cur_size))
  177. {
  178. if (cur_size.mX < mMinWindowWidth || cur_size.mY < mMinWindowHeight)
  179. {
  180. setSizeImpl(LLCoordScreen(llmin(cur_size.mX, mMinWindowWidth), llmin(cur_size.mY, mMinWindowHeight)));
  181. }
  182. }
  183. }
  184. }
  185. //virtual
  186. void LLWindow::processMiscNativeEvents()
  187. {
  188. // do nothing unless subclassed
  189. }
  190. //virtual
  191. BOOL LLWindow::isPrimaryTextAvailable()
  192. {
  193. return FALSE; // no
  194. }
  195. //virtual
  196. BOOL LLWindow::pasteTextFromPrimary(LLWString &dst)
  197. {
  198. return FALSE; // fail
  199. }
  200. // virtual
  201. BOOL LLWindow::copyTextToPrimary(const LLWString &src)
  202. {
  203. return FALSE; // fail
  204. }
  205. // static
  206. std::vector<std::string> LLWindow::getDynamicFallbackFontList()
  207. {
  208. #if LL_WINDOWS
  209. return LLWindowWin32::getDynamicFallbackFontList();
  210. #elif LL_DARWIN
  211. return LLWindowMacOSX::getDynamicFallbackFontList();
  212. #elif LL_SDL
  213. return LLWindowSDL::getDynamicFallbackFontList();
  214. #else
  215. return std::vector<std::string>();
  216. #endif
  217. }
  218. #define UTF16_IS_HIGH_SURROGATE(U) ((U16)((U) - 0xD800) < 0x0400)
  219. #define UTF16_IS_LOW_SURROGATE(U) ((U16)((U) - 0xDC00) < 0x0400)
  220. #define UTF16_SURROGATE_PAIR_TO_UTF32(H,L) (((H) << 10) + (L) - (0xD800 << 10) - 0xDC00 + 0x00010000)
  221. void LLWindow::handleUnicodeUTF16(U16 utf16, MASK mask)
  222. {
  223. // Note that we could discard unpaired surrogates, but I'm
  224. // following the Unicode Consortium's recommendation here;
  225. // that is, to preserve those unpaired surrogates in UTF-32
  226. // values. _To_preserve_ means to pass to the callback in our
  227. // context.
  228. if (mHighSurrogate == 0)
  229. {
  230. if (UTF16_IS_HIGH_SURROGATE(utf16))
  231. {
  232. mHighSurrogate = utf16;
  233. }
  234. else
  235. {
  236. mCallbacks->handleUnicodeChar(utf16, mask);
  237. }
  238. }
  239. else
  240. {
  241. if (UTF16_IS_LOW_SURROGATE(utf16))
  242. {
  243. /* A legal surrogate pair. */
  244. mCallbacks->handleUnicodeChar(UTF16_SURROGATE_PAIR_TO_UTF32(mHighSurrogate, utf16), mask);
  245. mHighSurrogate = 0;
  246. }
  247. else if (UTF16_IS_HIGH_SURROGATE(utf16))
  248. {
  249. /* Two consecutive high surrogates. */
  250. mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
  251. mHighSurrogate = utf16;
  252. }
  253. else
  254. {
  255. /* A non-low-surrogate preceeded by a high surrogate. */
  256. mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
  257. mHighSurrogate = 0;
  258. mCallbacks->handleUnicodeChar(utf16, mask);
  259. }
  260. }
  261. }
  262. //
  263. // LLSplashScreen
  264. //
  265. // static
  266. bool LLSplashScreen::isVisible()
  267. {
  268. return gSplashScreenp ? true: false;
  269. }
  270. // static
  271. LLSplashScreen *LLSplashScreen::create()
  272. {
  273. #if LL_MESA_HEADLESS || LL_SDL // !!! *FIX: (???)
  274. return 0;
  275. #elif LL_WINDOWS
  276. return new LLSplashScreenWin32;
  277. #elif LL_DARWIN
  278. return new LLSplashScreenMacOSX;
  279. #else
  280. #error("LLSplashScreen not implemented on this platform!")
  281. #endif
  282. }
  283. //static
  284. void LLSplashScreen::show()
  285. {
  286. if (!gSplashScreenp)
  287. {
  288. #if LL_WINDOWS && !LL_MESA_HEADLESS
  289. gSplashScreenp = new LLSplashScreenWin32;
  290. #elif LL_DARWIN
  291. gSplashScreenp = new LLSplashScreenMacOSX;
  292. #endif
  293. if (gSplashScreenp)
  294. {
  295. gSplashScreenp->showImpl();
  296. }
  297. }
  298. }
  299. //static
  300. void LLSplashScreen::update(const std::string& str)
  301. {
  302. LLSplashScreen::show();
  303. if (gSplashScreenp)
  304. {
  305. gSplashScreenp->updateImpl(str);
  306. }
  307. }
  308. //static
  309. void LLSplashScreen::hide()
  310. {
  311. if (gSplashScreenp)
  312. {
  313. gSplashScreenp->hideImpl();
  314. }
  315. delete gSplashScreenp;
  316. gSplashScreenp = NULL;
  317. }
  318. //
  319. // LLWindowManager
  320. //
  321. // TODO: replace with std::set
  322. static std::set<LLWindow*> sWindowList;
  323. LLWindow* LLWindowManager::createWindow(
  324. LLWindowCallbacks* callbacks,
  325. const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags,
  326. BOOL fullscreen,
  327. BOOL clearBg,
  328. BOOL disable_vsync,
  329. BOOL use_gl,
  330. BOOL ignore_pixel_depth,
  331. U32 fsaa_samples)
  332. {
  333. LLWindow* new_window;
  334. if (use_gl)
  335. {
  336. #if LL_MESA_HEADLESS
  337. new_window = new LLWindowMesaHeadless(callbacks,
  338. title, name, x, y, width, height, flags,
  339. fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
  340. #elif LL_SDL
  341. new_window = new LLWindowSDL(callbacks,
  342. title, x, y, width, height, flags,
  343. fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
  344. #elif LL_WINDOWS
  345. new_window = new LLWindowWin32(callbacks,
  346. title, name, x, y, width, height, flags,
  347. fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
  348. #elif LL_DARWIN
  349. new_window = new LLWindowMacOSX(callbacks,
  350. title, name, x, y, width, height, flags,
  351. fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
  352. #endif
  353. }
  354. else
  355. {
  356. new_window = new LLWindowHeadless(callbacks,
  357. title, name, x, y, width, height, flags,
  358. fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
  359. }
  360. if (FALSE == new_window->isValid())
  361. {
  362. delete new_window;
  363. llwarns << "LLWindowManager::create() : Error creating window." << llendl;
  364. return NULL;
  365. }
  366. sWindowList.insert(new_window);
  367. return new_window;
  368. }
  369. BOOL LLWindowManager::destroyWindow(LLWindow* window)
  370. {
  371. if (sWindowList.find(window) == sWindowList.end())
  372. {
  373. llerrs << "LLWindowManager::destroyWindow() : Window pointer not valid, this window doesn't exist!"
  374. << llendl;
  375. return FALSE;
  376. }
  377. window->close();
  378. sWindowList.erase(window);
  379. delete window;
  380. return TRUE;
  381. }
  382. BOOL LLWindowManager::isWindowValid(LLWindow *window)
  383. {
  384. return sWindowList.find(window) != sWindowList.end();
  385. }