PageRenderTime 193ms CodeModel.GetById 43ms app.highlight 136ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llwindow/llwindowwin32.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2253 lines | 1670 code | 321 blank | 262 comment | 234 complexity | 671c1e52977dd8d0791b4e195087f1b2 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llwindowwin32.cpp
   3 * @brief Platform-dependent implementation of llwindow
   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
  29#if LL_WINDOWS && !LL_MESA_HEADLESS
  30
  31#include "llwindowwin32.h"
  32
  33// LLWindow library includes
  34#include "llkeyboardwin32.h"
  35#include "lldragdropwin32.h"
  36#include "llpreeditor.h"
  37#include "llwindowcallbacks.h"
  38
  39// Linden library includes
  40#include "llerror.h"
  41#include "llgl.h"
  42#include "llstring.h"
  43#include "lldir.h"
  44#include "llglslshader.h"
  45
  46// System includes
  47#include <commdlg.h>
  48#include <WinUser.h>
  49#include <mapi.h>
  50#include <process.h>	// for _spawn
  51#include <shellapi.h>
  52#include <fstream>
  53#include <Imm.h>
  54
  55// Require DirectInput version 8
  56#define DIRECTINPUT_VERSION 0x0800
  57
  58#include <dinput.h>
  59#include <Dbt.h.>
  60
  61#include "llmemtype.h"
  62// culled from winuser.h
  63#ifndef WM_MOUSEWHEEL /* Added to be compatible with later SDK's */
  64const S32	WM_MOUSEWHEEL = 0x020A;
  65#endif
  66#ifndef WHEEL_DELTA /* Added to be compatible with later SDK's */
  67const S32	WHEEL_DELTA = 120;     /* Value for rolling one detent */
  68#endif
  69const S32	MAX_MESSAGE_PER_UPDATE = 20;
  70const S32	BITS_PER_PIXEL = 32;
  71const S32	MAX_NUM_RESOLUTIONS = 32;
  72const F32	ICON_FLASH_TIME = 0.5f;
  73
  74extern BOOL gDebugWindowProc;
  75
  76LPWSTR gIconResource = IDI_APPLICATION;
  77
  78LLW32MsgCallback gAsyncMsgCallback = NULL;
  79
  80//
  81// LLWindowWin32
  82//
  83
  84void show_window_creation_error(const std::string& title)
  85{
  86	LL_WARNS("Window") << title << LL_ENDL;
  87}
  88
  89//static
  90BOOL LLWindowWin32::sIsClassRegistered = FALSE;
  91
  92BOOL	LLWindowWin32::sLanguageTextInputAllowed = TRUE;
  93BOOL	LLWindowWin32::sWinIMEOpened = FALSE;
  94HKL		LLWindowWin32::sWinInputLocale = 0;
  95DWORD	LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE;
  96DWORD	LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC;
  97LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1);
  98
  99// The following class LLWinImm delegates Windows IMM APIs.
 100// We need this because some language versions of Windows,
 101// e.g., US version of Windows XP, doesn't install IMM32.DLL
 102// as a default, and we can't link against imm32.lib statically.
 103// I believe DLL loading of this type is best suited to do
 104// in a static initialization of a class.  What I'm not sure is
 105// whether it follows the Linden Conding Standard... 
 106// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members
 107
 108class LLWinImm
 109{
 110public:
 111	static bool		isAvailable() { return sTheInstance.mHImmDll != NULL; }
 112
 113public:
 114	// Wrappers for IMM API.
 115	static BOOL		isIME(HKL hkl);															
 116	static HWND		getDefaultIMEWnd(HWND hwnd);
 117	static HIMC		getContext(HWND hwnd);													
 118	static BOOL		releaseContext(HWND hwnd, HIMC himc);
 119	static BOOL		getOpenStatus(HIMC himc);												
 120	static BOOL		setOpenStatus(HIMC himc, BOOL status);									
 121	static BOOL		getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);	
 122	static BOOL		setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);		
 123	static BOOL		getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					
 124	static BOOL		setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					
 125	static LONG		getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length);
 126	static BOOL		setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength);
 127	static BOOL		setCompositionFont(HIMC himc, LPLOGFONTW logfont);
 128	static BOOL		setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form);
 129	static BOOL		notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value);
 130
 131private:
 132	LLWinImm();
 133	~LLWinImm();
 134
 135private:
 136	// Pointers to IMM API.
 137	BOOL	 	(WINAPI *mImmIsIME)(HKL);
 138	HWND		(WINAPI *mImmGetDefaultIMEWnd)(HWND);
 139	HIMC		(WINAPI *mImmGetContext)(HWND);
 140	BOOL		(WINAPI *mImmReleaseContext)(HWND, HIMC);
 141	BOOL		(WINAPI *mImmGetOpenStatus)(HIMC);
 142	BOOL		(WINAPI *mImmSetOpenStatus)(HIMC, BOOL);
 143	BOOL		(WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD);
 144	BOOL		(WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD);
 145	BOOL		(WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
 146	BOOL		(WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
 147	LONG		(WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD);
 148	BOOL		(WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD);
 149	BOOL		(WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW);
 150	BOOL		(WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM);
 151	BOOL		(WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD);
 152
 153private:
 154	HMODULE		mHImmDll;
 155	static LLWinImm sTheInstance;
 156};
 157
 158LLWinImm LLWinImm::sTheInstance;
 159
 160LLWinImm::LLWinImm() : mHImmDll(NULL)
 161{
 162	// Check system metrics 
 163	if ( !GetSystemMetrics( SM_DBCSENABLED ) )
 164		return;
 165	
 166
 167	mHImmDll = LoadLibraryA("Imm32");
 168	if (mHImmDll != NULL)
 169	{
 170		mImmIsIME               = (BOOL (WINAPI *)(HKL))                    GetProcAddress(mHImmDll, "ImmIsIME");
 171		mImmGetDefaultIMEWnd	= (HWND (WINAPI *)(HWND))					GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd");
 172		mImmGetContext          = (HIMC (WINAPI *)(HWND))                   GetProcAddress(mHImmDll, "ImmGetContext");
 173		mImmReleaseContext      = (BOOL (WINAPI *)(HWND, HIMC))             GetProcAddress(mHImmDll, "ImmReleaseContext");
 174		mImmGetOpenStatus       = (BOOL (WINAPI *)(HIMC))                   GetProcAddress(mHImmDll, "ImmGetOpenStatus");
 175		mImmSetOpenStatus       = (BOOL (WINAPI *)(HIMC, BOOL))             GetProcAddress(mHImmDll, "ImmSetOpenStatus");
 176		mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus");
 177		mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD))     GetProcAddress(mHImmDll, "ImmSetConversionStatus");
 178		mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmGetCompositionWindow");
 179		mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmSetCompositionWindow");
 180		mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD))					GetProcAddress(mHImmDll, "ImmGetCompositionStringW");
 181		mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD))	GetProcAddress(mHImmDll, "ImmSetCompositionStringW");
 182		mImmSetCompositionFont  = (BOOL (WINAPI *)(HIMC, LPLOGFONTW))		GetProcAddress(mHImmDll, "ImmSetCompositionFontW");
 183		mImmSetCandidateWindow  = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM))  GetProcAddress(mHImmDll, "ImmSetCandidateWindow");
 184		mImmNotifyIME			= (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD))	GetProcAddress(mHImmDll, "ImmNotifyIME");
 185
 186		if (mImmIsIME == NULL ||
 187			mImmGetDefaultIMEWnd == NULL ||
 188			mImmGetContext == NULL ||
 189			mImmReleaseContext == NULL ||
 190			mImmGetOpenStatus == NULL ||
 191			mImmSetOpenStatus == NULL ||
 192			mImmGetConversionStatus == NULL ||
 193			mImmSetConversionStatus == NULL ||
 194			mImmGetCompostitionWindow == NULL ||
 195			mImmSetCompostitionWindow == NULL ||
 196			mImmGetCompositionString == NULL ||
 197			mImmSetCompositionString == NULL ||
 198			mImmSetCompositionFont == NULL ||
 199			mImmSetCandidateWindow == NULL ||
 200			mImmNotifyIME == NULL)
 201		{
 202			// If any of the above API entires are not found, we can't use IMM API.  
 203			// So, turn off the IMM support.  We should log some warning message in 
 204			// the case, since it is very unusual; these APIs are available from 
 205			// the beginning, and all versions of IMM32.DLL should have them all.  
 206			// Unfortunately, this code may be executed before initialization of 
 207			// the logging channel (llwarns), and we can't do it here...  Yes, this 
 208			// is one of disadvantages to use static constraction to DLL loading. 
 209			FreeLibrary(mHImmDll);
 210			mHImmDll = NULL;
 211
 212			// If we unload the library, make sure all the function pointers are cleared
 213			mImmIsIME = NULL;
 214			mImmGetDefaultIMEWnd = NULL;
 215			mImmGetContext = NULL;
 216			mImmReleaseContext = NULL;
 217			mImmGetOpenStatus = NULL;
 218			mImmSetOpenStatus = NULL;
 219			mImmGetConversionStatus = NULL;
 220			mImmSetConversionStatus = NULL;
 221			mImmGetCompostitionWindow = NULL;
 222			mImmSetCompostitionWindow = NULL;
 223			mImmGetCompositionString = NULL;
 224			mImmSetCompositionString = NULL;
 225			mImmSetCompositionFont = NULL;
 226			mImmSetCandidateWindow = NULL;
 227			mImmNotifyIME = NULL;
 228		}
 229	}
 230}
 231
 232
 233// static 
 234BOOL	LLWinImm::isIME(HKL hkl)															
 235{ 
 236	if ( sTheInstance.mImmIsIME )
 237		return sTheInstance.mImmIsIME(hkl); 
 238	return FALSE;
 239}
 240
 241// static 
 242HIMC		LLWinImm::getContext(HWND hwnd)
 243{
 244	if ( sTheInstance.mImmGetContext )
 245		return sTheInstance.mImmGetContext(hwnd); 
 246	return 0;
 247}
 248
 249//static 
 250BOOL		LLWinImm::releaseContext(HWND hwnd, HIMC himc)
 251{ 
 252	if ( sTheInstance.mImmIsIME )
 253		return sTheInstance.mImmReleaseContext(hwnd, himc); 
 254	return FALSE;
 255}
 256
 257// static 
 258BOOL		LLWinImm::getOpenStatus(HIMC himc)
 259{ 
 260	if ( sTheInstance.mImmGetOpenStatus )
 261		return sTheInstance.mImmGetOpenStatus(himc); 
 262	return FALSE;
 263}
 264
 265// static 
 266BOOL		LLWinImm::setOpenStatus(HIMC himc, BOOL status)									
 267{ 
 268	if ( sTheInstance.mImmSetOpenStatus )
 269		return sTheInstance.mImmSetOpenStatus(himc, status); 
 270	return FALSE;
 271}
 272
 273// static 
 274BOOL		LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)	
 275{ 
 276	if ( sTheInstance.mImmGetConversionStatus )
 277		return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); 
 278	return FALSE;
 279}
 280
 281// static 
 282BOOL		LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)		
 283{ 
 284	if ( sTheInstance.mImmSetConversionStatus )
 285		return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); 
 286	return FALSE;
 287}
 288
 289// static 
 290BOOL		LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					
 291{ 
 292	if ( sTheInstance.mImmGetCompostitionWindow )
 293		return sTheInstance.mImmGetCompostitionWindow(himc, form);	
 294	return FALSE;
 295}
 296
 297// static 
 298BOOL		LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					
 299{ 
 300	if ( sTheInstance.mImmSetCompostitionWindow )
 301		return sTheInstance.mImmSetCompostitionWindow(himc, form);	
 302	return FALSE;
 303}
 304
 305
 306// static 
 307LONG		LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length)					
 308{ 
 309	if ( sTheInstance.mImmGetCompositionString )
 310		return sTheInstance.mImmGetCompositionString(himc, index, data, length);	
 311	return FALSE;
 312}
 313
 314
 315// static 
 316BOOL		LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)					
 317{ 
 318	if ( sTheInstance.mImmSetCompositionString )
 319		return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);	
 320	return FALSE;
 321}
 322
 323// static 
 324BOOL		LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)					
 325{ 
 326	if ( sTheInstance.mImmSetCompositionFont )
 327		return sTheInstance.mImmSetCompositionFont(himc, pFont);	
 328	return FALSE;
 329}
 330
 331// static 
 332BOOL		LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)					
 333{ 
 334	if ( sTheInstance.mImmSetCandidateWindow )
 335		return sTheInstance.mImmSetCandidateWindow(himc, form);	
 336	return FALSE;
 337}
 338
 339// static 
 340BOOL		LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)					
 341{ 
 342	if ( sTheInstance.mImmNotifyIME )
 343		return sTheInstance.mImmNotifyIME(himc, action, index, value);	
 344	return FALSE;
 345}
 346
 347
 348
 349
 350// ----------------------------------------------------------------------------------------
 351LLWinImm::~LLWinImm()
 352{
 353	if (mHImmDll != NULL)
 354	{
 355		FreeLibrary(mHImmDll);
 356		mHImmDll = NULL;
 357	}
 358}
 359
 360
 361LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
 362							 const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
 363							 S32 height, U32 flags, 
 364							 BOOL fullscreen, BOOL clearBg,
 365							 BOOL disable_vsync, BOOL use_gl,
 366							 BOOL ignore_pixel_depth,
 367							 U32 fsaa_samples)
 368	: LLWindow(callbacks, fullscreen, flags)
 369{
 370	mFSAASamples = fsaa_samples;
 371	mIconResource = gIconResource;
 372	mOverrideAspectRatio = 0.f;
 373	mNativeAspectRatio = 0.f;
 374	mMousePositionModified = FALSE;
 375	mInputProcessingPaused = FALSE;
 376	mPreeditor = NULL;
 377	mKeyCharCode = 0;
 378	mKeyScanCode = 0;
 379	mKeyVirtualKey = 0;
 380	mhDC = NULL;
 381	mhRC = NULL;
 382
 383	// Initialize the keyboard
 384	gKeyboard = new LLKeyboardWin32();
 385	gKeyboard->setCallbacks(callbacks);
 386
 387	// Initialize the Drag and Drop functionality
 388	mDragDrop = new LLDragDropWin32;
 389
 390	// Initialize (boot strap) the Language text input management,
 391	// based on the system's (user's) default settings.
 392	allowLanguageTextInput(mPreeditor, FALSE);
 393
 394	WNDCLASS		wc;
 395	RECT			window_rect;
 396
 397	// Set the window title
 398	if (title.empty())
 399	{
 400		mWindowTitle = new WCHAR[50];
 401		wsprintf(mWindowTitle, L"OpenGL Window");
 402	}
 403	else
 404	{
 405		mWindowTitle = new WCHAR[256]; // Assume title length < 255 chars.
 406		mbstowcs(mWindowTitle, title.c_str(), 255);
 407		mWindowTitle[255] = 0;
 408	}
 409
 410	// Set the window class name
 411	if (name.empty())
 412	{
 413		mWindowClassName = new WCHAR[50];
 414		wsprintf(mWindowClassName, L"OpenGL Window");
 415	}
 416	else
 417	{
 418		mWindowClassName = new WCHAR[256]; // Assume title length < 255 chars.
 419		mbstowcs(mWindowClassName, name.c_str(), 255);
 420		mWindowClassName[255] = 0;
 421	}
 422
 423
 424	// We're not clipping yet
 425	SetRect( &mOldMouseClip, 0, 0, 0, 0 );
 426
 427	// Make an instance of our window then define the window class
 428	mhInstance = GetModuleHandle(NULL);
 429	mWndProc = NULL;
 430
 431	mSwapMethod = SWAP_METHOD_UNDEFINED;
 432
 433	// No WPARAM yet.
 434	mLastSizeWParam = 0;
 435
 436	// Windows GDI rects don't include rightmost pixel
 437	window_rect.left = (long) 0;
 438	window_rect.right = (long) width;
 439	window_rect.top = (long) 0;
 440	window_rect.bottom = (long) height;
 441
 442	// Grab screen size to sanitize the window
 443	S32 window_border_y = GetSystemMetrics(SM_CYBORDER);
 444	S32 virtual_screen_x = GetSystemMetrics(SM_XVIRTUALSCREEN); 
 445	S32 virtual_screen_y = GetSystemMetrics(SM_YVIRTUALSCREEN); 
 446	S32 virtual_screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
 447	S32 virtual_screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
 448
 449	if (x < virtual_screen_x) x = virtual_screen_x;
 450	if (y < virtual_screen_y - window_border_y) y = virtual_screen_y - window_border_y;
 451
 452	if (x + width > virtual_screen_x + virtual_screen_width) x = virtual_screen_x + virtual_screen_width - width;
 453	if (y + height > virtual_screen_y + virtual_screen_height) y = virtual_screen_y + virtual_screen_height - height;
 454
 455	if (!sIsClassRegistered)
 456	{
 457		// Force redraw when resized and create a private device context
 458
 459		// Makes double click messages.
 460		wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
 461
 462		// Set message handler function
 463		wc.lpfnWndProc = (WNDPROC) mainWindowProc;
 464
 465		// unused
 466		wc.cbClsExtra = 0;
 467		wc.cbWndExtra = 0;
 468
 469		wc.hInstance = mhInstance;
 470		wc.hIcon = LoadIcon(mhInstance, mIconResource);
 471
 472		// We will set the cursor ourselves
 473		wc.hCursor = NULL;
 474
 475		// background color is not used
 476		if (clearBg)
 477		{
 478			wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
 479		}
 480		else
 481		{
 482			wc.hbrBackground = (HBRUSH) NULL;
 483		}
 484
 485		// we don't use windows menus
 486		wc.lpszMenuName = NULL;
 487
 488		wc.lpszClassName = mWindowClassName;
 489
 490		if (!RegisterClass(&wc))
 491		{
 492			OSMessageBox(mCallbacks->translateString("MBRegClassFailed"), 
 493				mCallbacks->translateString("MBError"), OSMB_OK);
 494			return;
 495		}
 496		sIsClassRegistered = TRUE;
 497	}
 498
 499	//-----------------------------------------------------------------------
 500	// Get the current refresh rate
 501	//-----------------------------------------------------------------------
 502
 503	DEVMODE dev_mode;
 504	::ZeroMemory(&dev_mode, sizeof(DEVMODE));
 505	dev_mode.dmSize = sizeof(DEVMODE);
 506	DWORD current_refresh;
 507	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
 508	{
 509		current_refresh = dev_mode.dmDisplayFrequency;
 510		mNativeAspectRatio = ((F32)dev_mode.dmPelsWidth) / ((F32)dev_mode.dmPelsHeight);
 511	}
 512	else
 513	{
 514		current_refresh = 60;
 515	}
 516
 517	//-----------------------------------------------------------------------
 518	// Drop resolution and go fullscreen
 519	// use a display mode with our desired size and depth, with a refresh
 520	// rate as close at possible to the users' default
 521	//-----------------------------------------------------------------------
 522	if (mFullscreen)
 523	{
 524		BOOL success = FALSE;
 525		DWORD closest_refresh = 0;
 526
 527		for (S32 mode_num = 0;; mode_num++)
 528		{
 529			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
 530			{
 531				break;
 532			}
 533
 534			if (dev_mode.dmPelsWidth == width &&
 535				dev_mode.dmPelsHeight == height &&
 536				dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
 537			{
 538				success = TRUE;
 539				if ((dev_mode.dmDisplayFrequency - current_refresh)
 540					< (closest_refresh - current_refresh))
 541				{
 542					closest_refresh = dev_mode.dmDisplayFrequency;
 543				}
 544			}
 545		}
 546
 547		if (closest_refresh == 0)
 548		{
 549			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
 550			//success = FALSE;
 551
 552			if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
 553			{
 554				success = FALSE;
 555			}
 556			else
 557			{
 558				if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
 559				{
 560					LL_WARNS("Window") << "Current BBP is OK falling back to that" << LL_ENDL;
 561					window_rect.right=width=dev_mode.dmPelsWidth;
 562					window_rect.bottom=height=dev_mode.dmPelsHeight;
 563					success = TRUE;
 564				}
 565				else
 566				{
 567					LL_WARNS("Window") << "Current BBP is BAD" << LL_ENDL;
 568					success = FALSE;
 569				}
 570			}
 571		}
 572
 573		// If we found a good resolution, use it.
 574		if (success)
 575		{
 576			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
 577		}
 578
 579		// Keep a copy of the actual current device mode in case we minimize 
 580		// and change the screen resolution.   JC
 581		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
 582
 583		// If it failed, we don't want to run fullscreen
 584		if (success)
 585		{
 586			mFullscreen = TRUE;
 587			mFullscreenWidth   = dev_mode.dmPelsWidth;
 588			mFullscreenHeight  = dev_mode.dmPelsHeight;
 589			mFullscreenBits    = dev_mode.dmBitsPerPel;
 590			mFullscreenRefresh = dev_mode.dmDisplayFrequency;
 591
 592			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
 593				<< "x"   << dev_mode.dmPelsHeight
 594				<< "x"   << dev_mode.dmBitsPerPel
 595				<< " @ " << dev_mode.dmDisplayFrequency
 596				<< LL_ENDL;
 597		}
 598		else
 599		{
 600			mFullscreen = FALSE;
 601			mFullscreenWidth   = -1;
 602			mFullscreenHeight  = -1;
 603			mFullscreenBits    = -1;
 604			mFullscreenRefresh = -1;
 605
 606			std::map<std::string,std::string> args;
 607			args["[WIDTH]"] = llformat("%d", width);
 608			args["[HEIGHT]"] = llformat ("%d", height);
 609			OSMessageBox(mCallbacks->translateString("MBFullScreenErr", args),
 610				mCallbacks->translateString("MBError"), OSMB_OK);
 611		}
 612	}
 613
 614	// TODO: add this after resolving _WIN32_WINNT issue
 615	//	if (!fullscreen)
 616	//	{
 617	//		TRACKMOUSEEVENT track_mouse_event;
 618	//		track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT );
 619	//		track_mouse_event.dwFlags = TME_LEAVE;
 620	//		track_mouse_event.hwndTrack = mWindowHandle;
 621	//		track_mouse_event.dwHoverTime = HOVER_DEFAULT;
 622	//		TrackMouseEvent( &track_mouse_event ); 
 623	//	}
 624
 625
 626	//-----------------------------------------------------------------------
 627	// Create GL drawing context
 628	//-----------------------------------------------------------------------
 629	LLCoordScreen windowPos(x,y);
 630	LLCoordScreen windowSize(window_rect.right - window_rect.left,
 631							 window_rect.bottom - window_rect.top);
 632	if (!switchContext(mFullscreen, windowSize, TRUE, &windowPos))
 633	{
 634		return;
 635	}
 636	
 637	//start with arrow cursor
 638	initCursors();
 639	setCursor( UI_CURSOR_ARROW );
 640
 641	// Initialize (boot strap) the Language text input management,
 642	// based on the system's (or user's) default settings.
 643	allowLanguageTextInput(NULL, FALSE);
 644}
 645
 646
 647LLWindowWin32::~LLWindowWin32()
 648{
 649	delete mDragDrop;
 650
 651	delete [] mWindowTitle;
 652	mWindowTitle = NULL;
 653
 654	delete [] mSupportedResolutions;
 655	mSupportedResolutions = NULL;
 656
 657	delete mWindowClassName;
 658	mWindowClassName = NULL;
 659}
 660
 661void LLWindowWin32::show()
 662{
 663	ShowWindow(mWindowHandle, SW_SHOW);
 664	SetForegroundWindow(mWindowHandle);
 665	SetFocus(mWindowHandle);
 666}
 667
 668void LLWindowWin32::hide()
 669{
 670	setMouseClipping(FALSE);
 671	ShowWindow(mWindowHandle, SW_HIDE);
 672}
 673
 674//virtual
 675void LLWindowWin32::minimize()
 676{
 677	setMouseClipping(FALSE);
 678	showCursor();
 679	ShowWindow(mWindowHandle, SW_MINIMIZE);
 680}
 681
 682//virtual
 683void LLWindowWin32::restore()
 684{
 685	ShowWindow(mWindowHandle, SW_RESTORE);
 686	SetForegroundWindow(mWindowHandle);
 687	SetFocus(mWindowHandle);
 688}
 689
 690
 691// close() destroys all OS-specific code associated with a window.
 692// Usually called from LLWindowManager::destroyWindow()
 693void LLWindowWin32::close()
 694{
 695	LL_DEBUGS("Window") << "Closing LLWindowWin32" << LL_ENDL;
 696	// Is window is already closed?
 697	if (!mWindowHandle)
 698	{
 699		return;
 700	}
 701
 702	mDragDrop->reset();
 703
 704	// Make sure cursor is visible and we haven't mangled the clipping state.
 705	setMouseClipping(FALSE);
 706	showCursor();
 707
 708	// Go back to screen mode written in the registry.
 709	if (mFullscreen)
 710	{
 711		resetDisplayResolution();
 712	}
 713
 714	// Clean up remaining GL state
 715	LL_DEBUGS("Window") << "Shutting down GL" << LL_ENDL;
 716	gGLManager.shutdownGL();
 717
 718	LL_DEBUGS("Window") << "Releasing Context" << LL_ENDL;
 719	if (mhRC)
 720	{
 721		if (!wglMakeCurrent(NULL, NULL))
 722		{
 723			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL;
 724		}
 725
 726		if (!wglDeleteContext(mhRC))
 727		{
 728			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL;
 729		}
 730
 731		mhRC = NULL;
 732	}
 733
 734	// Restore gamma to the system values.
 735	restoreGamma();
 736
 737	if (mhDC && !ReleaseDC(mWindowHandle, mhDC))
 738	{
 739		LL_WARNS("Window") << "Release of ghDC failed" << LL_ENDL;
 740		mhDC = NULL;
 741	}
 742
 743	LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
 744	
 745	// Don't process events in our mainWindowProc any longer.
 746	SetWindowLong(mWindowHandle, GWL_USERDATA, NULL);
 747
 748	// Make sure we don't leave a blank toolbar button.
 749	ShowWindow(mWindowHandle, SW_HIDE);
 750
 751	// This causes WM_DESTROY to be sent *immediately*
 752	if (!DestroyWindow(mWindowHandle))
 753	{
 754		OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"),
 755			mCallbacks->translateString("MBShutdownErr"),
 756			OSMB_OK);
 757	}
 758
 759	mWindowHandle = NULL;
 760}
 761
 762BOOL LLWindowWin32::isValid()
 763{
 764	return (mWindowHandle != NULL);
 765}
 766
 767BOOL LLWindowWin32::getVisible()
 768{
 769	return (mWindowHandle && IsWindowVisible(mWindowHandle));
 770}
 771
 772BOOL LLWindowWin32::getMinimized()
 773{
 774	return (mWindowHandle && IsIconic(mWindowHandle));
 775}
 776
 777BOOL LLWindowWin32::getMaximized()
 778{
 779	return (mWindowHandle && IsZoomed(mWindowHandle));
 780}
 781
 782BOOL LLWindowWin32::maximize()
 783{
 784	BOOL success = FALSE;
 785	if (!mWindowHandle) return success;
 786
 787	WINDOWPLACEMENT placement;
 788	placement.length = sizeof(WINDOWPLACEMENT);
 789
 790	success = GetWindowPlacement(mWindowHandle, &placement);
 791	if (!success) return success;
 792
 793	placement.showCmd = SW_MAXIMIZE;
 794
 795	success = SetWindowPlacement(mWindowHandle, &placement);
 796	return success;
 797}
 798
 799BOOL LLWindowWin32::getFullscreen()
 800{
 801	return mFullscreen;
 802}
 803
 804BOOL LLWindowWin32::getPosition(LLCoordScreen *position)
 805{
 806	RECT window_rect;
 807
 808	if (!mWindowHandle ||
 809		!GetWindowRect(mWindowHandle, &window_rect) ||
 810		NULL == position)
 811	{
 812		return FALSE;
 813	}
 814
 815	position->mX = window_rect.left;
 816	position->mY = window_rect.top;
 817	return TRUE;
 818}
 819
 820BOOL LLWindowWin32::getSize(LLCoordScreen *size)
 821{
 822	RECT window_rect;
 823
 824	if (!mWindowHandle ||
 825		!GetWindowRect(mWindowHandle, &window_rect) ||
 826		NULL == size)
 827	{
 828		return FALSE;
 829	}
 830
 831	size->mX = window_rect.right - window_rect.left;
 832	size->mY = window_rect.bottom - window_rect.top;
 833	return TRUE;
 834}
 835
 836BOOL LLWindowWin32::getSize(LLCoordWindow *size)
 837{
 838	RECT client_rect;
 839
 840	if (!mWindowHandle ||
 841		!GetClientRect(mWindowHandle, &client_rect) ||
 842		NULL == size)
 843	{
 844		return FALSE;
 845	}
 846
 847	size->mX = client_rect.right - client_rect.left;
 848	size->mY = client_rect.bottom - client_rect.top;
 849	return TRUE;
 850}
 851
 852BOOL LLWindowWin32::setPosition(const LLCoordScreen position)
 853{
 854	LLCoordScreen size;
 855
 856	if (!mWindowHandle)
 857	{
 858		return FALSE;
 859	}
 860	getSize(&size);
 861	moveWindow(position, size);
 862	return TRUE;
 863}
 864
 865BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size)
 866{
 867	LLCoordScreen position;
 868
 869	getPosition(&position);
 870	if (!mWindowHandle)
 871	{
 872		return FALSE;
 873	}
 874
 875	moveWindow(position, size);
 876	return TRUE;
 877}
 878
 879// changing fullscreen resolution
 880BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp)
 881{
 882	GLuint	pixel_format;
 883	DEVMODE dev_mode;
 884	::ZeroMemory(&dev_mode, sizeof(DEVMODE));
 885	dev_mode.dmSize = sizeof(DEVMODE);
 886	DWORD	current_refresh;
 887	DWORD	dw_ex_style;
 888	DWORD	dw_style;
 889	RECT	window_rect;
 890	S32 width = size.mX;
 891	S32 height = size.mY;
 892	BOOL auto_show = FALSE;
 893
 894	if (mhRC)
 895	{
 896		auto_show = TRUE;
 897		resetDisplayResolution();
 898	}
 899
 900	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
 901	{
 902		current_refresh = dev_mode.dmDisplayFrequency;
 903	}
 904	else
 905	{
 906		current_refresh = 60;
 907	}
 908
 909	gGLManager.shutdownGL();
 910	//destroy gl context
 911	if (mhRC)
 912	{
 913		if (!wglMakeCurrent(NULL, NULL))
 914		{
 915			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL;
 916		}
 917
 918		if (!wglDeleteContext(mhRC))
 919		{
 920			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL;
 921		}
 922
 923		mhRC = NULL;
 924	}
 925
 926	if (fullscreen)
 927	{
 928		mFullscreen = TRUE;
 929		BOOL success = FALSE;
 930		DWORD closest_refresh = 0;
 931
 932		for (S32 mode_num = 0;; mode_num++)
 933		{
 934			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
 935			{
 936				break;
 937			}
 938
 939			if (dev_mode.dmPelsWidth == width &&
 940				dev_mode.dmPelsHeight == height &&
 941				dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
 942			{
 943				success = TRUE;
 944				if ((dev_mode.dmDisplayFrequency - current_refresh)
 945					< (closest_refresh - current_refresh))
 946				{
 947					closest_refresh = dev_mode.dmDisplayFrequency;
 948				}
 949			}
 950		}
 951
 952		if (closest_refresh == 0)
 953		{
 954			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
 955			return FALSE;
 956		}
 957
 958		// If we found a good resolution, use it.
 959		if (success)
 960		{
 961			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
 962		}
 963
 964		// Keep a copy of the actual current device mode in case we minimize 
 965		// and change the screen resolution.   JC
 966		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
 967
 968		if (success)
 969		{
 970			mFullscreen = TRUE;
 971			mFullscreenWidth   = dev_mode.dmPelsWidth;
 972			mFullscreenHeight  = dev_mode.dmPelsHeight;
 973			mFullscreenBits    = dev_mode.dmBitsPerPel;
 974			mFullscreenRefresh = dev_mode.dmDisplayFrequency;
 975
 976			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
 977				<< "x"   << dev_mode.dmPelsHeight
 978				<< "x"   << dev_mode.dmBitsPerPel
 979				<< " @ " << dev_mode.dmDisplayFrequency
 980				<< LL_ENDL;
 981
 982			window_rect.left = (long) 0;
 983			window_rect.right = (long) width;			// Windows GDI rects don't include rightmost pixel
 984			window_rect.top = (long) 0;
 985			window_rect.bottom = (long) height;
 986			dw_ex_style = WS_EX_APPWINDOW;
 987			dw_style = WS_POPUP;
 988
 989			// Move window borders out not to cover window contents
 990			AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style);
 991		}
 992		// If it failed, we don't want to run fullscreen
 993		else
 994		{
 995			mFullscreen = FALSE;
 996			mFullscreenWidth   = -1;
 997			mFullscreenHeight  = -1;
 998			mFullscreenBits    = -1;
 999			mFullscreenRefresh = -1;
1000
1001			LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL;
1002			return FALSE;
1003		}
1004	}
1005	else
1006	{
1007		mFullscreen = FALSE;
1008		window_rect.left = (long) (posp ? posp->mX : 0);
1009		window_rect.right = (long) width + window_rect.left;			// Windows GDI rects don't include rightmost pixel
1010		window_rect.top = (long) (posp ? posp->mY : 0);
1011		window_rect.bottom = (long) height + window_rect.top;
1012		// Window with an edge
1013		dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
1014		dw_style = WS_OVERLAPPEDWINDOW;
1015	}
1016
1017	// don't post quit messages when destroying old windows
1018	mPostQuit = FALSE;
1019
1020	// create window
1021	DestroyWindow(mWindowHandle);
1022	mWindowHandle = CreateWindowEx(dw_ex_style,
1023		mWindowClassName,
1024		mWindowTitle,
1025		WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
1026		window_rect.left,								// x pos
1027		window_rect.top,								// y pos
1028		window_rect.right - window_rect.left,			// width
1029		window_rect.bottom - window_rect.top,			// height
1030		NULL,
1031		NULL,
1032		mhInstance,
1033		NULL);
1034
1035	LL_INFOS("Window") << "window is created." << llendl ;
1036
1037	//-----------------------------------------------------------------------
1038	// Create GL drawing context
1039	//-----------------------------------------------------------------------
1040	static PIXELFORMATDESCRIPTOR pfd =
1041	{
1042		sizeof(PIXELFORMATDESCRIPTOR), 
1043			1,
1044			PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 
1045			PFD_TYPE_RGBA,
1046			BITS_PER_PIXEL,
1047			0, 0, 0, 0, 0, 0,	// RGB bits and shift, unused
1048			8,					// alpha bits
1049			0,					// alpha shift
1050			0,					// accum bits
1051			0, 0, 0, 0,			// accum RGBA
1052			24,					// depth bits
1053			8,					// stencil bits, avi added for stencil test
1054			0,
1055			PFD_MAIN_PLANE,
1056			0,
1057			0, 0, 0
1058	};
1059
1060	if (!(mhDC = GetDC(mWindowHandle)))
1061	{
1062		close();
1063		OSMessageBox(mCallbacks->translateString("MBDevContextErr"),
1064			mCallbacks->translateString("MBError"), OSMB_OK);
1065		return FALSE;
1066	}
1067
1068	if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
1069	{
1070		close();
1071		OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
1072			mCallbacks->translateString("MBError"), OSMB_OK);
1073		return FALSE;
1074	}
1075
1076	// Verify what pixel format we actually received.
1077	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
1078		&pfd))
1079	{
1080		close();
1081		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"),
1082			mCallbacks->translateString("MBError"), OSMB_OK);
1083		return FALSE;
1084	}
1085
1086	// (EXP-1765) dump pixel data to see if there is a pattern that leads to unreproducible crash
1087	LL_INFOS("Window") << "--- begin pixel format dump ---" << llendl ;
1088	LL_INFOS("Window") << "pixel_format is " << pixel_format << llendl ;
1089	LL_INFOS("Window") << "pfd.nSize:            " << pfd.nSize << llendl ;
1090	LL_INFOS("Window") << "pfd.nVersion:         " << pfd.nVersion << llendl ;
1091	LL_INFOS("Window") << "pfd.dwFlags:          0x" << std::hex << pfd.dwFlags << std::dec << llendl ;
1092	LL_INFOS("Window") << "pfd.iPixelType:       " << (int)pfd.iPixelType << llendl ;
1093	LL_INFOS("Window") << "pfd.cColorBits:       " << (int)pfd.cColorBits << llendl ;
1094	LL_INFOS("Window") << "pfd.cRedBits:         " << (int)pfd.cRedBits << llendl ;
1095	LL_INFOS("Window") << "pfd.cRedShift:        " << (int)pfd.cRedShift << llendl ;
1096	LL_INFOS("Window") << "pfd.cGreenBits:       " << (int)pfd.cGreenBits << llendl ;
1097	LL_INFOS("Window") << "pfd.cGreenShift:      " << (int)pfd.cGreenShift << llendl ;
1098	LL_INFOS("Window") << "pfd.cBlueBits:        " << (int)pfd.cBlueBits << llendl ;
1099	LL_INFOS("Window") << "pfd.cBlueShift:       " << (int)pfd.cBlueShift << llendl ;
1100	LL_INFOS("Window") << "pfd.cAlphaBits:       " << (int)pfd.cAlphaBits << llendl ;
1101	LL_INFOS("Window") << "pfd.cAlphaShift:      " << (int)pfd.cAlphaShift << llendl ;
1102	LL_INFOS("Window") << "pfd.cAccumBits:       " << (int)pfd.cAccumBits << llendl ;
1103	LL_INFOS("Window") << "pfd.cAccumRedBits:    " << (int)pfd.cAccumRedBits << llendl ;
1104	LL_INFOS("Window") << "pfd.cAccumGreenBits:  " << (int)pfd.cAccumGreenBits << llendl ;
1105	LL_INFOS("Window") << "pfd.cAccumBlueBits:   " << (int)pfd.cAccumBlueBits << llendl ;
1106	LL_INFOS("Window") << "pfd.cAccumAlphaBits:  " << (int)pfd.cAccumAlphaBits << llendl ;
1107	LL_INFOS("Window") << "pfd.cDepthBits:       " << (int)pfd.cDepthBits << llendl ;
1108	LL_INFOS("Window") << "pfd.cStencilBits:     " << (int)pfd.cStencilBits << llendl ;
1109	LL_INFOS("Window") << "pfd.cAuxBuffers:      " << (int)pfd.cAuxBuffers << llendl ;
1110	LL_INFOS("Window") << "pfd.iLayerType:       " << (int)pfd.iLayerType << llendl ;
1111	LL_INFOS("Window") << "pfd.bReserved:        " << (int)pfd.bReserved << llendl ;
1112	LL_INFOS("Window") << "pfd.dwLayerMask:      " << pfd.dwLayerMask << llendl ;
1113	LL_INFOS("Window") << "pfd.dwVisibleMask:    " << pfd.dwVisibleMask << llendl ;
1114	LL_INFOS("Window") << "pfd.dwDamageMask:     " << pfd.dwDamageMask << llendl ;
1115	LL_INFOS("Window") << "--- end pixel format dump ---" << llendl ;
1116
1117	if (pfd.cColorBits < 32)
1118	{
1119		close();
1120		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"),
1121			mCallbacks->translateString("MBError"), OSMB_OK);
1122		return FALSE;
1123	}
1124
1125	if (pfd.cAlphaBits < 8)
1126	{
1127		close();
1128		OSMessageBox(mCallbacks->translateString("MBAlpha"),
1129			mCallbacks->translateString("MBError"), OSMB_OK);
1130		return FALSE;
1131	}
1132
1133	if (!SetPixelFormat(mhDC, pixel_format, &pfd))
1134	{
1135		close();
1136		OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
1137			mCallbacks->translateString("MBError"), OSMB_OK);
1138		return FALSE;
1139	}
1140
1141	if (!(mhRC = wglCreateContext(mhDC)))
1142	{
1143		close();
1144		OSMessageBox(mCallbacks->translateString("MBGLContextErr"),
1145			mCallbacks->translateString("MBError"), OSMB_OK);
1146		return FALSE;
1147	}
1148
1149	if (!wglMakeCurrent(mhDC, mhRC))
1150	{
1151		close();
1152		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"),
1153			mCallbacks->translateString("MBError"), OSMB_OK);
1154		return FALSE;
1155	}
1156
1157	LL_INFOS("Window") << "Drawing context is created." << llendl ;
1158
1159	gGLManager.initWGL();
1160	
1161	if (wglChoosePixelFormatARB)
1162	{
1163		// OK, at this point, use the ARB wglChoosePixelFormatsARB function to see if we
1164		// can get exactly what we want.
1165		GLint attrib_list[256];
1166		S32 cur_attrib = 0;
1167
1168		attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB;
1169		attrib_list[cur_attrib++] = 24;
1170
1171		attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB;
1172		attrib_list[cur_attrib++] = 8;
1173
1174		attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB;
1175		attrib_list[cur_attrib++] = GL_TRUE;
1176
1177		attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB;
1178		attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB;
1179
1180		attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB;
1181		attrib_list[cur_attrib++] = GL_TRUE;
1182
1183		attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB;
1184		attrib_list[cur_attrib++] = GL_TRUE;
1185
1186		attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
1187		attrib_list[cur_attrib++] = 24;
1188
1189		attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
1190		attrib_list[cur_attrib++] = 8;
1191
1192		U32 end_attrib = 0;
1193		if (mFSAASamples > 0)
1194		{
1195			end_attrib = cur_attrib;
1196			attrib_list[cur_attrib++] = WGL_SAMPLE_BUFFERS_ARB;
1197			attrib_list[cur_attrib++] = GL_TRUE;
1198
1199			attrib_list[cur_attrib++] = WGL_SAMPLES_ARB;
1200			attrib_list[cur_attrib++] = mFSAASamples;
1201		}
1202
1203		// End the list
1204		attrib_list[cur_attrib++] = 0;
1205
1206		GLint pixel_formats[256];
1207		U32 num_formats = 0;
1208
1209		// First we try and get a 32 bit depth pixel format
1210		BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
1211		
1212		while(!result && mFSAASamples > 0) 
1213		{
1214			llwarns << "FSAASamples: " << mFSAASamples << " not supported." << llendl ;
1215
1216			mFSAASamples /= 2 ; //try to decrease sample pixel number until to disable anti-aliasing
1217			if(mFSAASamples < 2)
1218			{
1219				mFSAASamples = 0 ;
1220			}
1221
1222			if (mFSAASamples > 0)
1223			{
1224				attrib_list[end_attrib + 3] = mFSAASamples;
1225			}
1226			else
1227			{
1228				cur_attrib = end_attrib ;
1229				end_attrib = 0 ;
1230				attrib_list[cur_attrib++] = 0 ; //end
1231			}
1232			result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
1233
1234			if(result)
1235			{
1236				llwarns << "Only support FSAASamples: " << mFSAASamples << llendl ;
1237			}
1238		}
1239
1240		if (!result)
1241		{
1242			llwarns << "mFSAASamples: " << mFSAASamples << llendl ;
1243
1244			close();
1245			show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit");
1246			return FALSE;
1247		}
1248
1249		if (!num_formats)
1250		{
1251			if (end_attrib > 0)
1252			{
1253				LL_INFOS("Window") << "No valid pixel format for " << mFSAASamples << "x anti-aliasing." << LL_ENDL;
1254				attrib_list[end_attrib] = 0;
1255
1256				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
1257				if (!result)
1258				{
1259					close();
1260					show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit no AA");
1261					return FALSE;
1262				}
1263			}
1264
1265			if (!num_formats)
1266			{
1267				LL_INFOS("Window") << "No 32 bit z-buffer, trying 24 bits instead" << LL_ENDL;
1268				// Try 24-bit format
1269				attrib_list[1] = 24;
1270				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
1271				if (!result)
1272				{
1273					close();
1274					show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
1275					return FALSE;
1276				}
1277
1278				if (!num_formats)
1279				{
1280					LL_WARNS("Window") << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << LL_ENDL;
1281					attrib_list[1] = 16;
1282					BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
1283					if (!result || !num_formats)
1284					{
1285						close();
1286						show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
1287						return FALSE;
1288					}
1289				}
1290			}
1291
1292			LL_INFOS("Window") << "Choosing pixel formats: " << num_formats << " pixel formats returned" << LL_ENDL;
1293		}
1294
1295		LL_INFOS("Window") << "pixel formats done." << llendl ;
1296
1297		S32 swap_method = 0;
1298		S32 cur_format = num_formats-1;
1299		GLint swap_query = WGL_SWAP_METHOD_ARB;
1300
1301		BOOL found_format = FALSE;
1302
1303		while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
1304		{
1305			if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0)
1306			{
1307				found_format = TRUE;
1308			}
1309			else
1310			{
1311				--cur_format;
1312			}
1313		}
1314		
1315		pixel_format = pixel_formats[cur_format];
1316		
1317		if (mhDC != 0)											// Does The Window Have A Device Context?
1318		{
1319			wglMakeCurrent(mhDC, 0);							// Set The Current Active Rendering Context To Zero
1320			if (mhRC != 0)										// Does The Window Have A Rendering Context?
1321			{
1322				wglDeleteContext (mhRC);							// Release The Rendering Context
1323				mhRC = 0;										// Zero The Rendering Context
1324
1325			}
1326			ReleaseDC (mWindowHandle, mhDC);						// Release The Device Context
1327			mhDC = 0;											// Zero The Device Context
1328		}
1329		DestroyWindow (mWindowHandle);									// Destroy The Window
1330		
1331
1332		mWindowHandle = CreateWindowEx(dw_ex_style,
1333			mWindowClassName,
1334			mWindowTitle,
1335			WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
1336			window_rect.left,								// x pos
1337			window_rect.top,								// y pos
1338			window_rect.right - window_rect.left,			// width
1339			window_rect.bottom - window_rect.top,			// height
1340			NULL,
1341			NULL,
1342			mhInstance,
1343			NULL);
1344
1345		LL_INFOS("Window") << "recreate window done." << llendl ;
1346
1347		if (!(mhDC = GetDC(mWindowHandle)))
1348		{
1349			close();
1350			OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
1351			return FALSE;
1352		}
1353
1354		if (!SetPixelFormat(mhDC, pixel_format, &pfd))
1355		{
1356			close();
1357			OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
1358				mCallbacks->translateString("MBError"), OSMB_OK);
1359			return FALSE;
1360		}
1361
1362		if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
1363		{
1364			switch (swap_method)
1365			{
1366			case WGL_SWAP_EXCHANGE_ARB:
1367				mSwapMethod = SWAP_METHOD_EXCHANGE;
1368				LL_DEBUGS("Window") << "Swap Method: Exchange" << LL_ENDL;
1369				break;
1370			case WGL_SWAP_COPY_ARB:
1371				mSwapMethod = SWAP_METHOD_COPY;
1372				LL_DEBUGS("Window") << "Swap Method: Copy" << LL_ENDL;
1373				break;
1374			case WGL_SWAP_UNDEFINED_ARB:
1375				mSwapMethod = SWAP_METHOD_UNDEFINED;
1376				LL_DEBUGS("Window") << "Swap Method: Undefined" << LL_ENDL;
1377				break;
1378			default:
1379				mSwapMethod = SWAP_METHOD_UNDEFINED;
1380				LL_DEBUGS("Window") << "Swap Method: Unknown" << LL_ENDL;
1381				break;
1382			}
1383		}		
1384	}
1385	else
1386	{
1387		LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL;
1388	}
1389
1390	// Verify what pixel format we actually received.
1391	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
1392		&pfd))
1393	{
1394		close();
1395		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK);
1396		return FALSE;
1397	}
1398
1399	LL_INFOS("Window") << "GL buffer: Color Bits " << S32(pfd.cColorBits) 
1400		<< " Alpha Bits " << S32(pfd.cAlphaBits)
1401		<< " Depth Bits " << S32(pfd.cDepthBits) 
1402		<< LL_ENDL;
1403
1404	// make sure we have 32 bits per pixel
1405	if (pfd.cColorBits < 32 || GetDeviceCaps(mhDC, BITSPIXEL) < 32)
1406	{
1407		close();
1408		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), mCallbacks->translateString("MBError"), OSMB_OK);
1409		return FALSE;
1410	}
1411
1412	if (pfd.cAlphaBits < 8)
1413	{
1414		close();
1415		OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK);
1416		return FALSE;
1417	}
1418
1419	mhRC = 0;
1420	if (wglCreateContextAttribsARB)
1421	{ //attempt to create a specific versioned context
1422		S32 attribs[] = 
1423		{ //start at 4.2
1424			WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
1425			WGL_CONTEXT_MINOR_VERSION_ARB, 2,
1426			WGL_CONTEXT_PROFILE_MASK_ARB,  LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
1427			WGL_CONTEXT_FLAGS_ARB, gDebugGL ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
1428			0
1429		};
1430
1431		bool done = false;
1432		while (!done)
1433		{
1434			mhRC = wglCreateContextAttribsARB(mhDC, mhRC, attribs);
1435
1436			if (!mhRC)
1437			{
1438				if (attribs[3] > 0)
1439				{ //decrement minor version
1440					attribs[3]--;
1441				}
1442				else if (attribs[1] > 3)
1443				{ //decrement major version and start minor version over at 3
1444					attribs[1]--;
1445					attribs[3] = 3;
1446				}
1447				else
1448				{ //we reached 3.0 and still failed, bail out
1449					done = true;
1450				}
1451			}
1452			else
1453			{
1454				llinfos << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << " context." << llendl;
1455				done = true;
1456
1457				if (LLRender::sGLCoreProfile)
1458				{
1459					LLGLSLShader::sNoFixedFunction = true;
1460				}
1461			}
1462		}
1463	}
1464
1465	if (!mhRC && !(mhRC = wglCreateContext(mhDC)))
1466	{
1467		close();
1468		OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
1469		return FALSE;
1470	}
1471
1472	if (!wglMakeCurrent(mhDC, mhRC))
1473	{
1474		close();
1475		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK);
1476		return FALSE;
1477	}
1478
1479	if (!gGLManager.initGL())
1480	{
1481		close();
1482		OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
1483		return FALSE;
1484	}
1485	
1486	// Disable vertical sync for swap
1487	if (disable_vsync && wglSwapIntervalEXT)
1488	{
1489		LL_DEBUGS("Window") << "Disabling vertical sync" << LL_ENDL;
1490		wglSwapIntervalEXT(0);
1491	}
1492	else
1493	{
1494		LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL;
1495	}
1496
1497	SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
1498
1499	// register this window as handling drag/drop events from the OS
1500	DragAcceptFiles( mWindowHandle, TRUE );
1501
1502	mDragDrop->init( mWindowHandle );
1503	
1504	//register joystick timer callback
1505	SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer
1506
1507	// ok to post quit messages now
1508	mPostQuit = TRUE;
1509
1510	if (auto_show)
1511	{
1512		show();
1513		glClearColor(0.0f, 0.0f, 0.0f, 0.f);
1514		glClear(GL_COLOR_BUFFER_BIT);
1515		swapBuffers();
1516	}
1517
1518	return TRUE;
1519}
1520
1521void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size )
1522{
1523	if( mIsMouseClipping )
1524	{
1525		RECT client_rect_in_screen_space;
1526		if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
1527		{
1528			ClipCursor( &client_rect_in_screen_space );
1529		}
1530	}
1531
1532	// if the window was already maximized, MoveWindow seems to still set the maximized flag even if
1533	// the window is smaller than maximized.
1534	// So we're going to do a restore first (which is a ShowWindow call) (SL-44655).
1535
1536	// THIS CAUSES DEV-15484 and DEV-15949 
1537	//ShowWindow(mWindowHandle, SW_RESTORE);
1538	// NOW we can call MoveWindow
1539	MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE);
1540}
1541
1542BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
1543{
1544	LLCoordScreen screen_pos;
1545
1546	mMousePositionModified = TRUE;
1547	if (!mWindowHandle)
1548	{
1549		return FALSE;
1550	}
1551
1552	if (!convertCoords(position, &screen_pos))
1553	{
1554		return FALSE;
1555	}
1556
1557	// Inform the application of the new mouse position (needed for per-frame
1558	// hover/picking to function).
1559	LLCoordGL gl_pos;
1560	convertCoords(position, &gl_pos);
1561	mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
1562	
1563	// DEV-18951 VWR-8524 Camera moves wildly when alt-clicking.
1564	// Because we have preemptively notified the application of the new
1565	// mouse position via handleMouseMove() above, we need to clear out
1566	// any stale mouse move events.  RN/JC
1567	MSG msg;
1568	while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
1569	{ }
1570
1571	return SetCursorPos(screen_pos.mX, screen_pos.mY);
1572}
1573
1574BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)
1575{
1576	POINT cursor_point;
1577	LLCoordScreen screen_pos;
1578
1579	if (!mWindowHandle ||
1580		!GetCursorPos(&cursor_point))
1581	{
1582		return FALSE;
1583	}
1584
1585	screen_pos.mX = cursor_point.x;
1586	screen_pos.mY = cursor_point.y;
1587
1588	return convertCoords(screen_pos, position);
1589}
1590
1591void LLWindowWin32::hideCursor()
1592{
1593	while (ShowCursor(FALSE) >= 0)
1594	{
1595		// nothing, wait for cursor to push down
1596	}
1597	mCursorHidden = TRUE;
1598	mHideCursorPermanent = TRUE;
1599}
1600
1601void LLWindowWin32::showCursor()
1602{
1603	// makes sure the cursor shows up
1604	while (ShowCursor(TRUE) < 0)
1605	{
1606		// do nothing, wait for cursor to pop out
1607	}
1608	mCursorHidden = FALSE;
1609	mHideCursorPermanent = FALSE;
1610}
1611
1612void LLWindowWin32::showCursorFromMouseMove()
1613{
1614	if (!mHideCursorPermanent)
1615	{
1616		showCursor();
1617	}
1618}
1619
1620void LLWindowWin32::hideCursorUntilMouseMove()
1621{
1622	if (!mHideCursorPermanent)
1623	{
1624		hideCursor();
1625		mHideCursorPermanent = FALSE;
1626	}
1627}
1628
1629BOOL LLWindowWin32::isCursorHidden()
1630{
1631	return mCursorHidden;
1632}
1633
1634
1635HCURSOR LLWindowWin32::loadColorCursor(LPCTSTR name)
1636{
1637	return (HCURSOR)LoadImage(mhInstance,
1638							  name,
1639							  IMAGE_CURSOR,
1640							  0,	// default width
1641							  0,	// default height
1642							  LR_DEFAULTCOLOR);
1643}
1644
1645
1646void LLWindowWin32::initCursors()
1647{
1648	mCursor[ UI_CURSOR_ARROW ]		= LoadCursor(NULL, IDC_ARROW);
1649	mCursor[ UI_CURSOR_WAIT ]		= LoadCursor(NULL, IDC_WAIT);
1650	mCursor[ UI_CURSOR_HAND ]		= LoadCursor(NULL, IDC_HAND);
1651	mCursor[ UI_CURSOR_IBEAM ]		= LoadCursor(NULL, IDC_IBEAM);
1652	mCursor[ UI_CURSOR_CROSS ]		= LoadCursor(NULL, IDC_CROSS);
1653	mCursor[ UI_CURSOR_SIZENWSE ]	= LoadCursor(NULL, IDC_SIZENWSE);
1654	mCursor[ UI_CURSOR_SIZENESW ]	= LoadCursor(NULL, IDC_SIZENESW);
1655	mCursor[ UI_CURSOR_SIZEWE ]		= LoadCursor(NULL, IDC_SIZEWE);  
1656	mCursor[ UI_CURSOR_SIZENS ]		= LoadCursor(NULL, IDC_SIZENS);  
1657	mCursor[ UI_CURSOR_NO ]			= LoadCursor(NULL, IDC_NO);
1658	mCursor[ UI_CURSOR_WORKING ]	= LoadCursor(NULL, IDC_APPSTARTING); 
1659
1660	HMODULE module = GetModuleHandle(NULL);
1661	mCursor[ UI_CURSOR_TOOLGRAB ]	= LoadCursor(module, TEXT("TOOLGRAB"));
1662	mCursor[ UI_CURSOR_TOOLLAND ]	= LoadCursor(module, TEXT("TOOLLAND"));
1663	mCursor[ UI_CURSOR_TOOLFOCUS ]	= LoadCursor(module, TEXT("TOOLFOCUS"));
1664	mCursor[ UI_CURSOR_TOOLCREATE ]	= LoadCursor(module, TEXT("TOOLCREATE"));
1665	mCursor[ UI_CURSOR_ARROWDRAG ]	= LoadCursor(module, TEXT("ARROWDRAG"));
1666	mCursor[ UI_CURSOR_ARROWCOPY ]	= LoadCursor(module, TEXT("ARROWCOPY"));
1667	mCursor[ UI_CURSOR_ARROWDRAGMULTI ]	= LoadCursor(module, TEXT("ARROWDRAGMULTI"));
1668	mCursor[ UI_CURSOR_ARROWCOPYMULTI ]	= LoadCursor(module, TEXT("ARROWCOPYMULTI"));
1669	mCursor[ UI_CURSOR_NOLOCKED ]	= LoadCursor(module, TEXT("NOLOCKED"));
1670	mCursor[ UI_CURSOR_ARROWLOCKED ]= LoadCursor(module, TEXT("ARROWLOCKED"));
1671	mCursor[ UI_CURSOR_GRABLOCKED ]	= LoadCursor(module, TEXT("GRABLOCKED"));
1672	mCursor[ UI_CURSOR_TOOLTRANSLATE ]	= LoadCursor(module, TEXT("TOOLTRANSLATE"));
1673	mCursor[ UI_CURSOR_TOOLROTATE ]	= LoadCursor(module, TEXT("TOOLROTATE")); 
1674	mCursor[ UI_CURSOR_TOOLSCALE ]	= LoadCursor(module, TEXT("TOOLSCALE"));
1675	mCursor[ UI_CURSOR_TOOLCAMERA ]	= LoadCursor(module, TEXT("TOOLCAMERA"));
1676	mCursor[ UI_CURSOR_TOOLPAN ]	= LoadCursor(module, TEXT("TOOLPAN"));
1677	mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN"));
1678	mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3"));
1679	mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
1680	mCursor[ UI_CURSOR_TOOLSIT ]	= LoadCursor(module, TEXT("TOOLSIT"));
1681	mCursor[ UI_CURSOR_TOOLBUY ]	= LoadCursor(module, TEXT("TOOLBUY"));
1682	mCursor[ UI_CURSOR_TOOLOPEN ]	= LoadCursor(module, TEXT("TOOLOPEN"));
1683
1684	// Color cursors
1685	mCursor[ UI_CURSOR_TOOLPLAY ]		= loadColorCursor(TEXT("TOOLPLAY"));
1686	mCursor[ UI_CURSOR_TOOLPAUSE ]		= loadColorCursor(TEXT("TOOLPAUSE"));
1687	mCursor[ UI_CURSOR_TOOLMEDIAOPEN ]	= loadColorCursor(TEXT("TOOLMEDIAOPEN"));
1688
1689	// Note: custom cursors that are not found make LoadCursor() return NULL.
1690	for( S32 i = 0; i < UI_CURSOR_COUNT; i++ )
1691	{
1692		if( !mCursor[i] )
1693		{
1694			mCursor[i] = LoadCursor(NULL, IDC_ARROW);
1695		}
1696	}
1697}
1698
1699
1700
1701void LLWindowWin32::updateCursor()
1702{
1703	if (mNextCursor == UI_CURSOR_ARROW
1704		&& mBusyCount > 0)
1705	{
1706		mNextCursor = UI_CURSOR_WORKING;
1707	}
1708
1709	if( mCurrentCursor != mNextCursor )
1710	{
1711		mCurrentCursor = mNextCursor;
1712		SetCursor( mCursor[mNextCursor] );
1713	}
1714}
1715
1716ECursorType LLWindowWin32::getCursor() const
1717{
1718	return mCurrentCursor;
1719}
1720
1721void LLWindowWin32::captureMouse()
1722{
1723	SetCapture(mWindowHandle);
1724}
1725
1726void LLWindowWin32::releaseMouse()
1727{
1728	// *NOTE:Mani ReleaseCapture will spawn new windows messages...
1729	// which will in turn call our MainWindowProc. It therefore requires
1730	// pausing *and more importantly resumption* of the mainlooptimeout...
1731	// just like DispatchMessage below.
1732	mCallbacks->handlePauseWatchdog(this);
1733	ReleaseCapture();
1734	mCallbacks->handleResumeWatchdog(this);
1735}
1736
1737
1738void LLWindowWin32::delayInputProcessing()
1739{
1740	mInputProcessingPaused = TRUE;
1741}
1742
1743void LLWindowWin32::gatherInput()
1744{
1745	MSG		msg;
1746	int		msg_count = 0;
1747
1748	LLMemType m1(LLMemType::MTYPE_GATHER_INPUT);
1749
1750	while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1751	{
1752		mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput");
1753		TranslateMessage(&msg);
1754
1755		// turn watchdog off in …

Large files files are truncated, but you can click here to view the full file