diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llwindow/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llwindow/lldragdropwin32.cpp | 302 | ||||
| -rw-r--r-- | indra/llwindow/lldragdropwin32.h | 55 | ||||
| -rw-r--r-- | indra/llwindow/llwindowcallbacks.cpp | 5 | ||||
| -rw-r--r-- | indra/llwindow/llwindowcallbacks.h | 1 | ||||
| -rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 7375 | ||||
| -rw-r--r-- | indra/llwindow/llwindowwin32.h | 5 | ||||
| -rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
| -rw-r--r-- | indra/newview/llviewerwindow.cpp | 43 | ||||
| -rw-r--r-- | indra/newview/llviewerwindow.h | 3 | 
10 files changed, 4154 insertions, 3648 deletions
| diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 7b1cab696f..b4a3f74451 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -102,11 +102,13 @@ if (WINDOWS)         llwindowwin32.cpp         lldxhardware.cpp         llkeyboardwin32.cpp +       lldragdropwin32.cpp         )    list(APPEND llwindow_HEADER_FILES         llwindowwin32.h         lldxhardware.h         llkeyboardwin32.h +       lldragdropwin32.h         )    list(APPEND llwindow_LINK_LIBRARIES         comdlg32     # Common Dialogs for ChooseColor diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp new file mode 100644 index 0000000000..d05dbf19a5 --- /dev/null +++ b/indra/llwindow/lldragdropwin32.cpp @@ -0,0 +1,302 @@ +/**
 + * @file lldragdrop32.cpp
 + * @brief Handler for Windows specific drag and drop (OS to client) code
 + *
 + * $LicenseInfo:firstyear=2001&license=viewergpl$
 + *
 + * Copyright (c) 2001-2009, Linden Research, Inc.
 + *
 + * Second Life Viewer Source Code
 + * The source code in this file ("Source Code") is provided by Linden Lab
 + * to you under the terms of the GNU General Public License, version 2.0
 + * ("GPL"), unless you have obtained a separate licensing agreement
 + * ("Other License"), formally executed by you and Linden Lab.  Terms of
 + * the GPL can be found in doc/GPL-license.txt in this distribution, or
 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 + *
 + * There are special exceptions to the terms and conditions of the GPL as
 + * it is applied to this Source Code. View the full text of the exception
 + * in the file doc/FLOSS-exception.txt in this software distribution, or
 + * online at
 + * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 + *
 + * By copying, modifying or distributing this software, you acknowledge
 + * that you have read and understood your obligations described above,
 + * and agree to abide by those obligations.
 + *
 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 + * COMPLETENESS OR PERFORMANCE.
 + * $/LicenseInfo$
 + */
 +
 +#if LL_WINDOWS
 +
 +#include "linden_common.h"
 +
 +#define WIN32_LEAN_AND_MEAN
 +#include <windows.h>
 +
 +#include "llwindowwin32.h"
 +#include "llkeyboardwin32.h"
 +#include "lldragdropwin32.h"
 +
 +#include "llwindowcallbacks.h"
 +
 +#include <windows.h>
 +#include <ole2.h>
 +#include <shlobj.h>
 +#include <shellapi.h>
 +#include <shlwapi.h>
 +
 +// FIXME: this should be done in CMake
 +#pragma comment( lib, "shlwapi.lib" )
 +
 +class LLDragDropWin32Target: 
 +	public IDropTarget
 +{
 +	public:
 +		LLDragDropWin32Target( HWND  hWnd ) :
 +		  mWindowHandle( hWnd ),
 +		  mRefCount( 0 )
 +		{
 +			strcpy(szFileDropped,"");
 +			bDropTargetValid = false;
 +			bTextDropped = false;		
 +		};
 +
 +		/* IUnknown methods */
 +		STDMETHOD_( ULONG, AddRef )( void )
 +		{
 +			return ++mRefCount;
 +		};
 +
 +		STDMETHOD_( ULONG, Release )( void )
 +		{
 +			if ( --mRefCount == 0 )
 +			{
 +				delete this;
 +				return 0;
 +			}
 +			return mRefCount;
 +		};
 +
 +		STDMETHOD ( QueryInterface )( REFIID iid, void ** ppvObject )
 +		{
 +			if ( iid == IID_IUnknown || iid == IID_IDropTarget )
 +			{
 +				*ppvObject = this;
 +				AddRef();
 +				return S_OK;
 +			};
 +
 +			*ppvObject = NULL;
 +			return E_NOINTERFACE;
 +		};
 +		
 +		/* IDropTarget methods */
 +		STDMETHOD (DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
 +		{
 +			HRESULT hr = E_INVALIDARG;
 +			bDropTargetValid = false;
 +			bTextDropped = false;
 +			*pdwEffect=DROPEFFECT_NONE;
 +			
 +			FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
 +			STGMEDIUM medium;
 +				
 +			if (pDataObj && SUCCEEDED (pDataObj->GetData (&fmte, &medium)))
 +			{
 +				// We can Handle Only one File At a time !!!
 +				if (1 == DragQueryFile ((HDROP)medium.hGlobal,0xFFFFFFFF,NULL,0 ))
 +				{
 +					// Get the File Name
 +					if (DragQueryFileA((HDROP)medium.hGlobal, 0, szFileDropped,MAX_PATH))
 +					{
 +						if (!PathIsDirectoryA(szFileDropped))
 +						{
 +							char szTempFile[MAX_PATH];
 +							_splitpath(szFileDropped,NULL,NULL,NULL,szTempFile);
 +
 +//							if (!stricmp(szTempFile,".lnk"))
 +//							{
 +//								if (ResolveLink(szFileDropped,szTempFile))
 +//								{
 +//									strcpy(szFileDropped,szTempFile);
 +//									*pdwEffect=DROPEFFECT_COPY;
 +//									We Want to Create a Copy
 +//									bDropTargetValid = true;
 +//									hr = S_OK;
 +//								}
 +//							}
 +//							else
 +//							{
 +								*pdwEffect=DROPEFFECT_COPY;
 +								//We Want to Create a Copy
 +								bDropTargetValid = true;
 +								hr = S_OK;
 +//							}
 +						}
 +					}
 +				}
 +
 +				if (medium.pUnkForRelease)
 +					medium.pUnkForRelease->Release ();
 +				else
 +					GlobalFree (medium.hGlobal);
 +			}
 +			else 
 +			{
 +				fmte.cfFormat = CF_TEXT;
 +				fmte.ptd = NULL;
 +				fmte.dwAspect = DVASPECT_CONTENT;
 +				fmte.lindex = -1;
 +				fmte.tymed = TYMED_HGLOBAL; 
 +
 +				// Does the drag source provide CF_TEXT ?    
 +				if (NOERROR == pDataObj->QueryGetData(&fmte))
 +				{
 +					bDropTargetValid = true;
 +					bTextDropped = true;
 +					*pdwEffect=DROPEFFECT_COPY;
 +					hr = S_OK;
 +				}
 +			}
 +				return hr;
 +
 +
 +
 +		};
 +
 +		STDMETHOD (DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
 +		{
 +			HRESULT hr = S_OK;
 +			if (bDropTargetValid) 
 +				*pdwEffect=DROPEFFECT_COPY;
 +
 +			return hr;
 +		};
 +
 +		STDMETHOD (DragLeave)(void)
 +		{
 +			HRESULT hr = S_OK;
 +			strcpy(szFileDropped,"");
 +			return hr;
 +		};
 +
 +		STDMETHOD (Drop)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
 +		{
 +			HRESULT hr = S_OK;
 +			if (bDropTargetValid) 
 +			{
 +				*pdwEffect=DROPEFFECT_COPY;
 +			
 +				FORMATETC fmte;
 +				STGMEDIUM medium;
 +
 +				if (bTextDropped)
 +				{
 +					fmte.cfFormat = CF_TEXT;
 +					fmte.ptd = NULL;
 +					fmte.dwAspect = DVASPECT_CONTENT;  
 +					fmte.lindex = -1;
 +					fmte.tymed = TYMED_HGLOBAL;       
 +
 +					hr = pDataObj->GetData(&fmte, &medium);
 +					HGLOBAL hText = medium.hGlobal;
 +					LPSTR lpszText = (LPSTR)GlobalLock(hText);
 +
 +					LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mWindowHandle, GWL_USERDATA);
 +					if (NULL != window_imp)
 +					{
 +						LLCoordGL gl_coord( 0, 0 );
 +
 +						POINT pt2;
 +						pt2.x = pt.x;
 +						pt2.y = pt.y;
 +						ScreenToClient( mWindowHandle, &pt2 );
 +
 +						LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
 +						window_imp->convertCoords(cursor_coord_window, &gl_coord);
 +						llinfos << "### (Drop) URL is: " << lpszText << llendl;
 +						llinfos << "###        raw coords are: " << pt.x << " x " << pt.y << llendl;
 +						llinfos << "###	    window coords are: " << pt2.x << " x " << pt2.y << llendl;
 +						llinfos << "###         GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl;
 +						llinfos << llendl;
 +
 +						MASK mask = gKeyboard->currentMask(TRUE);
 +						window_imp->completeDropRequest( gl_coord, mask, std::string( lpszText ) );
 +					};
 +
 +					GlobalUnlock(hText);
 +					ReleaseStgMedium(&medium);
 +				}
 +			}
 +			return hr;
 +		};
 +	   
 +	private:
 +		ULONG mRefCount;
 +		HWND mWindowHandle;
 +		char szFileDropped[1024];
 +		bool bDropTargetValid;
 +		bool bTextDropped;
 +		friend class LLWindowWin32;
 +};
 +
 +LLDragDropWin32::LLDragDropWin32() :
 +	mDropTarget( NULL ),
 +	mDropWindowHandle( NULL )
 +
 +{
 +}
 +
 +LLDragDropWin32::~LLDragDropWin32()
 +{
 +}
 +
 +bool LLDragDropWin32::init( HWND hWnd )
 +{
 +	if (NOERROR != OleInitialize(NULL))
 +		return FALSE; 
 +
 +	mDropTarget = new LLDragDropWin32Target( hWnd );
 +	if ( mDropTarget )
 +	{
 +		HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, TRUE );
 +		if ( S_OK == result )
 +		{
 +			result = RegisterDragDrop( hWnd, mDropTarget );
 +			if ( S_OK != result )
 +			{
 +				// RegisterDragDrop failed
 +				return false;
 +			};
 +
 +			// all ok
 +			mDropWindowHandle = hWnd;
 +		}
 +		else
 +		{
 +			// Unable to lock OLE object
 +			return false;
 +		};
 +	};
 +
 +	// success
 +	return true;
 +}
 +
 +void LLDragDropWin32::reset()
 +{
 +	if ( mDropTarget )
 +	{
 +		CoLockObjectExternal( mDropTarget, FALSE, TRUE );
 +		RevokeDragDrop( mDropWindowHandle );
 +		mDropTarget->Release();  
 +	};
 +	
 +	OleUninitialize();
 +}
 +
 +#endif
 diff --git a/indra/llwindow/lldragdropwin32.h b/indra/llwindow/lldragdropwin32.h new file mode 100644 index 0000000000..6137e5eb65 --- /dev/null +++ b/indra/llwindow/lldragdropwin32.h @@ -0,0 +1,55 @@ +/**
 + * @file lldragdrop32.cpp
 + * @brief Handler for Windows specific drag and drop (OS to client) code
 + *
 + * $LicenseInfo:firstyear=2004&license=viewergpl$
 + *
 + * Copyright (c) 2004-2009, Linden Research, Inc.
 + *
 + * Second Life Viewer Source Code
 + * The source code in this file ("Source Code") is provided by Linden Lab
 + * to you under the terms of the GNU General Public License, version 2.0
 + * ("GPL"), unless you have obtained a separate licensing agreement
 + * ("Other License"), formally executed by you and Linden Lab.  Terms of
 + * the GPL can be found in doc/GPL-license.txt in this distribution, or
 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 + *
 + * There are special exceptions to the terms and conditions of the GPL as
 + * it is applied to this Source Code. View the full text of the exception
 + * in the file doc/FLOSS-exception.txt in this software distribution, or
 + * online at
 + * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 + *
 + * By copying, modifying or distributing this software, you acknowledge
 + * that you have read and understood your obligations described above,
 + * and agree to abide by those obligations.
 + *
 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 + * COMPLETENESS OR PERFORMANCE.
 + * $/LicenseInfo$
 + */
 +
 +#ifndef LL_LLDRAGDROP32_H
 +#define LL_LLDRAGDROP32_H
 +
 +#include <windows.h>
 +#include <ole2.h>
 +#include <shlobj.h>
 +#include <shlwapi.h>
 +
 +class LLDragDropWin32
 +{
 +	public:
 +		LLDragDropWin32();
 +		~LLDragDropWin32();
 +
 +		bool init( HWND hWnd );
 +		void reset();
 +
 +	private:
 +		IDropTarget* mDropTarget;
 +		HWND mDropWindowHandle;
 +};
 +
 +#endif
 diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index 72f9997149..1098529e1c 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -163,6 +163,11 @@ void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *da  {  } +BOOL LLWindowCallbacks::handleDrop(LLWindow *window, LLCoordGL pos, MASK mask, std::string data ) +{ +	return FALSE; +} +  BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window)  {  	return FALSE; diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index abc66c42a2..3a09100168 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -68,6 +68,7 @@ public:  	virtual void handleWindowBlock(LLWindow *window);							// window is taking over CPU for a while  	virtual void handleWindowUnblock(LLWindow *window);							// window coming back after taking over CPU for a while  	virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data); +	virtual BOOL handleDrop(LLWindow *window, LLCoordGL pos, MASK mask, std::string data);  	virtual BOOL handleTimerEvent(LLWindow *window);  	virtual BOOL handleDeviceChange(LLWindow *window); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index c608c21d05..da096b9a0a 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1,3647 +1,3728 @@ -/**  - * @file llwindowwin32.cpp - * @brief Platform-dependent implementation of llwindow - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - *  - * Copyright (c) 2001-2009, Linden Research, Inc. - *  - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab.  Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - *  - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - *  - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - *  - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#if LL_WINDOWS && !LL_MESA_HEADLESS - -#include "llwindowwin32.h" - -// LLWindow library includes -#include "llkeyboardwin32.h" -#include "llpreeditor.h" -#include "llwindowcallbacks.h" - -// Linden library includes -#include "llerror.h" -#include "llgl.h" -#include "llstring.h" - -// System includes -#include <commdlg.h> -#include <WinUser.h> -#include <mapi.h> -#include <process.h>	// for _spawn -#include <shellapi.h> -#include <Imm.h> - -// Require DirectInput version 8 -#define DIRECTINPUT_VERSION 0x0800 - -#include <dinput.h> -#include <Dbt.h.> - -#include "llmemtype.h" -// culled from winuser.h -#ifndef WM_MOUSEWHEEL /* Added to be compatible with later SDK's */ -const S32	WM_MOUSEWHEEL = 0x020A; -#endif -#ifndef WHEEL_DELTA /* Added to be compatible with later SDK's */ -const S32	WHEEL_DELTA = 120;     /* Value for rolling one detent */ -#endif -const S32	MAX_MESSAGE_PER_UPDATE = 20; -const S32	BITS_PER_PIXEL = 32; -const S32	MAX_NUM_RESOLUTIONS = 32; -const F32	ICON_FLASH_TIME = 0.5f; - -extern BOOL gDebugWindowProc; - -LPWSTR gIconResource = IDI_APPLICATION; - -LLW32MsgCallback gAsyncMsgCallback = NULL; - -// -// LLWindowWin32 -// - -void show_window_creation_error(const std::string& title) -{ -	LL_WARNS("Window") << title << LL_ENDL; -} - -//static -BOOL LLWindowWin32::sIsClassRegistered = FALSE; - -BOOL	LLWindowWin32::sLanguageTextInputAllowed = TRUE; -BOOL	LLWindowWin32::sWinIMEOpened = FALSE; -HKL		LLWindowWin32::sWinInputLocale = 0; -DWORD	LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE; -DWORD	LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC; -LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1); - -// The following class LLWinImm delegates Windows IMM APIs. -// We need this because some language versions of Windows, -// e.g., US version of Windows XP, doesn't install IMM32.DLL -// as a default, and we can't link against imm32.lib statically. -// I believe DLL loading of this type is best suited to do -// in a static initialization of a class.  What I'm not sure is -// whether it follows the Linden Conding Standard...  -// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members - -class LLWinImm -{ -public: -	static bool		isAvailable() { return sTheInstance.mHImmDll != NULL; } - -public: -	// Wrappers for IMM API. -	static BOOL		isIME(HKL hkl);															 -	static HWND		getDefaultIMEWnd(HWND hwnd); -	static HIMC		getContext(HWND hwnd);													 -	static BOOL		releaseContext(HWND hwnd, HIMC himc); -	static BOOL		getOpenStatus(HIMC himc);												 -	static BOOL		setOpenStatus(HIMC himc, BOOL status);									 -	static BOOL		getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);	 -	static BOOL		setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);		 -	static BOOL		getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					 -	static BOOL		setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					 -	static LONG		getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length); -	static BOOL		setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength); -	static BOOL		setCompositionFont(HIMC himc, LPLOGFONTW logfont); -	static BOOL		setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form); -	static BOOL		notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value); - -private: -	LLWinImm(); -	~LLWinImm(); - -private: -	// Pointers to IMM API. -	BOOL	 	(WINAPI *mImmIsIME)(HKL); -	HWND		(WINAPI *mImmGetDefaultIMEWnd)(HWND); -	HIMC		(WINAPI *mImmGetContext)(HWND); -	BOOL		(WINAPI *mImmReleaseContext)(HWND, HIMC); -	BOOL		(WINAPI *mImmGetOpenStatus)(HIMC); -	BOOL		(WINAPI *mImmSetOpenStatus)(HIMC, BOOL); -	BOOL		(WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD); -	BOOL		(WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD); -	BOOL		(WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); -	BOOL		(WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); -	LONG		(WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD); -	BOOL		(WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD); -	BOOL		(WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW); -	BOOL		(WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM); -	BOOL		(WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD); - -private: -	HMODULE		mHImmDll; -	static LLWinImm sTheInstance; -}; - -LLWinImm LLWinImm::sTheInstance; - -LLWinImm::LLWinImm() : mHImmDll(NULL) -{ -	// Check system metrics  -	if ( !GetSystemMetrics( SM_DBCSENABLED ) ) -		return; -	 - -	mHImmDll = LoadLibraryA("Imm32"); -	if (mHImmDll != NULL) -	{ -		mImmIsIME               = (BOOL (WINAPI *)(HKL))                    GetProcAddress(mHImmDll, "ImmIsIME"); -		mImmGetDefaultIMEWnd	= (HWND (WINAPI *)(HWND))					GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd"); -		mImmGetContext          = (HIMC (WINAPI *)(HWND))                   GetProcAddress(mHImmDll, "ImmGetContext"); -		mImmReleaseContext      = (BOOL (WINAPI *)(HWND, HIMC))             GetProcAddress(mHImmDll, "ImmReleaseContext"); -		mImmGetOpenStatus       = (BOOL (WINAPI *)(HIMC))                   GetProcAddress(mHImmDll, "ImmGetOpenStatus"); -		mImmSetOpenStatus       = (BOOL (WINAPI *)(HIMC, BOOL))             GetProcAddress(mHImmDll, "ImmSetOpenStatus"); -		mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus"); -		mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD))     GetProcAddress(mHImmDll, "ImmSetConversionStatus"); -		mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmGetCompositionWindow"); -		mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmSetCompositionWindow"); -		mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD))					GetProcAddress(mHImmDll, "ImmGetCompositionStringW"); -		mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD))	GetProcAddress(mHImmDll, "ImmSetCompositionStringW"); -		mImmSetCompositionFont  = (BOOL (WINAPI *)(HIMC, LPLOGFONTW))		GetProcAddress(mHImmDll, "ImmSetCompositionFontW"); -		mImmSetCandidateWindow  = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM))  GetProcAddress(mHImmDll, "ImmSetCandidateWindow"); -		mImmNotifyIME			= (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD))	GetProcAddress(mHImmDll, "ImmNotifyIME"); - -		if (mImmIsIME == NULL || -			mImmGetDefaultIMEWnd == NULL || -			mImmGetContext == NULL || -			mImmReleaseContext == NULL || -			mImmGetOpenStatus == NULL || -			mImmSetOpenStatus == NULL || -			mImmGetConversionStatus == NULL || -			mImmSetConversionStatus == NULL || -			mImmGetCompostitionWindow == NULL || -			mImmSetCompostitionWindow == NULL || -			mImmGetCompositionString == NULL || -			mImmSetCompositionString == NULL || -			mImmSetCompositionFont == NULL || -			mImmSetCandidateWindow == NULL || -			mImmNotifyIME == NULL) -		{ -			// If any of the above API entires are not found, we can't use IMM API.   -			// So, turn off the IMM support.  We should log some warning message in  -			// the case, since it is very unusual; these APIs are available from  -			// the beginning, and all versions of IMM32.DLL should have them all.   -			// Unfortunately, this code may be executed before initialization of  -			// the logging channel (llwarns), and we can't do it here...  Yes, this  -			// is one of disadvantages to use static constraction to DLL loading.  -			FreeLibrary(mHImmDll); -			mHImmDll = NULL; - -			// If we unload the library, make sure all the function pointers are cleared -			mImmIsIME = NULL; -			mImmGetDefaultIMEWnd = NULL; -			mImmGetContext = NULL; -			mImmReleaseContext = NULL; -			mImmGetOpenStatus = NULL; -			mImmSetOpenStatus = NULL; -			mImmGetConversionStatus = NULL; -			mImmSetConversionStatus = NULL; -			mImmGetCompostitionWindow = NULL; -			mImmSetCompostitionWindow = NULL; -			mImmGetCompositionString = NULL; -			mImmSetCompositionString = NULL; -			mImmSetCompositionFont = NULL; -			mImmSetCandidateWindow = NULL; -			mImmNotifyIME = NULL; -		} -	} -} - - -// static  -BOOL	LLWinImm::isIME(HKL hkl)															 -{  -	if ( sTheInstance.mImmIsIME ) -		return sTheInstance.mImmIsIME(hkl);  -	return FALSE; -} - -// static  -HIMC		LLWinImm::getContext(HWND hwnd) -{ -	if ( sTheInstance.mImmGetContext ) -		return sTheInstance.mImmGetContext(hwnd);  -	return 0; -} - -//static  -BOOL		LLWinImm::releaseContext(HWND hwnd, HIMC himc) -{  -	if ( sTheInstance.mImmIsIME ) -		return sTheInstance.mImmReleaseContext(hwnd, himc);  -	return FALSE; -} - -// static  -BOOL		LLWinImm::getOpenStatus(HIMC himc) -{  -	if ( sTheInstance.mImmGetOpenStatus ) -		return sTheInstance.mImmGetOpenStatus(himc);  -	return FALSE; -} - -// static  -BOOL		LLWinImm::setOpenStatus(HIMC himc, BOOL status)									 -{  -	if ( sTheInstance.mImmSetOpenStatus ) -		return sTheInstance.mImmSetOpenStatus(himc, status);  -	return FALSE; -} - -// static  -BOOL		LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)	 -{  -	if ( sTheInstance.mImmGetConversionStatus ) -		return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence);  -	return FALSE; -} - -// static  -BOOL		LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)		 -{  -	if ( sTheInstance.mImmSetConversionStatus ) -		return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence);  -	return FALSE; -} - -// static  -BOOL		LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					 -{  -	if ( sTheInstance.mImmGetCompostitionWindow ) -		return sTheInstance.mImmGetCompostitionWindow(himc, form);	 -	return FALSE; -} - -// static  -BOOL		LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					 -{  -	if ( sTheInstance.mImmSetCompostitionWindow ) -		return sTheInstance.mImmSetCompostitionWindow(himc, form);	 -	return FALSE; -} - - -// static  -LONG		LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length)					 -{  -	if ( sTheInstance.mImmGetCompositionString ) -		return sTheInstance.mImmGetCompositionString(himc, index, data, length);	 -	return FALSE; -} - - -// static  -BOOL		LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)					 -{  -	if ( sTheInstance.mImmSetCompositionString ) -		return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);	 -	return FALSE; -} - -// static  -BOOL		LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)					 -{  -	if ( sTheInstance.mImmSetCompositionFont ) -		return sTheInstance.mImmSetCompositionFont(himc, pFont);	 -	return FALSE; -} - -// static  -BOOL		LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)					 -{  -	if ( sTheInstance.mImmSetCandidateWindow ) -		return sTheInstance.mImmSetCandidateWindow(himc, form);	 -	return FALSE; -} - -// static  -BOOL		LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)					 -{  -	if ( sTheInstance.mImmNotifyIME ) -		return sTheInstance.mImmNotifyIME(himc, action, index, value);	 -	return FALSE; -} - - - - -// ---------------------------------------------------------------------------------------- -LLWinImm::~LLWinImm() -{ -	if (mHImmDll != NULL) -	{ -		FreeLibrary(mHImmDll); -		mHImmDll = NULL; -	} -} - - -LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, -							 const std::string& title, const std::string& 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, -							 U32 fsaa_samples) -	: LLWindow(callbacks, fullscreen, flags) -{ -	mFSAASamples = fsaa_samples; -	mIconResource = gIconResource; -	mOverrideAspectRatio = 0.f; -	mNativeAspectRatio = 0.f; -	mMousePositionModified = FALSE; -	mInputProcessingPaused = FALSE; -	mPreeditor = NULL; -	mhDC = NULL; -	mhRC = NULL; - -	// Initialize the keyboard -	gKeyboard = new LLKeyboardWin32(); -	gKeyboard->setCallbacks(callbacks); - -	// Initialize (boot strap) the Language text input management, -	// based on the system's (user's) default settings. -	allowLanguageTextInput(mPreeditor, FALSE); - -	WNDCLASS		wc; -	RECT			window_rect; - -	// Set the window title -	if (title.empty()) -	{ -		mWindowTitle = new WCHAR[50]; -		wsprintf(mWindowTitle, L"OpenGL Window"); -	} -	else -	{ -		mWindowTitle = new WCHAR[256]; // Assume title length < 255 chars. -		mbstowcs(mWindowTitle, title.c_str(), 255); -		mWindowTitle[255] = 0; -	} - -	// Set the window class name -	if (name.empty()) -	{ -		mWindowClassName = new WCHAR[50]; -		wsprintf(mWindowClassName, L"OpenGL Window"); -	} -	else -	{ -		mWindowClassName = new WCHAR[256]; // Assume title length < 255 chars. -		mbstowcs(mWindowClassName, name.c_str(), 255); -		mWindowClassName[255] = 0; -	} - - -	// We're not clipping yet -	SetRect( &mOldMouseClip, 0, 0, 0, 0 ); - -	// Make an instance of our window then define the window class -	mhInstance = GetModuleHandle(NULL); -	mWndProc = NULL; - -	mSwapMethod = SWAP_METHOD_UNDEFINED; - -	// No WPARAM yet. -	mLastSizeWParam = 0; - -	// Windows GDI rects don't include rightmost pixel -	window_rect.left = (long) 0; -	window_rect.right = (long) width; -	window_rect.top = (long) 0; -	window_rect.bottom = (long) height; - -	// Grab screen size to sanitize the window -	S32 window_border_y = GetSystemMetrics(SM_CYBORDER); -	S32 virtual_screen_x = GetSystemMetrics(SM_XVIRTUALSCREEN);  -	S32 virtual_screen_y = GetSystemMetrics(SM_YVIRTUALSCREEN);  -	S32 virtual_screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); -	S32 virtual_screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); - -	if (x < virtual_screen_x) x = virtual_screen_x; -	if (y < virtual_screen_y - window_border_y) y = virtual_screen_y - window_border_y; - -	if (x + width > virtual_screen_x + virtual_screen_width) x = virtual_screen_x + virtual_screen_width - width; -	if (y + height > virtual_screen_y + virtual_screen_height) y = virtual_screen_y + virtual_screen_height - height; - -	if (!sIsClassRegistered) -	{ -		// Force redraw when resized and create a private device context - -		// Makes double click messages. -		wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; - -		// Set message handler function -		wc.lpfnWndProc = (WNDPROC) mainWindowProc; - -		// unused -		wc.cbClsExtra = 0; -		wc.cbWndExtra = 0; - -		wc.hInstance = mhInstance; -		wc.hIcon = LoadIcon(mhInstance, mIconResource); - -		// We will set the cursor ourselves -		wc.hCursor = NULL; - -		// background color is not used -		if (clearBg) -		{ -			wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); -		} -		else -		{ -			wc.hbrBackground = (HBRUSH) NULL; -		} - -		// we don't use windows menus -		wc.lpszMenuName = NULL; - -		wc.lpszClassName = mWindowClassName; - -		if (!RegisterClass(&wc)) -		{ -			OSMessageBox(mCallbacks->translateString("MBRegClassFailed"),  -				mCallbacks->translateString("MBError"), OSMB_OK); -			return; -		} -		sIsClassRegistered = TRUE; -	} - -	//----------------------------------------------------------------------- -	// Get the current refresh rate -	//----------------------------------------------------------------------- - -	DEVMODE dev_mode; -	DWORD current_refresh; -	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) -	{ -		current_refresh = dev_mode.dmDisplayFrequency; -		mNativeAspectRatio = ((F32)dev_mode.dmPelsWidth) / ((F32)dev_mode.dmPelsHeight); -	} -	else -	{ -		current_refresh = 60; -	} - -	//----------------------------------------------------------------------- -	// Drop resolution and go fullscreen -	// use a display mode with our desired size and depth, with a refresh -	// rate as close at possible to the users' default -	//----------------------------------------------------------------------- -	if (mFullscreen) -	{ -		BOOL success = FALSE; -		DWORD closest_refresh = 0; - -		for (S32 mode_num = 0;; mode_num++) -		{ -			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) -			{ -				break; -			} - -			if (dev_mode.dmPelsWidth == width && -				dev_mode.dmPelsHeight == height && -				dev_mode.dmBitsPerPel == BITS_PER_PIXEL) -			{ -				success = TRUE; -				if ((dev_mode.dmDisplayFrequency - current_refresh) -					< (closest_refresh - current_refresh)) -				{ -					closest_refresh = dev_mode.dmDisplayFrequency; -				} -			} -		} - -		if (closest_refresh == 0) -		{ -			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL; -			success = FALSE; -		} - -		// If we found a good resolution, use it. -		if (success) -		{ -			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); -		} - -		// Keep a copy of the actual current device mode in case we minimize  -		// and change the screen resolution.   JC -		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); - -		// If it failed, we don't want to run fullscreen -		if (success) -		{ -			mFullscreen = TRUE; -			mFullscreenWidth   = dev_mode.dmPelsWidth; -			mFullscreenHeight  = dev_mode.dmPelsHeight; -			mFullscreenBits    = dev_mode.dmBitsPerPel; -			mFullscreenRefresh = dev_mode.dmDisplayFrequency; - -			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth -				<< "x"   << dev_mode.dmPelsHeight -				<< "x"   << dev_mode.dmBitsPerPel -				<< " @ " << dev_mode.dmDisplayFrequency -				<< LL_ENDL; -		} -		else -		{ -			mFullscreen = FALSE; -			mFullscreenWidth   = -1; -			mFullscreenHeight  = -1; -			mFullscreenBits    = -1; -			mFullscreenRefresh = -1; - -			std::map<std::string,std::string> args; -			args["[WIDTH]"] = llformat("%d", width); -			args["[HEIGHT]"] = llformat ("%d", height); -			OSMessageBox(mCallbacks->translateString("MBFullScreenErr", args), -				mCallbacks->translateString("MBError"), OSMB_OK); -		} -	} - -	// TODO: add this after resolving _WIN32_WINNT issue -	//	if (!fullscreen) -	//	{ -	//		TRACKMOUSEEVENT track_mouse_event; -	//		track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); -	//		track_mouse_event.dwFlags = TME_LEAVE; -	//		track_mouse_event.hwndTrack = mWindowHandle; -	//		track_mouse_event.dwHoverTime = HOVER_DEFAULT; -	//		TrackMouseEvent( &track_mouse_event );  -	//	} - - -	//----------------------------------------------------------------------- -	// Create GL drawing context -	//----------------------------------------------------------------------- -	LLCoordScreen windowPos(x,y); -	LLCoordScreen windowSize(window_rect.right - window_rect.left, -							 window_rect.bottom - window_rect.top); -	if (!switchContext(mFullscreen, windowSize, TRUE, &windowPos)) -	{ -		return; -	} -	 -	//start with arrow cursor -	initCursors(); -	setCursor( UI_CURSOR_ARROW ); - -	// Initialize (boot strap) the Language text input management, -	// based on the system's (or user's) default settings. -	allowLanguageTextInput(NULL, FALSE); -} - - -LLWindowWin32::~LLWindowWin32() -{ -	delete [] mWindowTitle; -	mWindowTitle = NULL; - -	delete [] mSupportedResolutions; -	mSupportedResolutions = NULL; - -	delete mWindowClassName; -	mWindowClassName = NULL; -} - -void LLWindowWin32::show() -{ -	ShowWindow(mWindowHandle, SW_SHOW); -	SetForegroundWindow(mWindowHandle); -	SetFocus(mWindowHandle); -} - -void LLWindowWin32::hide() -{ -	setMouseClipping(FALSE); -	ShowWindow(mWindowHandle, SW_HIDE); -} - -void LLWindowWin32::minimize() -{ -	setMouseClipping(FALSE); -	showCursor(); -	ShowWindow(mWindowHandle, SW_MINIMIZE); -} - - -void LLWindowWin32::restore() -{ -	ShowWindow(mWindowHandle, SW_RESTORE); -	SetForegroundWindow(mWindowHandle); -	SetFocus(mWindowHandle); -} - - -// close() destroys all OS-specific code associated with a window. -// Usually called from LLWindowManager::destroyWindow() -void LLWindowWin32::close() -{ -	LL_DEBUGS("Window") << "Closing LLWindowWin32" << LL_ENDL; -	// Is window is already closed? -	if (!mWindowHandle) -	{ -		return; -	} - -	// Make sure cursor is visible and we haven't mangled the clipping state. -	setMouseClipping(FALSE); -	showCursor(); - -	// Go back to screen mode written in the registry. -	if (mFullscreen) -	{ -		resetDisplayResolution(); -	} - -	// Clean up remaining GL state -	LL_DEBUGS("Window") << "Shutting down GL" << LL_ENDL; -	gGLManager.shutdownGL(); - -	LL_DEBUGS("Window") << "Releasing Context" << LL_ENDL; -	if (mhRC) -	{ -		if (!wglMakeCurrent(NULL, NULL)) -		{ -			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; -		} - -		if (!wglDeleteContext(mhRC)) -		{ -			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; -		} - -		mhRC = NULL; -	} - -	// Restore gamma to the system values. -	restoreGamma(); - -	if (mhDC && !ReleaseDC(mWindowHandle, mhDC)) -	{ -		LL_WARNS("Window") << "Release of ghDC failed" << LL_ENDL; -		mhDC = NULL; -	} - -	LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL; -	 -	// Don't process events in our mainWindowProc any longer. -	SetWindowLong(mWindowHandle, GWL_USERDATA, NULL); - -	// Make sure we don't leave a blank toolbar button. -	ShowWindow(mWindowHandle, SW_HIDE); - -	// This causes WM_DESTROY to be sent *immediately* -	if (!DestroyWindow(mWindowHandle)) -	{ -		OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), -			mCallbacks->translateString("MBShutdownErr"), -			OSMB_OK); -	} - -	mWindowHandle = NULL; -} - -BOOL LLWindowWin32::isValid() -{ -	return (mWindowHandle != NULL); -} - -BOOL LLWindowWin32::getVisible() -{ -	return (mWindowHandle && IsWindowVisible(mWindowHandle)); -} - -BOOL LLWindowWin32::getMinimized() -{ -	return (mWindowHandle && IsIconic(mWindowHandle)); -} - -BOOL LLWindowWin32::getMaximized() -{ -	return (mWindowHandle && IsZoomed(mWindowHandle)); -} - -BOOL LLWindowWin32::maximize() -{ -	BOOL success = FALSE; -	if (!mWindowHandle) return success; - -	WINDOWPLACEMENT placement; -	placement.length = sizeof(WINDOWPLACEMENT); - -	success = GetWindowPlacement(mWindowHandle, &placement); -	if (!success) return success; - -	placement.showCmd = SW_MAXIMIZE; - -	success = SetWindowPlacement(mWindowHandle, &placement); -	return success; -} - -BOOL LLWindowWin32::getFullscreen() -{ -	return mFullscreen; -} - -BOOL LLWindowWin32::getPosition(LLCoordScreen *position) -{ -	RECT window_rect; - -	if (!mWindowHandle || -		!GetWindowRect(mWindowHandle, &window_rect) || -		NULL == position) -	{ -		return FALSE; -	} - -	position->mX = window_rect.left; -	position->mY = window_rect.top; -	return TRUE; -} - -BOOL LLWindowWin32::getSize(LLCoordScreen *size) -{ -	RECT window_rect; - -	if (!mWindowHandle || -		!GetWindowRect(mWindowHandle, &window_rect) || -		NULL == size) -	{ -		return FALSE; -	} - -	size->mX = window_rect.right - window_rect.left; -	size->mY = window_rect.bottom - window_rect.top; -	return TRUE; -} - -BOOL LLWindowWin32::getSize(LLCoordWindow *size) -{ -	RECT client_rect; - -	if (!mWindowHandle || -		!GetClientRect(mWindowHandle, &client_rect) || -		NULL == size) -	{ -		return FALSE; -	} - -	size->mX = client_rect.right - client_rect.left; -	size->mY = client_rect.bottom - client_rect.top; -	return TRUE; -} - -BOOL LLWindowWin32::setPosition(const LLCoordScreen position) -{ -	LLCoordScreen size; - -	if (!mWindowHandle) -	{ -		return FALSE; -	} -	getSize(&size); -	moveWindow(position, size); -	return TRUE; -} - -BOOL LLWindowWin32::setSize(const LLCoordScreen size) -{ -	LLCoordScreen position; - -	getPosition(&position); -	if (!mWindowHandle) -	{ -		return FALSE; -	} - -	moveWindow(position, size); -	return TRUE; -} - -// changing fullscreen resolution -BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp) -{ -	GLuint	pixel_format; -	DEVMODE dev_mode; -	DWORD	current_refresh; -	DWORD	dw_ex_style; -	DWORD	dw_style; -	RECT	window_rect; -	S32 width = size.mX; -	S32 height = size.mY; -	BOOL auto_show = FALSE; - -	if (mhRC) -	{ -		auto_show = TRUE; -		resetDisplayResolution(); -	} - -	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) -	{ -		current_refresh = dev_mode.dmDisplayFrequency; -	} -	else -	{ -		current_refresh = 60; -	} - -	gGLManager.shutdownGL(); -	//destroy gl context -	if (mhRC) -	{ -		if (!wglMakeCurrent(NULL, NULL)) -		{ -			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; -		} - -		if (!wglDeleteContext(mhRC)) -		{ -			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; -		} - -		mhRC = NULL; -	} - -	if (fullscreen) -	{ -		mFullscreen = TRUE; -		BOOL success = FALSE; -		DWORD closest_refresh = 0; - -		for (S32 mode_num = 0;; mode_num++) -		{ -			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) -			{ -				break; -			} - -			if (dev_mode.dmPelsWidth == width && -				dev_mode.dmPelsHeight == height && -				dev_mode.dmBitsPerPel == BITS_PER_PIXEL) -			{ -				success = TRUE; -				if ((dev_mode.dmDisplayFrequency - current_refresh) -					< (closest_refresh - current_refresh)) -				{ -					closest_refresh = dev_mode.dmDisplayFrequency; -				} -			} -		} - -		if (closest_refresh == 0) -		{ -			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL; -			return FALSE; -		} - -		// If we found a good resolution, use it. -		if (success) -		{ -			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); -		} - -		// Keep a copy of the actual current device mode in case we minimize  -		// and change the screen resolution.   JC -		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); - -		if (success) -		{ -			mFullscreen = TRUE; -			mFullscreenWidth   = dev_mode.dmPelsWidth; -			mFullscreenHeight  = dev_mode.dmPelsHeight; -			mFullscreenBits    = dev_mode.dmBitsPerPel; -			mFullscreenRefresh = dev_mode.dmDisplayFrequency; - -			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth -				<< "x"   << dev_mode.dmPelsHeight -				<< "x"   << dev_mode.dmBitsPerPel -				<< " @ " << dev_mode.dmDisplayFrequency -				<< LL_ENDL; - -			window_rect.left = (long) 0; -			window_rect.right = (long) width;			// Windows GDI rects don't include rightmost pixel -			window_rect.top = (long) 0; -			window_rect.bottom = (long) height; -			dw_ex_style = WS_EX_APPWINDOW; -			dw_style = WS_POPUP; - -			// Move window borders out not to cover window contents -			AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); -		} -		// If it failed, we don't want to run fullscreen -		else -		{ -			mFullscreen = FALSE; -			mFullscreenWidth   = -1; -			mFullscreenHeight  = -1; -			mFullscreenBits    = -1; -			mFullscreenRefresh = -1; - -			LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL; -			return FALSE; -		} -	} -	else -	{ -		mFullscreen = FALSE; -		window_rect.left = (long) (posp ? posp->mX : 0); -		window_rect.right = (long) width + window_rect.left;			// Windows GDI rects don't include rightmost pixel -		window_rect.top = (long) (posp ? posp->mY : 0); -		window_rect.bottom = (long) height + window_rect.top; -		// Window with an edge -		dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; -		dw_style = WS_OVERLAPPEDWINDOW; -	} - -	// don't post quit messages when destroying old windows -	mPostQuit = FALSE; - -	// create window -	DestroyWindow(mWindowHandle); -	mWindowHandle = CreateWindowEx(dw_ex_style, -		mWindowClassName, -		mWindowTitle, -		WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, -		window_rect.left,								// x pos -		window_rect.top,								// y pos -		window_rect.right - window_rect.left,			// width -		window_rect.bottom - window_rect.top,			// height -		NULL, -		NULL, -		mhInstance, -		NULL); - -	//----------------------------------------------------------------------- -	// Create GL drawing context -	//----------------------------------------------------------------------- -	static PIXELFORMATDESCRIPTOR pfd = -	{ -		sizeof(PIXELFORMATDESCRIPTOR),  -			1, -			PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,  -			PFD_TYPE_RGBA, -			BITS_PER_PIXEL, -			0, 0, 0, 0, 0, 0,	// RGB bits and shift, unused -			8,					// alpha bits -			0,					// alpha shift -			0,					// accum bits -			0, 0, 0, 0,			// accum RGBA -			24,					// depth bits -			8,					// stencil bits, avi added for stencil test -			0, -			PFD_MAIN_PLANE, -			0, -			0, 0, 0 -	}; - -	if (!(mhDC = GetDC(mWindowHandle))) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBDevContextErr"), -			mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd))) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"), -			mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	// Verify what pixel format we actually received. -	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), -		&pfd)) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), -			mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (pfd.cColorBits < 32) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), -			mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (pfd.cAlphaBits < 8) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBAlpha"), -			mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (!SetPixelFormat(mhDC, pixel_format, &pfd)) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), -			mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (!(mhRC = wglCreateContext(mhDC))) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBGLContextErr"), -			mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (!wglMakeCurrent(mhDC, mhRC)) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), -			mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	gGLManager.initWGL(); - -	if (wglChoosePixelFormatARB) -	{ -		// OK, at this point, use the ARB wglChoosePixelFormatsARB function to see if we -		// can get exactly what we want. -		GLint attrib_list[256]; -		S32 cur_attrib = 0; - -		attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB; -		attrib_list[cur_attrib++] = 24; - -		attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB; -		attrib_list[cur_attrib++] = 8; - -		attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB; -		attrib_list[cur_attrib++] = GL_TRUE; - -		attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB; -		attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB; - -		attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB; -		attrib_list[cur_attrib++] = GL_TRUE; - -		attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB; -		attrib_list[cur_attrib++] = GL_TRUE; - -		attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB; -		attrib_list[cur_attrib++] = 24; - -		attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB; -		attrib_list[cur_attrib++] = 8; - -		U32 end_attrib = 0; -		if (mFSAASamples > 0) -		{ -			end_attrib = cur_attrib; -			attrib_list[cur_attrib++] = WGL_SAMPLE_BUFFERS_ARB; -			attrib_list[cur_attrib++] = GL_TRUE; - -			attrib_list[cur_attrib++] = WGL_SAMPLES_ARB; -			attrib_list[cur_attrib++] = mFSAASamples; -		} - -		// End the list -		attrib_list[cur_attrib++] = 0; - -		GLint pixel_formats[256]; -		U32 num_formats = 0; - -		// First we try and get a 32 bit depth pixel format -		BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); -		if (!result) -		{ -			close(); -			show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit"); -			return FALSE; -		} - -		if (!num_formats) -		{ -			if (end_attrib > 0) -			{ -				LL_INFOS("Window") << "No valid pixel format for " << mFSAASamples << "x anti-aliasing." << LL_ENDL; -				attrib_list[end_attrib] = 0; - -				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); -				if (!result) -				{ -					close(); -					show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit no AA"); -					return FALSE; -				} -			} - -			if (!num_formats) -			{ -				LL_INFOS("Window") << "No 32 bit z-buffer, trying 24 bits instead" << LL_ENDL; -				// Try 24-bit format -				attrib_list[1] = 24; -				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); -				if (!result) -				{ -					close(); -					show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit"); -					return FALSE; -				} - -				if (!num_formats) -				{ -					LL_WARNS("Window") << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << LL_ENDL; -					attrib_list[1] = 16; -					BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); -					if (!result || !num_formats) -					{ -						close(); -						show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit"); -						return FALSE; -					} -				} -			} - -			LL_INFOS("Window") << "Choosing pixel formats: " << num_formats << " pixel formats returned" << LL_ENDL; -		} - -		 - -		S32 swap_method = 0; -		S32 cur_format = num_formats-1; -		GLint swap_query = WGL_SWAP_METHOD_ARB; - -		BOOL found_format = FALSE; - -		while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method)) -		{ -			if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0) -			{ -				found_format = TRUE; -			} -			else -			{ -				--cur_format; -			} -		} -		 -		pixel_format = pixel_formats[cur_format]; -		 -		if (mhDC != 0)											// Does The Window Have A Device Context? -		{ -			wglMakeCurrent(mhDC, 0);							// Set The Current Active Rendering Context To Zero -			if (mhRC != 0)										// Does The Window Have A Rendering Context? -			{ -				wglDeleteContext (mhRC);							// Release The Rendering Context -				mhRC = 0;										// Zero The Rendering Context - -			} -			ReleaseDC (mWindowHandle, mhDC);						// Release The Device Context -			mhDC = 0;											// Zero The Device Context -		} -		DestroyWindow (mWindowHandle);									// Destroy The Window -		 - -		mWindowHandle = CreateWindowEx(dw_ex_style, -			mWindowClassName, -			mWindowTitle, -			WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, -			window_rect.left,								// x pos -			window_rect.top,								// y pos -			window_rect.right - window_rect.left,			// width -			window_rect.bottom - window_rect.top,			// height -			NULL, -			NULL, -			mhInstance, -			NULL); - -		if (!(mhDC = GetDC(mWindowHandle))) -		{ -			close(); -			OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); -			return FALSE; -		} - -		if (!SetPixelFormat(mhDC, pixel_format, &pfd)) -		{ -			close(); -			OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), -				mCallbacks->translateString("MBError"), OSMB_OK); -			return FALSE; -		} - -		if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method)) -		{ -			switch (swap_method) -			{ -			case WGL_SWAP_EXCHANGE_ARB: -				mSwapMethod = SWAP_METHOD_EXCHANGE; -				LL_DEBUGS("Window") << "Swap Method: Exchange" << LL_ENDL; -				break; -			case WGL_SWAP_COPY_ARB: -				mSwapMethod = SWAP_METHOD_COPY; -				LL_DEBUGS("Window") << "Swap Method: Copy" << LL_ENDL; -				break; -			case WGL_SWAP_UNDEFINED_ARB: -				mSwapMethod = SWAP_METHOD_UNDEFINED; -				LL_DEBUGS("Window") << "Swap Method: Undefined" << LL_ENDL; -				break; -			default: -				mSwapMethod = SWAP_METHOD_UNDEFINED; -				LL_DEBUGS("Window") << "Swap Method: Unknown" << LL_ENDL; -				break; -			} -		}		 -	} -	else -	{ -		LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL; -	} - -	// Verify what pixel format we actually received. -	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), -		&pfd)) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	LL_INFOS("Window") << "GL buffer: Color Bits " << S32(pfd.cColorBits)  -		<< " Alpha Bits " << S32(pfd.cAlphaBits) -		<< " Depth Bits " << S32(pfd.cDepthBits)  -		<< LL_ENDL; - -	// make sure we have 32 bits per pixel -	if (pfd.cColorBits < 32 || GetDeviceCaps(mhDC, BITSPIXEL) < 32) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (pfd.cAlphaBits < 8) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (!(mhRC = wglCreateContext(mhDC))) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (!wglMakeCurrent(mhDC, mhRC)) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	if (!gGLManager.initGL()) -	{ -		close(); -		OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK); -		return FALSE; -	} - -	// Disable vertical sync for swap -	if (disable_vsync && wglSwapIntervalEXT) -	{ -		LL_DEBUGS("Window") << "Disabling vertical sync" << LL_ENDL; -		wglSwapIntervalEXT(0); -	} -	else -	{ -		LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL; -	} - -	SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this); -	 -	//register joystick timer callback -	SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer - -	// ok to post quit messages now -	mPostQuit = TRUE; - -	if (auto_show) -	{ -		show(); -		glClearColor(0.0f, 0.0f, 0.0f, 0.f); -		glClear(GL_COLOR_BUFFER_BIT); -		swapBuffers(); -	} - -	return TRUE; -} - -void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size ) -{ -	if( mIsMouseClipping ) -	{ -		RECT client_rect_in_screen_space; -		if( getClientRectInScreenSpace( &client_rect_in_screen_space ) ) -		{ -			ClipCursor( &client_rect_in_screen_space ); -		} -	} - -	// if the window was already maximized, MoveWindow seems to still set the maximized flag even if -	// the window is smaller than maximized. -	// So we're going to do a restore first (which is a ShowWindow call) (SL-44655). - -	// THIS CAUSES DEV-15484 and DEV-15949  -	//ShowWindow(mWindowHandle, SW_RESTORE); -	// NOW we can call MoveWindow -	MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE); -} - -BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) -{ -	LLCoordScreen screen_pos; - -	mMousePositionModified = TRUE; -	if (!mWindowHandle) -	{ -		return FALSE; -	} - -	if (!convertCoords(position, &screen_pos)) -	{ -		return FALSE; -	} - -	// Inform the application of the new mouse position (needed for per-frame -	// hover/picking to function). -	LLCoordGL gl_pos; -	convertCoords(position, &gl_pos); -	mCallbacks->handleMouseMove(this, gl_pos, (MASK)0); -	 -	// DEV-18951 VWR-8524 Camera moves wildly when alt-clicking. -	// Because we have preemptively notified the application of the new -	// mouse position via handleMouseMove() above, we need to clear out -	// any stale mouse move events.  RN/JC -	MSG msg; -	while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) -	{ } - -	return SetCursorPos(screen_pos.mX, screen_pos.mY); -} - -BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position) -{ -	POINT cursor_point; -	LLCoordScreen screen_pos; - -	if (!mWindowHandle || -		!GetCursorPos(&cursor_point)) -	{ -		return FALSE; -	} - -	screen_pos.mX = cursor_point.x; -	screen_pos.mY = cursor_point.y; - -	return convertCoords(screen_pos, position); -} - -void LLWindowWin32::hideCursor() -{ -	while (ShowCursor(FALSE) >= 0) -	{ -		// nothing, wait for cursor to push down -	} -	mCursorHidden = TRUE; -	mHideCursorPermanent = TRUE; -} - -void LLWindowWin32::showCursor() -{ -	// makes sure the cursor shows up -	while (ShowCursor(TRUE) < 0) -	{ -		// do nothing, wait for cursor to pop out -	} -	mCursorHidden = FALSE; -	mHideCursorPermanent = FALSE; -} - -void LLWindowWin32::showCursorFromMouseMove() -{ -	if (!mHideCursorPermanent) -	{ -		showCursor(); -	} -} - -void LLWindowWin32::hideCursorUntilMouseMove() -{ -	if (!mHideCursorPermanent) -	{ -		hideCursor(); -		mHideCursorPermanent = FALSE; -	} -} - -BOOL LLWindowWin32::isCursorHidden() -{ -	return mCursorHidden; -} - - -HCURSOR LLWindowWin32::loadColorCursor(LPCTSTR name) -{ -	return (HCURSOR)LoadImage(mhInstance, -							  name, -							  IMAGE_CURSOR, -							  0,	// default width -							  0,	// default height -							  LR_DEFAULTCOLOR); -} - - -void LLWindowWin32::initCursors() -{ -	mCursor[ UI_CURSOR_ARROW ]		= LoadCursor(NULL, IDC_ARROW); -	mCursor[ UI_CURSOR_WAIT ]		= LoadCursor(NULL, IDC_WAIT); -	mCursor[ UI_CURSOR_HAND ]		= LoadCursor(NULL, IDC_HAND); -	mCursor[ UI_CURSOR_IBEAM ]		= LoadCursor(NULL, IDC_IBEAM); -	mCursor[ UI_CURSOR_CROSS ]		= LoadCursor(NULL, IDC_CROSS); -	mCursor[ UI_CURSOR_SIZENWSE ]	= LoadCursor(NULL, IDC_SIZENWSE); -	mCursor[ UI_CURSOR_SIZENESW ]	= LoadCursor(NULL, IDC_SIZENESW); -	mCursor[ UI_CURSOR_SIZEWE ]		= LoadCursor(NULL, IDC_SIZEWE);   -	mCursor[ UI_CURSOR_SIZENS ]		= LoadCursor(NULL, IDC_SIZENS);   -	mCursor[ UI_CURSOR_NO ]			= LoadCursor(NULL, IDC_NO); -	mCursor[ UI_CURSOR_WORKING ]	= LoadCursor(NULL, IDC_APPSTARTING);  - -	HMODULE module = GetModuleHandle(NULL); -	mCursor[ UI_CURSOR_TOOLGRAB ]	= LoadCursor(module, TEXT("TOOLGRAB")); -	mCursor[ UI_CURSOR_TOOLLAND ]	= LoadCursor(module, TEXT("TOOLLAND")); -	mCursor[ UI_CURSOR_TOOLFOCUS ]	= LoadCursor(module, TEXT("TOOLFOCUS")); -	mCursor[ UI_CURSOR_TOOLCREATE ]	= LoadCursor(module, TEXT("TOOLCREATE")); -	mCursor[ UI_CURSOR_ARROWDRAG ]	= LoadCursor(module, TEXT("ARROWDRAG")); -	mCursor[ UI_CURSOR_ARROWCOPY ]	= LoadCursor(module, TEXT("ARROWCOPY")); -	mCursor[ UI_CURSOR_ARROWDRAGMULTI ]	= LoadCursor(module, TEXT("ARROWDRAGMULTI")); -	mCursor[ UI_CURSOR_ARROWCOPYMULTI ]	= LoadCursor(module, TEXT("ARROWCOPYMULTI")); -	mCursor[ UI_CURSOR_NOLOCKED ]	= LoadCursor(module, TEXT("NOLOCKED")); -	mCursor[ UI_CURSOR_ARROWLOCKED ]= LoadCursor(module, TEXT("ARROWLOCKED")); -	mCursor[ UI_CURSOR_GRABLOCKED ]	= LoadCursor(module, TEXT("GRABLOCKED")); -	mCursor[ UI_CURSOR_TOOLTRANSLATE ]	= LoadCursor(module, TEXT("TOOLTRANSLATE")); -	mCursor[ UI_CURSOR_TOOLROTATE ]	= LoadCursor(module, TEXT("TOOLROTATE"));  -	mCursor[ UI_CURSOR_TOOLSCALE ]	= LoadCursor(module, TEXT("TOOLSCALE")); -	mCursor[ UI_CURSOR_TOOLCAMERA ]	= LoadCursor(module, TEXT("TOOLCAMERA")); -	mCursor[ UI_CURSOR_TOOLPAN ]	= LoadCursor(module, TEXT("TOOLPAN")); -	mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN")); -	mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3")); -	mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE")); - -	// Color cursors -	mCursor[UI_CURSOR_TOOLPLAY] = loadColorCursor(TEXT("TOOLPLAY")); -	mCursor[UI_CURSOR_TOOLPAUSE] = loadColorCursor(TEXT("TOOLPAUSE")); -	mCursor[UI_CURSOR_TOOLMEDIAOPEN] = loadColorCursor(TEXT("TOOLMEDIAOPEN")); - -	// Note: custom cursors that are not found make LoadCursor() return NULL. -	for( S32 i = 0; i < UI_CURSOR_COUNT; i++ ) -	{ -		if( !mCursor[i] ) -		{ -			mCursor[i] = LoadCursor(NULL, IDC_ARROW); -		} -	} -} - - - -void LLWindowWin32::setCursor(ECursorType cursor) -{ -	if (cursor == UI_CURSOR_ARROW -		&& mBusyCount > 0) -	{ -		cursor = UI_CURSOR_WORKING; -	} - -	if( mCurrentCursor != cursor ) -	{ -		mCurrentCursor = cursor; -		SetCursor( mCursor[cursor] ); -	} -} - -ECursorType LLWindowWin32::getCursor() const -{ -	return mCurrentCursor; -} - -void LLWindowWin32::captureMouse() -{ -	SetCapture(mWindowHandle); -} - -void LLWindowWin32::releaseMouse() -{ -	// *NOTE:Mani ReleaseCapture will spawn new windows messages... -	// which will in turn call our MainWindowProc. It therefore requires -	// pausing *and more importantly resumption* of the mainlooptimeout... -	// just like DispatchMessage below. -	mCallbacks->handlePauseWatchdog(this); -	ReleaseCapture(); -	mCallbacks->handleResumeWatchdog(this); -} - - -void LLWindowWin32::delayInputProcessing() -{ -	mInputProcessingPaused = TRUE; -} - -void LLWindowWin32::gatherInput() -{ -	MSG		msg; -	int		msg_count = 0; - -	LLMemType m1(LLMemType::MTYPE_GATHER_INPUT); - -	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE) -	{ -		mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput"); -		TranslateMessage(&msg); - -		// turn watchdog off in here to not fail if windows is doing something wacky -		mCallbacks->handlePauseWatchdog(this); -		DispatchMessage(&msg); -		mCallbacks->handleResumeWatchdog(this); -		msg_count++; - -		if ( mInputProcessingPaused ) -		{ -			break; -		} -		/* Attempted workaround for problem where typing fast and hitting -		   return would result in only part of the text being sent. JC - -		BOOL key_posted = TranslateMessage(&msg); -		DispatchMessage(&msg); -		msg_count++; - -		// If a key was translated, a WM_CHAR might have been posted to the end -		// of the event queue.  We need it immediately. -		if (key_posted && msg.message == WM_KEYDOWN) -		{ -			if (PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, PM_REMOVE)) -			{ -				TranslateMessage(&msg); -				DispatchMessage(&msg); -				msg_count++; -			} -		} -		*/ -		mCallbacks->handlePingWatchdog(this, "Main:AsyncCallbackGatherInput"); -		// For async host by name support.  Really hacky. -		if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) -		{ -			gAsyncMsgCallback(msg); -		} -	} - -	mInputProcessingPaused = FALSE; - -	// clear this once we've processed all mouse messages that might have occurred after -	// we slammed the mouse position -	mMousePositionModified = FALSE; -} - -static LLFastTimer::DeclareTimer FTM_KEYHANDLER("Handle Keyboard"); -static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse"); - -LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) -{ -	LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA); - - -	if (NULL != window_imp) -	{ -		window_imp->mCallbacks->handleResumeWatchdog(window_imp); -		window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:StartWndProc"); -		// Has user provided their own window callback? -		if (NULL != window_imp->mWndProc) -		{ -			if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param)) -			{ -				// user has handled window message -				return 0; -			} -		} - -		window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:PreSwitchWndProc"); -		 -		// Juggle to make sure we can get negative positions for when -		// mouse is outside window. -		LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); - -		// This doesn't work, as LOWORD returns unsigned short. -		//LLCoordWindow window_coord(LOWORD(l_param), HIWORD(l_param)); -		LLCoordGL gl_coord; - -		// pass along extended flag in mask -		MASK mask = (l_param>>16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0; -		BOOL eat_keystroke = TRUE; - -		switch(u_msg) -		{ -			RECT	update_rect; -			S32		update_width; -			S32		update_height; - -		case WM_TIMER: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_TIMER"); -			window_imp->mCallbacks->handleTimerEvent(window_imp); -			break; - -		case WM_DEVICECHANGE: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DEVICECHANGE"); -			if (gDebugWindowProc) -			{ -				llinfos << "  WM_DEVICECHANGE: wParam=" << w_param  -						<< "; lParam=" << l_param << llendl; -			} -			if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL) -			{ -				if (window_imp->mCallbacks->handleDeviceChange(window_imp)) -				{ -					return 0; -				} -			} -			break; - -		case WM_PAINT: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PAINT"); -			GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE); -			update_width = update_rect.right - update_rect.left + 1; -			update_height = update_rect.bottom - update_rect.top + 1; -			window_imp->mCallbacks->handlePaint(window_imp, update_rect.left, update_rect.top, -				update_width, update_height); -			break; -		case WM_PARENTNOTIFY: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PARENTNOTIFY"); -			u_msg = u_msg; -			break; - -		case WM_SETCURSOR: -			// This message is sent whenever the cursor is moved in a window. -			// You need to set the appropriate cursor appearance. - -			// Only take control of cursor over client region of window -			// This allows Windows(tm) to handle resize cursors, etc. -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETCURSOR"); -			if (LOWORD(l_param) == HTCLIENT) -			{ -				SetCursor(window_imp->mCursor[ window_imp->mCurrentCursor] ); -				return 0; -			} -			break; - -		case WM_ENTERMENULOOP: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ENTERMENULOOP"); -			window_imp->mCallbacks->handleWindowBlock(window_imp); -			break; - -		case WM_EXITMENULOOP: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_EXITMENULOOP"); -			window_imp->mCallbacks->handleWindowUnblock(window_imp); -			break; - -		case WM_ACTIVATEAPP: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATEAPP"); -			{ -				// This message should be sent whenever the app gains or loses focus. -				BOOL activating = (BOOL) w_param; -				BOOL minimized = window_imp->getMinimized(); - -				if (gDebugWindowProc) -				{ -					LL_INFOS("Window") << "WINDOWPROC ActivateApp " -						<< " activating " << S32(activating) -						<< " minimized " << S32(minimized) -						<< " fullscreen " << S32(window_imp->mFullscreen) -						<< LL_ENDL; -				} - -				if (window_imp->mFullscreen) -				{ -					// When we run fullscreen, restoring or minimizing the app needs  -					// to switch the screen resolution -					if (activating) -					{ -						window_imp->setFullscreenResolution(); -						window_imp->restore(); -					} -					else -					{ -						window_imp->minimize(); -						window_imp->resetDisplayResolution(); -					} -				} - -				window_imp->mCallbacks->handleActivateApp(window_imp, activating); - -				break; -			} - -		case WM_ACTIVATE: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATE"); -			{ -				// Can be one of WA_ACTIVE, WA_CLICKACTIVE, or WA_INACTIVE -				BOOL activating = (LOWORD(w_param) != WA_INACTIVE); - -				BOOL minimized = BOOL(HIWORD(w_param)); - -				if (!activating && LLWinImm::isAvailable() && window_imp->mPreeditor) -				{ -					window_imp->interruptLanguageTextInput(); -				} - -				// JC - I'm not sure why, but if we don't report that we handled the  -				// WM_ACTIVATE message, the WM_ACTIVATEAPP messages don't work  -				// properly when we run fullscreen. -				if (gDebugWindowProc) -				{ -					LL_INFOS("Window") << "WINDOWPROC Activate " -						<< " activating " << S32(activating)  -						<< " minimized " << S32(minimized) -						<< LL_ENDL; -				} - -				// Don't handle this. -				break; -			} - -		case WM_QUERYOPEN: -			// TODO: use this to return a nice icon -			break; - -		case WM_SYSCOMMAND: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSCOMMAND"); -			switch(w_param) -			{ -			case SC_KEYMENU:  -				// Disallow the ALT key from triggering the default system menu. -				return 0;		 - -			case SC_SCREENSAVE: -			case SC_MONITORPOWER: -				// eat screen save messages and prevent them! -				return 0; -			} -			break; - -		case WM_CLOSE: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CLOSE"); -			// Will the app allow the window to close? -			if (window_imp->mCallbacks->handleCloseRequest(window_imp)) -			{ -				// Get the app to initiate cleanup. -				window_imp->mCallbacks->handleQuit(window_imp); -				// The app is responsible for calling destroyWindow when done with GL -			} -			return 0; - -		case WM_DESTROY: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DESTROY"); -			if (window_imp->shouldPostQuit()) -			{ -				PostQuitMessage(0);  // Posts WM_QUIT with an exit code of 0 -			} -			return 0; - -		case WM_COMMAND: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COMMAND"); -			if (!HIWORD(w_param)) // this message is from a menu -			{ -				window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param)); -			} -			break; - -		case WM_SYSKEYDOWN: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSKEYDOWN"); -			// allow system keys, such as ALT-F4 to be processed by Windows -			eat_keystroke = FALSE; -		case WM_KEYDOWN: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN"); -			{ -				if (gDebugWindowProc) -				{ -					LL_INFOS("Window") << "Debug WindowProc WM_KEYDOWN " -						<< " key " << S32(w_param)  -						<< LL_ENDL; -				} -				if(gKeyboard->handleKeyDown(w_param, mask) && eat_keystroke) -				{ -					return 0; -				} -				// pass on to windows if we didn't handle it -				break; -			} -		case WM_SYSKEYUP: -			eat_keystroke = FALSE; -		case WM_KEYUP: -		{ -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP"); -			LLFastTimer t2(FTM_KEYHANDLER); - -			if (gDebugWindowProc) -			{ -				LL_INFOS("Window") << "Debug WindowProc WM_KEYUP " -					<< " key " << S32(w_param)  -					<< LL_ENDL; -			} -			if (gKeyboard->handleKeyUp(w_param, mask) && eat_keystroke) -			{ -				return 0; -			} - -			// pass on to windows -			break; -		} -		case WM_IME_SETCONTEXT: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_SETCONTEXT"); -			if (gDebugWindowProc) -			{ -				llinfos << "WM_IME_SETCONTEXT" << llendl; -			} -			if (LLWinImm::isAvailable() && window_imp->mPreeditor) -			{ -				l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW; -				// Invoke DefWinProc with the modified LPARAM. -			} -			break; - -		case WM_IME_STARTCOMPOSITION: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_STARTCOMPOSITION"); -			if (gDebugWindowProc) -			{ -				llinfos << "WM_IME_STARTCOMPOSITION" << llendl; -			} -			if (LLWinImm::isAvailable() && window_imp->mPreeditor) -			{ -				window_imp->handleStartCompositionMessage(); -				return 0; -			} -			break; - -		case WM_IME_ENDCOMPOSITION: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_ENDCOMPOSITION"); -			if (gDebugWindowProc) -			{ -				llinfos << "WM_IME_ENDCOMPOSITION" << llendl; -			} -			if (LLWinImm::isAvailable() && window_imp->mPreeditor) -			{ -				return 0; -			} -			break; - -		case WM_IME_COMPOSITION: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_COMPOSITION"); -			if (gDebugWindowProc) -			{ -				llinfos << "WM_IME_COMPOSITION" << llendl; -			} -			if (LLWinImm::isAvailable() && window_imp->mPreeditor) -			{ -				window_imp->handleCompositionMessage(l_param); -				return 0; -			} -			break; - -		case WM_IME_REQUEST: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_REQUEST"); -			if (gDebugWindowProc) -			{ -				llinfos << "WM_IME_REQUEST" << llendl; -			} -			if (LLWinImm::isAvailable() && window_imp->mPreeditor) -			{ -				LRESULT result = 0; -				if (window_imp->handleImeRequests(w_param, l_param, &result)) -				{ -					return result; -				} -			} -			break; - -		case WM_CHAR: -			// Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need -			// to figure out how that works. - Doug -			// -			// ... Well, I don't think so. -			// How it works is explained in Win32 API document, but WM_UNICHAR didn't work -			// as specified at least on Windows XP SP1 Japanese version.  I have never used -			// it since then, and I'm not sure whether it has been fixed now, but I don't think -			// it is worth trying.  The good old WM_CHAR works just fine even for supplementary -			// characters.  We just need to take care of surrogate pairs sent as two WM_CHAR's -			// by ourselves.  It is not that tough.  -- Alissa Sabre @ SL -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CHAR"); -			if (gDebugWindowProc) -			{ -				LL_INFOS("Window") << "Debug WindowProc WM_CHAR " -					<< " key " << S32(w_param)  -					<< LL_ENDL; -			} -			// Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE, -			// we *did* processed the event, so I believe we should not pass it to DefWindowProc... -			window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE)); -			return 0; - -		case WM_LBUTTONDOWN: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN"); -				LLFastTimer t2(FTM_MOUSEHANDLER); -				if (LLWinImm::isAvailable() && window_imp->mPreeditor) -				{ -					window_imp->interruptLanguageTextInput(); -				} - -				// Because we move the cursor position in the app, we need to query -				// to find out where the cursor at the time the event is handled. -				// If we don't do this, many clicks could get buffered up, and if the -				// first click changes the cursor position, all subsequent clicks -				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window; -				if (window_imp->mMousePositionModified) -				{ -					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); -				} -				else -				{ -					window_imp->convertCoords(window_coord, &gl_coord); -				} -				MASK mask = gKeyboard->currentMask(TRUE); -				// generate move event to update mouse coordinates -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); -				if (window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask)) -				{ -					return 0; -				} -			} -			break; - -		case WM_LBUTTONDBLCLK: -		//RN: ignore right button double clicks for now -		//case WM_RBUTTONDBLCLK: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDBLCLK"); -				// Because we move the cursor position in the app, we need to query -				// to find out where the cursor at the time the event is handled. -				// If we don't do this, many clicks could get buffered up, and if the -				// first click changes the cursor position, all subsequent clicks -				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window; -				if (window_imp->mMousePositionModified) -				{ -					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); -				} -				else -				{ -					window_imp->convertCoords(window_coord, &gl_coord); -				} -				MASK mask = gKeyboard->currentMask(TRUE); -				// generate move event to update mouse coordinates -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); -				if (window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask) ) -				{ -					return 0; -				} -			} -			break; - -		case WM_LBUTTONUP: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP"); -				LLFastTimer t2(FTM_MOUSEHANDLER); -				//if (gDebugClicks) -				//{ -				//	LL_INFOS("Window") << "WndProc left button up" << LL_ENDL; -				//} -				// Because we move the cursor position in the app, we need to query -				// to find out where the cursor at the time the event is handled. -				// If we don't do this, many clicks could get buffered up, and if the -				// first click changes the cursor position, all subsequent clicks -				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window; -				if (window_imp->mMousePositionModified) -				{ -					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); -				} -				else -				{ -					window_imp->convertCoords(window_coord, &gl_coord); -				} -				MASK mask = gKeyboard->currentMask(TRUE); -				// generate move event to update mouse coordinates -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); -				if (window_imp->mCallbacks->handleMouseUp(window_imp, gl_coord, mask)) -				{ -					return 0; -				} -			} -			break; - -		case WM_RBUTTONDBLCLK: -		case WM_RBUTTONDOWN: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONDOWN"); -				LLFastTimer t2(FTM_MOUSEHANDLER); -				if (LLWinImm::isAvailable() && window_imp->mPreeditor) -				{ -					window_imp->interruptLanguageTextInput(); -				} - -				// Because we move the cursor position in the llviewerapp, we need to query -				// to find out where the cursor at the time the event is handled. -				// If we don't do this, many clicks could get buffered up, and if the -				// first click changes the cursor position, all subsequent clicks -				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window; -				if (window_imp->mMousePositionModified) -				{ -					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); -				} -				else -				{ -					window_imp->convertCoords(window_coord, &gl_coord); -				} -				MASK mask = gKeyboard->currentMask(TRUE); -				// generate move event to update mouse coordinates -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); -				if (window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask)) -				{ -					return 0; -				} -			} -			break; - -		case WM_RBUTTONUP: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONUP"); -				LLFastTimer t2(FTM_MOUSEHANDLER); -				// Because we move the cursor position in the app, we need to query -				// to find out where the cursor at the time the event is handled. -				// If we don't do this, many clicks could get buffered up, and if the -				// first click changes the cursor position, all subsequent clicks -				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window; -				if (window_imp->mMousePositionModified) -				{ -					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); -				} -				else -				{ -					window_imp->convertCoords(window_coord, &gl_coord); -				} -				MASK mask = gKeyboard->currentMask(TRUE); -				// generate move event to update mouse coordinates -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); -				if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask)) -				{ -					return 0; -				} -			} -			break; - -		case WM_MBUTTONDOWN: -//		case WM_MBUTTONDBLCLK: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN"); -				LLFastTimer t2(FTM_MOUSEHANDLER); -				if (LLWinImm::isAvailable() && window_imp->mPreeditor) -				{ -					window_imp->interruptLanguageTextInput(); -				} - -				// Because we move the cursor position in tllviewerhe app, we need to query -				// to find out where the cursor at the time the event is handled. -				// If we don't do this, many clicks could get buffered up, and if the -				// first click changes the cursor position, all subsequent clicks -				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window; -				if (window_imp->mMousePositionModified) -				{ -					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); -				} -				else -				{ -					window_imp->convertCoords(window_coord, &gl_coord); -				} -				MASK mask = gKeyboard->currentMask(TRUE); -				// generate move event to update mouse coordinates -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); -				if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask)) -				{ -					return 0; -				} -			} -			break; - -		case WM_MBUTTONUP: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP"); -				LLFastTimer t2(FTM_MOUSEHANDLER); -				// Because we move the cursor position in tllviewerhe app, we need to query -				// to find out where the cursor at the time the event is handled. -				// If we don't do this, many clicks could get buffered up, and if the -				// first click changes the cursor position, all subsequent clicks -				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window; -				if (window_imp->mMousePositionModified) -				{ -					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); -				} -				else -				{ -					window_imp->convertCoords(window_coord, &gl_coord); -				} -				MASK mask = gKeyboard->currentMask(TRUE); -				// generate move event to update mouse coordinates -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); -				if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask)) -				{ -					return 0; -				} -			} -			break; - -		case WM_MOUSEWHEEL: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEWHEEL"); -				static short z_delta = 0; - -				z_delta += HIWORD(w_param); -				// cout << "z_delta " << z_delta << endl; - -				// current mouse wheels report changes in increments of zDelta (+120, -120) -				// Future, higher resolution mouse wheels may report smaller deltas. -				// So we sum the deltas and only act when we've exceeded WHEEL_DELTA -				// -				// If the user rapidly spins the wheel, we can get messages with -				// large deltas, like 480 or so.  Thus we need to scroll more quickly. -				if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) -				{ -					window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA); -					z_delta = 0; -				} -				return 0; -			} -			/* -			// TODO: add this after resolving _WIN32_WINNT issue -			case WM_MOUSELEAVE: -			{ -			window_imp->mCallbacks->handleMouseLeave(window_imp); - -			//				TRACKMOUSEEVENT track_mouse_event; -			//				track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); -			//				track_mouse_event.dwFlags = TME_LEAVE; -			//				track_mouse_event.hwndTrack = h_wnd; -			//				track_mouse_event.dwHoverTime = HOVER_DEFAULT; -			//				TrackMouseEvent( &track_mouse_event );  -			return 0; -			} -			*/ -			// Handle mouse movement within the window -		case WM_MOUSEMOVE: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE"); -				window_imp->convertCoords(window_coord, &gl_coord); -				MASK mask = gKeyboard->currentMask(TRUE); -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); -				return 0; -			} - -		case WM_SIZE: -			{ -				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SIZE"); -				S32 width = S32( LOWORD(l_param) ); -				S32 height = S32( HIWORD(l_param) ); - -				if (gDebugWindowProc) -				{ -					BOOL maximized = ( w_param == SIZE_MAXIMIZED ); -					BOOL restored  = ( w_param == SIZE_RESTORED ); -					BOOL minimized = ( w_param == SIZE_MINIMIZED ); - -					LL_INFOS("Window") << "WINDOWPROC Size " -						<< width << "x" << height -						<< " max " << S32(maximized) -						<< " min " << S32(minimized) -						<< " rest " << S32(restored) -						<< LL_ENDL; -				} - -				// There's an odd behavior with WM_SIZE that I would call a bug. If  -				// the window is maximized, and you call MoveWindow() with a size smaller -				// than a maximized window, it ends up sending WM_SIZE with w_param set  -				// to SIZE_MAXIMIZED -- which isn't true. So the logic below doesn't work. -				// (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see  -				// LLWindowWin32::moveWindow in this file).  - -				// If we are now restored, but we weren't before, this -				// means that the window was un-minimized. -				if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED) -				{ -					window_imp->mCallbacks->handleActivate(window_imp, TRUE); -				} - -				// handle case of window being maximized from fully minimized state -				if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED) -				{ -					window_imp->mCallbacks->handleActivate(window_imp, TRUE); -				} - -				// Also handle the minimization case -				if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED) -				{ -					window_imp->mCallbacks->handleActivate(window_imp, FALSE); -				} - -				// Actually resize all of our views -				if (w_param != SIZE_MINIMIZED) -				{ -					// Ignore updates for minimizing and minimized "windows" -					window_imp->mCallbacks->handleResize(	window_imp,  -						LOWORD(l_param),  -						HIWORD(l_param) ); -				} - -				window_imp->mLastSizeWParam = w_param; - -				return 0; -			} - -		case WM_SETFOCUS: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETFOCUS"); -			if (gDebugWindowProc) -			{ -				LL_INFOS("Window") << "WINDOWPROC SetFocus" << LL_ENDL; -			} -			window_imp->mCallbacks->handleFocus(window_imp); -			return 0; - -		case WM_KILLFOCUS: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KILLFOCUS"); -			if (gDebugWindowProc) -			{ -				LL_INFOS("Window") << "WINDOWPROC KillFocus" << LL_ENDL; -			} -			window_imp->mCallbacks->handleFocusLost(window_imp); -			return 0; - -		case WM_COPYDATA: -			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA"); -			// received a URL -			PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param; -			window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData); -			return 0;			 -		} - -	window_imp->mCallbacks->handlePauseWatchdog(window_imp);	 -	} - - -	// pass unhandled messages down to Windows -	return DefWindowProc(h_wnd, u_msg, w_param, l_param); -} - -BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to) -{ -	S32		client_height; -	RECT	client_rect; -	LLCoordWindow window_position; - -	if (!mWindowHandle || -		!GetClientRect(mWindowHandle, &client_rect) || -		NULL == to) -	{ -		return FALSE; -	} - -	to->mX = from.mX; -	client_height = client_rect.bottom - client_rect.top; -	to->mY = client_height - from.mY - 1; - -	return TRUE; -} - -BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to) -{ -	S32		client_height; -	RECT	client_rect; - -	if (!mWindowHandle || -		!GetClientRect(mWindowHandle, &client_rect) || -		NULL == to) -	{ -		return FALSE; -	} - -	to->mX = from.mX; -	client_height = client_rect.bottom - client_rect.top; -	to->mY = client_height - from.mY - 1; - -	return TRUE; -} - -BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to) -{	 -	POINT mouse_point; - -	mouse_point.x = from.mX; -	mouse_point.y = from.mY; -	BOOL result = ScreenToClient(mWindowHandle, &mouse_point); - -	if (result) -	{ -		to->mX = mouse_point.x; -		to->mY = mouse_point.y; -	} - -	return result; -} - -BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to) -{ -	POINT mouse_point; - -	mouse_point.x = from.mX; -	mouse_point.y = from.mY; -	BOOL result = ClientToScreen(mWindowHandle, &mouse_point); - -	if (result) -	{ -		to->mX = mouse_point.x; -		to->mY = mouse_point.y; -	} - -	return result; -} - -BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to) -{ -	LLCoordWindow window_coord; - -	if (!mWindowHandle || (NULL == to)) -	{ -		return FALSE; -	} - -	convertCoords(from, &window_coord); -	convertCoords(window_coord, to); -	return TRUE; -} - -BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to) -{ -	LLCoordWindow window_coord; - -	if (!mWindowHandle || (NULL == to)) -	{ -		return FALSE; -	} - -	convertCoords(from, &window_coord); -	convertCoords(window_coord, to); -	return TRUE; -} - - -BOOL LLWindowWin32::isClipboardTextAvailable() -{ -	return IsClipboardFormatAvailable(CF_UNICODETEXT); -} - - -BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst) -{ -	BOOL success = FALSE; - -	if (IsClipboardFormatAvailable(CF_UNICODETEXT)) -	{ -		if (OpenClipboard(mWindowHandle)) -		{ -			HGLOBAL h_data = GetClipboardData(CF_UNICODETEXT); -			if (h_data) -			{ -				WCHAR *utf16str = (WCHAR*) GlobalLock(h_data); -				if (utf16str) -				{ -					dst = utf16str_to_wstring(utf16str); -					LLWStringUtil::removeCRLF(dst); -					GlobalUnlock(h_data); -					success = TRUE; -				} -			} -			CloseClipboard(); -		} -	} - -	return success; -} - - -BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr) -{ -	BOOL success = FALSE; - -	if (OpenClipboard(mWindowHandle)) -	{ -		EmptyClipboard(); - -		// Provide a copy of the data in Unicode format. -		LLWString sanitized_string(wstr); -		LLWStringUtil::addCRLF(sanitized_string); -		llutf16string out_utf16 = wstring_to_utf16str(sanitized_string); -		const size_t size_utf16 = (out_utf16.length() + 1) * sizeof(WCHAR); - -		// Memory is allocated and then ownership of it is transfered to the system. -		HGLOBAL hglobal_copy_utf16 = GlobalAlloc(GMEM_MOVEABLE, size_utf16);  -		if (hglobal_copy_utf16) -		{ -			WCHAR* copy_utf16 = (WCHAR*) GlobalLock(hglobal_copy_utf16); -			if (copy_utf16) -			{ -				memcpy(copy_utf16, out_utf16.c_str(), size_utf16);	/* Flawfinder: ignore */ -				GlobalUnlock(hglobal_copy_utf16); - -				if (SetClipboardData(CF_UNICODETEXT, hglobal_copy_utf16)) -				{ -					success = TRUE; -				} -			} -		} - -		CloseClipboard(); -	} - -	return success; -} - -// Constrains the mouse to the window. -void LLWindowWin32::setMouseClipping( BOOL b ) -{ -	if( b != mIsMouseClipping ) -	{ -		BOOL success = FALSE; - -		if( b ) -		{ -			GetClipCursor( &mOldMouseClip ); - -			RECT client_rect_in_screen_space; -			if( getClientRectInScreenSpace( &client_rect_in_screen_space ) ) -			{ -				success = ClipCursor( &client_rect_in_screen_space ); -			} -		} -		else -		{ -			// Must restore the old mouse clip, which may be set by another window. -			success = ClipCursor( &mOldMouseClip ); -			SetRect( &mOldMouseClip, 0, 0, 0, 0 ); -		} - -		if( success ) -		{ -			mIsMouseClipping = b; -		} -	} -} - -BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp ) -{ -	BOOL success = FALSE; - -	RECT client_rect; -	if( mWindowHandle && GetClientRect(mWindowHandle, &client_rect) ) -	{ -		POINT top_left; -		top_left.x = client_rect.left; -		top_left.y = client_rect.top; -		ClientToScreen(mWindowHandle, &top_left);  - -		POINT bottom_right; -		bottom_right.x = client_rect.right; -		bottom_right.y = client_rect.bottom; -		ClientToScreen(mWindowHandle, &bottom_right);  - -		SetRect( rectp, -			top_left.x, -			top_left.y, -			bottom_right.x, -			bottom_right.y ); - -		success = TRUE; -	} - -	return success; -} - -void LLWindowWin32::flashIcon(F32 seconds) -{ -	FLASHWINFO flash_info; - -	flash_info.cbSize = sizeof(FLASHWINFO); -	flash_info.hwnd = mWindowHandle; -	flash_info.dwFlags = FLASHW_TRAY; -	flash_info.uCount = UINT(seconds / ICON_FLASH_TIME); -	flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds -	FlashWindowEx(&flash_info); -} - -F32 LLWindowWin32::getGamma() -{ -	return mCurrentGamma; -} - -BOOL LLWindowWin32::restoreGamma() -{ -	return SetDeviceGammaRamp(mhDC, mPrevGammaRamp); -} - -BOOL LLWindowWin32::setGamma(const F32 gamma) -{ -	mCurrentGamma = gamma; - -	LL_DEBUGS("Window") << "Setting gamma to " << gamma << LL_ENDL; - -	for ( int i = 0; i < 256; ++i ) -	{ -		int mult = 256 - ( int ) ( ( gamma - 1.0f ) * 128.0f ); - -		int value = mult * i; - -		if ( value > 0xffff ) -			value = 0xffff; - -		mCurrentGammaRamp [ 0 * 256 + i ] =  -			mCurrentGammaRamp [ 1 * 256 + i ] =  -				mCurrentGammaRamp [ 2 * 256 + i ] = ( WORD )value; -	}; - -	return SetDeviceGammaRamp ( mhDC, mCurrentGammaRamp ); -} - -void LLWindowWin32::setFSAASamples(const U32 fsaa_samples) -{ -	mFSAASamples = fsaa_samples; -} - -U32 LLWindowWin32::getFSAASamples() -{ -	return mFSAASamples; -} - -LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_resolutions) -{ -	if (!mSupportedResolutions) -	{ -		mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS]; -		DEVMODE dev_mode; - -		mNumSupportedResolutions = 0; -		for (S32 mode_num = 0; mNumSupportedResolutions < MAX_NUM_RESOLUTIONS; mode_num++) -		{ -			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) -			{ -				break; -			} - -			if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL && -				dev_mode.dmPelsWidth >= 800 && -				dev_mode.dmPelsHeight >= 600) -			{ -				BOOL resolution_exists = FALSE; -				for(S32 i = 0; i < mNumSupportedResolutions; i++) -				{ -					if (mSupportedResolutions[i].mWidth == dev_mode.dmPelsWidth && -						mSupportedResolutions[i].mHeight == dev_mode.dmPelsHeight) -					{ -						resolution_exists = TRUE; -					} -				} -				if (!resolution_exists) -				{ -					mSupportedResolutions[mNumSupportedResolutions].mWidth = dev_mode.dmPelsWidth; -					mSupportedResolutions[mNumSupportedResolutions].mHeight = dev_mode.dmPelsHeight; -					mNumSupportedResolutions++; -				} -			} -		} -	} - -	num_resolutions = mNumSupportedResolutions; -	return mSupportedResolutions; -} - - -F32 LLWindowWin32::getNativeAspectRatio() -{ -	if (mOverrideAspectRatio > 0.f) -	{ -		return mOverrideAspectRatio; -	} -	else if (mNativeAspectRatio > 0.f) -	{ -		// we grabbed this value at startup, based on the user's desktop settings -		return mNativeAspectRatio; -	} -	// RN: this hack presumes that the largest supported resolution is monitor-limited -	// and that pixels in that mode are square, therefore defining the native aspect ratio -	// of the monitor...this seems to work to a close approximation for most CRTs/LCDs -	S32 num_resolutions; -	LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions); - -	return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight); -} - -F32 LLWindowWin32::getPixelAspectRatio() -{ -	F32 pixel_aspect = 1.f; -	if (getFullscreen()) -	{ -		LLCoordScreen screen_size; -		getSize(&screen_size); -		pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX; -	} - -	return pixel_aspect; -} - -// Change display resolution.  Returns true if successful. -// protected -BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh) -{ -	DEVMODE dev_mode; -	dev_mode.dmSize = sizeof(dev_mode); -	BOOL success = FALSE; - -	// Don't change anything if we don't have to -	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) -	{ -		if (dev_mode.dmPelsWidth        == width && -			dev_mode.dmPelsHeight       == height && -			dev_mode.dmBitsPerPel       == bits && -			dev_mode.dmDisplayFrequency == refresh ) -		{ -			// ...display mode identical, do nothing -			return TRUE; -		} -	} - -	memset(&dev_mode, 0, sizeof(dev_mode)); -	dev_mode.dmSize = sizeof(dev_mode); -	dev_mode.dmPelsWidth        = width; -	dev_mode.dmPelsHeight       = height; -	dev_mode.dmBitsPerPel       = bits; -	dev_mode.dmDisplayFrequency = refresh; -	dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; - -	// CDS_FULLSCREEN indicates that this is a temporary change to the device mode. -	LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN); - -	success = (DISP_CHANGE_SUCCESSFUL == cds_result); - -	if (!success) -	{ -		LL_WARNS("Window") << "setDisplayResolution failed, " -			<< width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL; -	} - -	return success; -} - -// protected -BOOL LLWindowWin32::setFullscreenResolution() -{ -	if (mFullscreen) -	{ -		return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh); -	} -	else -	{ -		return FALSE; -	} -} - -// protected -BOOL LLWindowWin32::resetDisplayResolution() -{ -	LL_DEBUGS("Window") << "resetDisplayResolution START" << LL_ENDL; - -	LONG cds_result = ChangeDisplaySettings(NULL, 0); - -	BOOL success = (DISP_CHANGE_SUCCESSFUL == cds_result); - -	if (!success) -	{ -		LL_WARNS("Window") << "resetDisplayResolution failed" << LL_ENDL; -	} - -	LL_DEBUGS("Window") << "resetDisplayResolution END" << LL_ENDL; - -	return success; -} - -void LLWindowWin32::swapBuffers() -{ -	SwapBuffers(mhDC); -} - - -// -// LLSplashScreenImp -// -LLSplashScreenWin32::LLSplashScreenWin32() -:	mWindow(NULL) -{ -} - -LLSplashScreenWin32::~LLSplashScreenWin32() -{ -} - -void LLSplashScreenWin32::showImpl() -{ -	// This appears to work.  ??? -	HINSTANCE hinst = GetModuleHandle(NULL); - -	mWindow = CreateDialog(hinst,  -		TEXT("SPLASHSCREEN"),  -		NULL,	// no parent -		(DLGPROC) LLSplashScreenWin32::windowProc);  -	ShowWindow(mWindow, SW_SHOW); -} - - -void LLSplashScreenWin32::updateImpl(const std::string& mesg) -{ -	if (!mWindow) return; - -	WCHAR w_mesg[1024]; -	mbstowcs(w_mesg, mesg.c_str(), 1024); - -	SendDlgItemMessage(mWindow, -		666,		// HACK: text id -		WM_SETTEXT, -		FALSE, -		(LPARAM)w_mesg); -} - - -void LLSplashScreenWin32::hideImpl() -{ -	if (mWindow) -	{ -		DestroyWindow(mWindow); -		mWindow = NULL;  -	} -} - - -// static -LRESULT CALLBACK LLSplashScreenWin32::windowProc(HWND h_wnd, UINT u_msg, -											WPARAM w_param, LPARAM l_param) -{ -	// Just give it to windows -	return DefWindowProc(h_wnd, u_msg, w_param, l_param); -} - -// -// Helper Funcs -// - -S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type) -{ -	UINT uType; - -	switch(type) -	{ -	case OSMB_OK: -		uType = MB_OK; -		break; -	case OSMB_OKCANCEL: -		uType = MB_OKCANCEL; -		break; -	case OSMB_YESNO: -		uType = MB_YESNO; -		break; -	default: -		uType = MB_OK; -		break; -	} - -	// HACK! Doesn't properly handle wide strings! -	int retval_win = MessageBoxA(NULL, text.c_str(), caption.c_str(), uType); -	S32 retval; - -	switch(retval_win) -	{ -	case IDYES: -		retval = OSBTN_YES; -		break; -	case IDNO: -		retval = OSBTN_NO; -		break; -	case IDOK: -		retval = OSBTN_OK; -		break; -	case IDCANCEL: -		retval = OSBTN_CANCEL; -		break; -	default: -		retval = OSBTN_CANCEL; -		break; -	} - -	return retval; -} - - -void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url ) -{ -	bool found = false; -	S32 i; -	for (i = 0; i < gURLProtocolWhitelistCount; i++) -	{ -		if (escaped_url.find(gURLProtocolWhitelist[i]) == 0) -		{ -			found = true; -			break; -		} -	} - -	if (!found) -	{ -		LL_WARNS("Window") << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << LL_ENDL; -		return; -	} - -	LL_INFOS("Window") << "Opening URL " << escaped_url << LL_ENDL; - -	// replaced ShellExecute code with ShellExecuteEx since ShellExecute doesn't work -	// reliablly on Vista. - -	// this is madness.. no, this is.. -	LLWString url_wstring = utf8str_to_wstring( escaped_url ); -	llutf16string url_utf16 = wstring_to_utf16str( url_wstring ); - -	// let the OS decide what to use to open the URL -	SHELLEXECUTEINFO sei = { sizeof( sei ) }; -	sei.fMask = SEE_MASK_FLAG_DDEWAIT; -	sei.nShow = SW_SHOWNORMAL; -	sei.lpVerb = L"open"; -	sei.lpFile = url_utf16.c_str(); -	ShellExecuteEx( &sei ); - -	//// TODO: LEAVING OLD CODE HERE SO I DON'T BONE OTHER MERGES -	//// DELETE THIS ONCE THE MERGES ARE DONE - -	// Figure out the user's default web browser -	// HKEY_CLASSES_ROOT\http\shell\open\command -	/* -	std::string reg_path_str = gURLProtocolWhitelistHandler[i] + "\\shell\\open\\command"; -	WCHAR reg_path_wstr[256]; -	mbstowcs( reg_path_wstr, reg_path_str.c_str(), LL_ARRAY_SIZE(reg_path_wstr) ); - -	HKEY key; -	WCHAR browser_open_wstr[1024]; -	DWORD buffer_length = 1024; -	RegOpenKeyEx(HKEY_CLASSES_ROOT, reg_path_wstr, 0, KEY_QUERY_VALUE, &key); -	RegQueryValueEx(key, NULL, NULL, NULL, (LPBYTE)browser_open_wstr, &buffer_length); -	RegCloseKey(key); - -	// Convert to STL string -	LLWString browser_open_wstring = utf16str_to_wstring(browser_open_wstr); - -	if (browser_open_wstring.length() < 2) -	{ -		LL_WARNS("Window") << "Invalid browser executable in registry " << browser_open_wstring << LL_ENDL; -		return; -	} - -	// Extract the process that's supposed to be launched -	LLWString browser_executable; -	if (browser_open_wstring[0] == '"') -	{ -		// executable is quoted, find the matching quote -		size_t quote_pos = browser_open_wstring.find('"', 1); -		// copy out the string including both quotes -		browser_executable = browser_open_wstring.substr(0, quote_pos+1); -	} -	else -	{ -		// executable not quoted, find a space -		size_t space_pos = browser_open_wstring.find(' ', 1); -		browser_executable = browser_open_wstring.substr(0, space_pos); -	} - -	LL_DEBUGS("Window") << "Browser reg key: " << wstring_to_utf8str(browser_open_wstring) << LL_ENDL; -	LL_INFOS("Window") << "Browser executable: " << wstring_to_utf8str(browser_executable) << LL_ENDL; - -	// Convert URL to wide string for Windows API -	// Assume URL is UTF8, as can come from scripts -	LLWString url_wstring = utf8str_to_wstring(escaped_url); -	llutf16string url_utf16 = wstring_to_utf16str(url_wstring); - -	// Convert executable and path to wide string for Windows API -	llutf16string browser_exec_utf16 = wstring_to_utf16str(browser_executable); - -	// ShellExecute returns HINSTANCE for backwards compatiblity. -	// MS docs say to cast to int and compare to 32. -	HWND our_window = NULL; -	LPCWSTR directory_wstr = NULL; -	int retval = (int) ShellExecute(our_window, 	// Flawfinder: ignore -									L"open",  -									browser_exec_utf16.c_str(),  -									url_utf16.c_str(),  -									directory_wstr, -									SW_SHOWNORMAL); -	if (retval > 32) -	{ -		LL_DEBUGS("Window") << "load_url success with " << retval << LL_ENDL; -	} -	else -	{ -		LL_INFOS("Window") << "load_url failure with " << retval << LL_ENDL; -	} -	*/ -} - - -BOOL LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b ) -{ -	BOOL retval = FALSE; - -	static CHOOSECOLOR cc; -	static COLORREF crCustColors[16]; -	cc.lStructSize = sizeof(CHOOSECOLOR); -	cc.hwndOwner = mWindowHandle; -	cc.hInstance = NULL; -	cc.rgbResult = RGB ((*r * 255.f),(*g *255.f),(*b * 255.f)); -	//cc.rgbResult = RGB (0x80,0x80,0x80);  -	cc.lpCustColors = crCustColors; -	cc.Flags = CC_RGBINIT | CC_FULLOPEN; -	cc.lCustData = 0; -	cc.lpfnHook = NULL; -	cc.lpTemplateName = NULL; -  -	// This call is modal, so pause agent -	//send_agent_pause();	// this is in newview and we don't want to set up a dependency -	{ -		retval = ChooseColor(&cc); -	} -	//send_agent_resume();	// this is in newview and we don't want to set up a dependency - -	*b = ((F32)((cc.rgbResult >> 16) & 0xff)) / 255.f; - -	*g = ((F32)((cc.rgbResult >> 8) & 0xff)) / 255.f; -	 -	*r = ((F32)(cc.rgbResult & 0xff)) / 255.f; - -	return (retval); -} - -void *LLWindowWin32::getPlatformWindow() -{ -	return (void*)mWindowHandle; -} - -void LLWindowWin32::bringToFront() -{ -	BringWindowToTop(mWindowHandle); -} - -// set (OS) window focus back to the client -void LLWindowWin32::focusClient() -{ -	SetFocus ( mWindowHandle ); -} - -void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) -{ -	if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable()) -	{ -		return; -	} - -	if (preeditor != mPreeditor && !b) -	{ -		// This condition may occur with a call to -		// setEnabled(BOOL) from LLTextEditor or LLLineEditor -		// when the control is not focused. -		// We need to silently ignore the case so that -		// the language input status of the focused control -		// is not disturbed. -		return; -	} - -	// Take care of old and new preeditors. -	if (preeditor != mPreeditor || !b) -	{ -		if (sLanguageTextInputAllowed) -		{ -			interruptLanguageTextInput(); -		} -		mPreeditor = (b ? preeditor : NULL); -	} - -	sLanguageTextInputAllowed = b; - -	if ( sLanguageTextInputAllowed ) -	{ -		// Allowing: Restore the previous IME status, so that the user has a feeling that the previous  -		// text input continues naturally.  Be careful, however, the IME status is meaningful only during the user keeps  -		// using same Input Locale (aka Keyboard Layout). -		if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale) -		{ -			HIMC himc = LLWinImm::getContext(mWindowHandle); -			LLWinImm::setOpenStatus(himc, TRUE); -			LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode); -			LLWinImm::releaseContext(mWindowHandle, himc); -		} -	} -	else -	{ -		// Disallowing: Turn off the IME so that succeeding key events bypass IME and come to us directly. -		// However, do it after saving the current IME  status.  We need to restore the status when -		//   allowing language text input again. -		sWinInputLocale = GetKeyboardLayout(0); -		sWinIMEOpened = LLWinImm::isIME(sWinInputLocale); -		if (sWinIMEOpened) -		{ -			HIMC himc = LLWinImm::getContext(mWindowHandle); -			sWinIMEOpened = LLWinImm::getOpenStatus(himc); -			if (sWinIMEOpened) -			{ -				LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode); - -				// We need both ImmSetConversionStatus and ImmSetOpenStatus here to surely disable IME's  -				// keyboard hooking, because Some IME reacts only on the former and some other on the latter... -				LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode); -				LLWinImm::setOpenStatus(himc, FALSE); -			} -			LLWinImm::releaseContext(mWindowHandle, himc); - 		} -	} -} - -void LLWindowWin32::fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds,  -		CANDIDATEFORM *form) -{ -	LLCoordWindow caret_coord, top_left, bottom_right; -	convertCoords(caret, &caret_coord); -	convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left); -	convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right); - -	memset(form, 0, sizeof(CANDIDATEFORM)); -	form->dwStyle = CFS_EXCLUDE; -	form->ptCurrentPos.x = caret_coord.mX; -	form->ptCurrentPos.y = caret_coord.mY; -	form->rcArea.left   = top_left.mX; -	form->rcArea.top    = top_left.mY; -	form->rcArea.right  = bottom_right.mX; -	form->rcArea.bottom = bottom_right.mY; -} - - -// Put the IME window at the right place (near current text input).   Point coordinates should be the top of the current text line. -void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position ) -{ -	if (sLanguageTextInputAllowed && LLWinImm::isAvailable()) -	{ -		HIMC himc = LLWinImm::getContext(mWindowHandle); - -		LLCoordWindow win_pos; -		convertCoords( position, &win_pos ); - -		if ( win_pos.mX >= 0 && win_pos.mY >= 0 &&  -			(win_pos.mX != sWinIMEWindowPosition.mX) || (win_pos.mY != sWinIMEWindowPosition.mY) ) -		{ -			COMPOSITIONFORM ime_form; -			memset( &ime_form, 0, sizeof(ime_form) ); -			ime_form.dwStyle = CFS_POINT; -			ime_form.ptCurrentPos.x = win_pos.mX; -			ime_form.ptCurrentPos.y = win_pos.mY; - -			LLWinImm::setCompositionWindow( himc, &ime_form ); - -			sWinIMEWindowPosition.set( win_pos.mX, win_pos.mY ); -		} - -		LLWinImm::releaseContext(mWindowHandle, himc); -	} -} - - -void LLWindowWin32::fillCharPosition(const LLCoordGL& caret, const LLRect& bounds, const LLRect& control, -		IMECHARPOSITION *char_position) -{ -	LLCoordScreen caret_coord, top_left, bottom_right; -	convertCoords(caret, &caret_coord); -	convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left); -	convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right); - -	char_position->pt.x = caret_coord.mX; -	char_position->pt.y = top_left.mY;	// Windows wants the coordinate of upper left corner of a character... -	char_position->cLineHeight = bottom_right.mY - top_left.mY; -	char_position->rcDocument.left   = top_left.mX; -	char_position->rcDocument.top    = top_left.mY; -	char_position->rcDocument.right  = bottom_right.mX; -	char_position->rcDocument.bottom = bottom_right.mY; -} - -void LLWindowWin32::fillCompositionLogfont(LOGFONT *logfont) -{ -	// Our font is a list of FreeType recognized font files that may -	// not have a corresponding ones in Windows' fonts.  Hence, we -	// can't simply tell Windows which font we are using.  We will -	// notify a _standard_ font for a current input locale instead. -	// We use a hard-coded knowledge about the Windows' standard -	// configuration to do so... - -	memset(logfont, 0, sizeof(LOGFONT)); - -	const WORD lang_id = LOWORD(GetKeyboardLayout(0)); -	switch (PRIMARYLANGID(lang_id)) -	{ -	case LANG_CHINESE: -		// We need to identify one of two Chinese fonts. -		switch (SUBLANGID(lang_id)) -		{ -		case SUBLANG_CHINESE_SIMPLIFIED: -		case SUBLANG_CHINESE_SINGAPORE: -			logfont->lfCharSet = GB2312_CHARSET; -			lstrcpy(logfont->lfFaceName, TEXT("SimHei")); -			break; -		case SUBLANG_CHINESE_TRADITIONAL: -		case SUBLANG_CHINESE_HONGKONG: -		case SUBLANG_CHINESE_MACAU: -		default: -			logfont->lfCharSet = CHINESEBIG5_CHARSET; -			lstrcpy(logfont->lfFaceName, TEXT("MingLiU")); -			break;			 -		} -		break; -	case LANG_JAPANESE: -		logfont->lfCharSet = SHIFTJIS_CHARSET; -		lstrcpy(logfont->lfFaceName, TEXT("MS Gothic")); -		break;		 -	case LANG_KOREAN: -		logfont->lfCharSet = HANGUL_CHARSET; -		lstrcpy(logfont->lfFaceName, TEXT("Gulim")); -		break; -	default: -		logfont->lfCharSet = ANSI_CHARSET; -		lstrcpy(logfont->lfFaceName, TEXT("Tahoma")); -		break; -	} -							 -	logfont->lfHeight = mPreeditor->getPreeditFontSize(); -	logfont->lfWeight = FW_NORMAL; -}	 - -U32 LLWindowWin32::fillReconvertString(const LLWString &text, -	S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string) -{ -	const llutf16string text_utf16 = wstring_to_utf16str(text); -	const DWORD required_size = sizeof(RECONVERTSTRING) + (text_utf16.length() + 1) * sizeof(WCHAR); -	if (reconvert_string && reconvert_string->dwSize >= required_size) -	{ -		const DWORD focus_utf16_at = wstring_utf16_length(text, 0, focus); -		const DWORD focus_utf16_length = wstring_utf16_length(text, focus, focus_length); - -		reconvert_string->dwVersion = 0; -		reconvert_string->dwStrLen = text_utf16.length(); -		reconvert_string->dwStrOffset = sizeof(RECONVERTSTRING); -		reconvert_string->dwCompStrLen = focus_utf16_length; -		reconvert_string->dwCompStrOffset = focus_utf16_at * sizeof(WCHAR); -		reconvert_string->dwTargetStrLen = 0; -		reconvert_string->dwTargetStrOffset = focus_utf16_at * sizeof(WCHAR); - -		const LPWSTR text = (LPWSTR)((BYTE *)reconvert_string + sizeof(RECONVERTSTRING)); -		memcpy(text, text_utf16.c_str(), (text_utf16.length() + 1) * sizeof(WCHAR)); -	} -	return required_size; -} - -void LLWindowWin32::updateLanguageTextInputArea() -{ -	if (!mPreeditor || !LLWinImm::isAvailable()) -	{ -		return; -	} - -	LLCoordGL caret_coord; -	LLRect preedit_bounds; -	if (mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL)) -	{ -		mLanguageTextInputPointGL = caret_coord; -		mLanguageTextInputAreaGL = preedit_bounds; - -		CANDIDATEFORM candidate_form; -		fillCandidateForm(caret_coord, preedit_bounds, &candidate_form); - -		HIMC himc = LLWinImm::getContext(mWindowHandle); -		// Win32 document says there may be up to 4 candidate windows. -		// This magic number 4 appears only in the document, and -		// there are no constant/macro for the value... -		for (int i = 3; i >= 0; --i) -		{ -			candidate_form.dwIndex = i; -			LLWinImm::setCandidateWindow(himc, &candidate_form); -		} -		LLWinImm::releaseContext(mWindowHandle, himc); -	} -} - -void LLWindowWin32::interruptLanguageTextInput() -{ -	if (mPreeditor) -	{ -		if (LLWinImm::isAvailable()) -		{ -			HIMC himc = LLWinImm::getContext(mWindowHandle); -			LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); -			LLWinImm::releaseContext(mWindowHandle, himc); -		} - -		// Win32 document says there will be no composition string -		// after NI_COMPOSITIONSTR returns.  The following call to -		// resetPreedit should be a NOP unless IME goes mad... -		mPreeditor->resetPreedit(); -	} -} - -void LLWindowWin32::handleStartCompositionMessage() -{ -	// Let IME know the font to use in feedback UI. -	LOGFONT logfont; -	fillCompositionLogfont(&logfont); -	HIMC himc = LLWinImm::getContext(mWindowHandle); -	LLWinImm::setCompositionFont(himc, &logfont); -	LLWinImm::releaseContext(mWindowHandle, himc); -} - -// Handle WM_IME_COMPOSITION message. - -void LLWindowWin32::handleCompositionMessage(const U32 indexes) -{ -	BOOL needs_update = FALSE; -	LLWString result_string; -	LLWString preedit_string; -	S32 preedit_string_utf16_length = 0; -	LLPreeditor::segment_lengths_t preedit_segment_lengths; -	LLPreeditor::standouts_t preedit_standouts; - -	// Step I: Receive details of preedits from IME. - -	HIMC himc = LLWinImm::getContext(mWindowHandle); - -	if (indexes & GCS_RESULTSTR) -	{ -		LONG size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, NULL, 0); -		if (size >= 0) -		{ -			const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1]; -			size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, data, size); -			if (size > 0) -			{ -				result_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR))); -			} -			delete[] data; -			needs_update = TRUE; -		} -	} -	 -	if (indexes & GCS_COMPSTR) -	{ -		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, NULL, 0); -		if (size >= 0) -		{ -			const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1]; -			size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, data, size); -			if (size > 0) -			{ -				preedit_string_utf16_length = size / sizeof(WCHAR); -				preedit_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR))); -			} -			delete[] data; -			needs_update = TRUE; -		} -	} - -	if ((indexes & GCS_COMPCLAUSE) && preedit_string.length() > 0) -	{ -		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, NULL, 0); -		if (size > 0) -		{ -			const LPDWORD data = new DWORD[size / sizeof(DWORD)]; -			size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, data, size); -			if (size >= sizeof(DWORD) * 2 -				&& data[0] == 0 && data[size / sizeof(DWORD) - 1] == preedit_string_utf16_length) -			{ -				preedit_segment_lengths.resize(size / sizeof(DWORD) - 1); -				S32 offset = 0; -				for (U32 i = 0; i < preedit_segment_lengths.size(); i++) -				{ -					const S32 length = wstring_wstring_length_from_utf16_length(preedit_string, offset, data[i + 1] - data[i]); -					preedit_segment_lengths[i] = length; -					offset += length; -				} -			} -			delete[] data; -		} -	} - -	if ((indexes & GCS_COMPATTR) && preedit_segment_lengths.size() > 1) -	{ -		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, NULL, 0); -		if (size > 0) -		{ -			const LPBYTE data = new BYTE[size / sizeof(BYTE)]; -			size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, data, size); -			if (size == preedit_string_utf16_length) -			{ -				preedit_standouts.assign(preedit_segment_lengths.size(), FALSE); -				S32 offset = 0; -				for (U32 i = 0; i < preedit_segment_lengths.size(); i++) -				{ -					if (ATTR_TARGET_CONVERTED == data[offset] || ATTR_TARGET_NOTCONVERTED == data[offset]) -					{ -						preedit_standouts[i] = TRUE; -					} -					offset += wstring_utf16_length(preedit_string, offset, preedit_segment_lengths[i]); -				} -			} -			delete[] data; -		} -	} - -	S32 caret_position = preedit_string.length(); -	if (indexes & GCS_CURSORPOS) -	{ -		const S32 caret_position_utf16 = LLWinImm::getCompositionString(himc, GCS_CURSORPOS, NULL, 0); -		if (caret_position_utf16 >= 0 && caret_position <= preedit_string_utf16_length) -		{ -			caret_position = wstring_wstring_length_from_utf16_length(preedit_string, 0, caret_position_utf16); -		} -	} - -	if (indexes == 0) -	{ -		// I'm not sure this condition really happens, but -		// Windows SDK document says it is an indication -		// of "reset everything." -		needs_update = TRUE; -	} - -	LLWinImm::releaseContext(mWindowHandle, himc); - -	// Step II: Update the active preeditor. - -	if (needs_update) -	{ -		mPreeditor->resetPreedit(); - -		if (result_string.length() > 0) -		{ -			for (LLWString::const_iterator i = result_string.begin(); i != result_string.end(); i++) -			{ -				mPreeditor->handleUnicodeCharHere(*i); -			} -		} - -		if (preedit_string.length() == 0) - 		{ -			preedit_segment_lengths.clear(); -			preedit_standouts.clear(); -		} -		else -		{ -			if (preedit_segment_lengths.size() == 0) -			{ -				preedit_segment_lengths.assign(1, preedit_string.length()); -			} -			if (preedit_standouts.size() == 0) -			{ -				preedit_standouts.assign(preedit_segment_lengths.size(), FALSE); -			} -		} -		mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position); - -		// Some IME doesn't query char position after WM_IME_COMPOSITION, -		// so we need to update them actively. -		updateLanguageTextInputArea(); -	} -} - -// Given a text and a focus range, find_context finds and returns a -// surrounding context of the focused subtext.  A variable pointed -// to by offset receives the offset in llwchars of the beginning of -// the returned context string in the given wtext. - -static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_length, S32 *offset) -{ -	static const S32 CONTEXT_EXCESS = 30;	// This value is by experiences. - -	const S32 e = llmin((S32) wtext.length(), focus + focus_length + CONTEXT_EXCESS); -	S32 end = focus + focus_length; -	while (end < e && '\n' != wtext[end]) -	{ -		end++; -	} - -	const S32 s = llmax(0, focus - CONTEXT_EXCESS); -	S32 start = focus; -	while (start > s && '\n' != wtext[start - 1]) -	{ -		--start; -	} - -	*offset = start; -	return wtext.substr(start, end - start); -} - -// Handle WM_IME_REQUEST message. -// If it handled the message, returns TRUE.  Otherwise, FALSE. -// When it handled the message, the value to be returned from -// the Window Procedure is set to *result. - -BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result) -{ -	if ( mPreeditor ) -	{ -		switch (request) -		{ -			case IMR_CANDIDATEWINDOW:		// http://msdn2.microsoft.com/en-us/library/ms776080.aspx -			{ -				LLCoordGL caret_coord; -				LLRect preedit_bounds; -				mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL); -				 -				CANDIDATEFORM *const form = (CANDIDATEFORM *)param; -				DWORD const dwIndex = form->dwIndex; -				fillCandidateForm(caret_coord, preedit_bounds, form); -				form->dwIndex = dwIndex; - -				*result = 1; -				return TRUE; -			} -			case IMR_QUERYCHARPOSITION: -			{ -				IMECHARPOSITION *const char_position = (IMECHARPOSITION *)param; - -				// char_position->dwCharPos counts in number of -				// WCHARs, i.e., UTF-16 encoding units, so we can't simply pass the -				// number to getPreeditLocation.   - -				const LLWString & wtext = mPreeditor->getPreeditString(); -				S32 preedit, preedit_length; -				mPreeditor->getPreeditRange(&preedit, &preedit_length); -				LLCoordGL caret_coord; -				LLRect preedit_bounds, text_control; -				const S32 position = wstring_wstring_length_from_utf16_length(wtext, preedit, char_position->dwCharPos); - -				if (!mPreeditor->getPreeditLocation(position, &caret_coord, &preedit_bounds, &text_control)) -				{ -					LL_WARNS("Window") << "*** IMR_QUERYCHARPOSITON called but getPreeditLocation failed." << LL_ENDL; -					return FALSE; -				} -				fillCharPosition(caret_coord, preedit_bounds, text_control, char_position); - -				*result = 1; -				return TRUE; -			} -			case IMR_COMPOSITIONFONT: -			{ -				fillCompositionLogfont((LOGFONT *)param); - -				*result = 1; -				return TRUE; -			} -			case IMR_RECONVERTSTRING: -			{ -				mPreeditor->resetPreedit(); -				const LLWString & wtext = mPreeditor->getPreeditString(); -				S32 select, select_length; -				mPreeditor->getSelectionRange(&select, &select_length); - -				S32 context_offset; -				const LLWString context = find_context(wtext, select, select_length, &context_offset); - -				RECONVERTSTRING * const reconvert_string = (RECONVERTSTRING *)param; -				const U32 size = fillReconvertString(context, select - context_offset, select_length, reconvert_string); -				if (reconvert_string) -				{ -					if (select_length == 0) -					{ -						// Let the IME to decide the reconversion range, and -						// adjust the reconvert_string structure accordingly. -						HIMC himc = LLWinImm::getContext(mWindowHandle); -						const BOOL adjusted = LLWinImm::setCompositionString(himc, -									SCS_QUERYRECONVERTSTRING, reconvert_string, size, NULL, 0); -						LLWinImm::releaseContext(mWindowHandle, himc); -						if (adjusted) -						{ -							const llutf16string & text_utf16 = wstring_to_utf16str(context); -							const S32 new_preedit_start = reconvert_string->dwCompStrOffset / sizeof(WCHAR); -							const S32 new_preedit_end = new_preedit_start + reconvert_string->dwCompStrLen; -							select = utf16str_wstring_length(text_utf16, new_preedit_start); -							select_length = utf16str_wstring_length(text_utf16, new_preedit_end) - select; -							select += context_offset; -						} -					} -					mPreeditor->markAsPreedit(select, select_length); -				} - -				*result = size; -				return TRUE; -			} -			case IMR_CONFIRMRECONVERTSTRING: -			{ -				*result = FALSE; -				return TRUE; -			} -			case IMR_DOCUMENTFEED: -			{ -				const LLWString & wtext = mPreeditor->getPreeditString(); -				S32 preedit, preedit_length; -				mPreeditor->getPreeditRange(&preedit, &preedit_length); -				 -				S32 context_offset; -				LLWString context = find_context(wtext, preedit, preedit_length, &context_offset); -				preedit -= context_offset; -				if (preedit_length) -				{ -					// IMR_DOCUMENTFEED may be called when we have an active preedit. -					// We should pass the context string *excluding* the preedit string. -					// Otherwise, some IME are confused. -					context.erase(preedit, preedit_length); -				} -				 -				RECONVERTSTRING *reconvert_string = (RECONVERTSTRING *)param; -				*result = fillReconvertString(context, preedit, 0, reconvert_string); -				return TRUE; -			} -			default: -				return FALSE; -		} -	} - -	return FALSE; -} - -//static -std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList() -{ -	// Fonts previously in getFontListSans() have moved to fonts.xml. -	return std::vector<std::string>(); -} - - -#endif // LL_WINDOWS +/** 
 + * @file llwindowwin32.cpp
 + * @brief Platform-dependent implementation of llwindow
 + *
 + * $LicenseInfo:firstyear=2001&license=viewergpl$
 + * 
 + * Copyright (c) 2001-2009, Linden Research, Inc.
 + * 
 + * Second Life Viewer Source Code
 + * The source code in this file ("Source Code") is provided by Linden Lab
 + * to you under the terms of the GNU General Public License, version 2.0
 + * ("GPL"), unless you have obtained a separate licensing agreement
 + * ("Other License"), formally executed by you and Linden Lab.  Terms of
 + * the GPL can be found in doc/GPL-license.txt in this distribution, or
 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 + * 
 + * There are special exceptions to the terms and conditions of the GPL as
 + * it is applied to this Source Code. View the full text of the exception
 + * in the file doc/FLOSS-exception.txt in this software distribution, or
 + * online at
 + * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 + * 
 + * By copying, modifying or distributing this software, you acknowledge
 + * that you have read and understood your obligations described above,
 + * and agree to abide by those obligations.
 + * 
 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 + * COMPLETENESS OR PERFORMANCE.
 + * $/LicenseInfo$
 + */
 +
 +#include "linden_common.h"
 +
 +#if LL_WINDOWS && !LL_MESA_HEADLESS
 +
 +#include "llwindowwin32.h"
 +
 +// LLWindow library includes
 +#include "llkeyboardwin32.h"
 +#include "lldragdropwin32.h"
 +#include "llpreeditor.h"
 +#include "llwindowcallbacks.h"
 +
 +// Linden library includes
 +#include "llerror.h"
 +#include "llgl.h"
 +#include "llstring.h"
 +
 +// System includes
 +#include <commdlg.h>
 +#include <WinUser.h>
 +#include <mapi.h>
 +#include <process.h>	// for _spawn
 +#include <shellapi.h>
 +#include <fstream>
 +#include <Imm.h>
 +
 +// Require DirectInput version 8
 +#define DIRECTINPUT_VERSION 0x0800
 +
 +#include <dinput.h>
 +#include <Dbt.h.>
 +
 +#include "llmemtype.h"
 +// culled from winuser.h
 +#ifndef WM_MOUSEWHEEL /* Added to be compatible with later SDK's */
 +const S32	WM_MOUSEWHEEL = 0x020A;
 +#endif
 +#ifndef WHEEL_DELTA /* Added to be compatible with later SDK's */
 +const S32	WHEEL_DELTA = 120;     /* Value for rolling one detent */
 +#endif
 +const S32	MAX_MESSAGE_PER_UPDATE = 20;
 +const S32	BITS_PER_PIXEL = 32;
 +const S32	MAX_NUM_RESOLUTIONS = 32;
 +const F32	ICON_FLASH_TIME = 0.5f;
 +
 +extern BOOL gDebugWindowProc;
 +
 +LPWSTR gIconResource = IDI_APPLICATION;
 +
 +LLW32MsgCallback gAsyncMsgCallback = NULL;
 +
 +//
 +// LLWindowWin32
 +//
 +
 +void show_window_creation_error(const std::string& title)
 +{
 +	LL_WARNS("Window") << title << LL_ENDL;
 +}
 +
 +//static
 +BOOL LLWindowWin32::sIsClassRegistered = FALSE;
 +
 +BOOL	LLWindowWin32::sLanguageTextInputAllowed = TRUE;
 +BOOL	LLWindowWin32::sWinIMEOpened = FALSE;
 +HKL		LLWindowWin32::sWinInputLocale = 0;
 +DWORD	LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE;
 +DWORD	LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC;
 +LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1);
 +
 +// The following class LLWinImm delegates Windows IMM APIs.
 +// We need this because some language versions of Windows,
 +// e.g., US version of Windows XP, doesn't install IMM32.DLL
 +// as a default, and we can't link against imm32.lib statically.
 +// I believe DLL loading of this type is best suited to do
 +// in a static initialization of a class.  What I'm not sure is
 +// whether it follows the Linden Conding Standard... 
 +// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members
 +
 +class LLWinImm
 +{
 +public:
 +	static bool		isAvailable() { return sTheInstance.mHImmDll != NULL; }
 +
 +public:
 +	// Wrappers for IMM API.
 +	static BOOL		isIME(HKL hkl);															
 +	static HWND		getDefaultIMEWnd(HWND hwnd);
 +	static HIMC		getContext(HWND hwnd);													
 +	static BOOL		releaseContext(HWND hwnd, HIMC himc);
 +	static BOOL		getOpenStatus(HIMC himc);												
 +	static BOOL		setOpenStatus(HIMC himc, BOOL status);									
 +	static BOOL		getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);	
 +	static BOOL		setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);		
 +	static BOOL		getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					
 +	static BOOL		setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);					
 +	static LONG		getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length);
 +	static BOOL		setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength);
 +	static BOOL		setCompositionFont(HIMC himc, LPLOGFONTW logfont);
 +	static BOOL		setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form);
 +	static BOOL		notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value);
 +
 +private:
 +	LLWinImm();
 +	~LLWinImm();
 +
 +private:
 +	// Pointers to IMM API.
 +	BOOL	 	(WINAPI *mImmIsIME)(HKL);
 +	HWND		(WINAPI *mImmGetDefaultIMEWnd)(HWND);
 +	HIMC		(WINAPI *mImmGetContext)(HWND);
 +	BOOL		(WINAPI *mImmReleaseContext)(HWND, HIMC);
 +	BOOL		(WINAPI *mImmGetOpenStatus)(HIMC);
 +	BOOL		(WINAPI *mImmSetOpenStatus)(HIMC, BOOL);
 +	BOOL		(WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD);
 +	BOOL		(WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD);
 +	BOOL		(WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
 +	BOOL		(WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
 +	LONG		(WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD);
 +	BOOL		(WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD);
 +	BOOL		(WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW);
 +	BOOL		(WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM);
 +	BOOL		(WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD);
 +
 +private:
 +	HMODULE		mHImmDll;
 +	static LLWinImm sTheInstance;
 +};
 +
 +LLWinImm LLWinImm::sTheInstance;
 +
 +LLWinImm::LLWinImm() : mHImmDll(NULL)
 +{
 +	// Check system metrics 
 +	if ( !GetSystemMetrics( SM_DBCSENABLED ) )
 +		return;
 +	
 +
 +	mHImmDll = LoadLibraryA("Imm32");
 +	if (mHImmDll != NULL)
 +	{
 +		mImmIsIME               = (BOOL (WINAPI *)(HKL))                    GetProcAddress(mHImmDll, "ImmIsIME");
 +		mImmGetDefaultIMEWnd	= (HWND (WINAPI *)(HWND))					GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd");
 +		mImmGetContext          = (HIMC (WINAPI *)(HWND))                   GetProcAddress(mHImmDll, "ImmGetContext");
 +		mImmReleaseContext      = (BOOL (WINAPI *)(HWND, HIMC))             GetProcAddress(mHImmDll, "ImmReleaseContext");
 +		mImmGetOpenStatus       = (BOOL (WINAPI *)(HIMC))                   GetProcAddress(mHImmDll, "ImmGetOpenStatus");
 +		mImmSetOpenStatus       = (BOOL (WINAPI *)(HIMC, BOOL))             GetProcAddress(mHImmDll, "ImmSetOpenStatus");
 +		mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus");
 +		mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD))     GetProcAddress(mHImmDll, "ImmSetConversionStatus");
 +		mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmGetCompositionWindow");
 +		mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM))   GetProcAddress(mHImmDll, "ImmSetCompositionWindow");
 +		mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD))					GetProcAddress(mHImmDll, "ImmGetCompositionStringW");
 +		mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD))	GetProcAddress(mHImmDll, "ImmSetCompositionStringW");
 +		mImmSetCompositionFont  = (BOOL (WINAPI *)(HIMC, LPLOGFONTW))		GetProcAddress(mHImmDll, "ImmSetCompositionFontW");
 +		mImmSetCandidateWindow  = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM))  GetProcAddress(mHImmDll, "ImmSetCandidateWindow");
 +		mImmNotifyIME			= (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD))	GetProcAddress(mHImmDll, "ImmNotifyIME");
 +
 +		if (mImmIsIME == NULL ||
 +			mImmGetDefaultIMEWnd == NULL ||
 +			mImmGetContext == NULL ||
 +			mImmReleaseContext == NULL ||
 +			mImmGetOpenStatus == NULL ||
 +			mImmSetOpenStatus == NULL ||
 +			mImmGetConversionStatus == NULL ||
 +			mImmSetConversionStatus == NULL ||
 +			mImmGetCompostitionWindow == NULL ||
 +			mImmSetCompostitionWindow == NULL ||
 +			mImmGetCompositionString == NULL ||
 +			mImmSetCompositionString == NULL ||
 +			mImmSetCompositionFont == NULL ||
 +			mImmSetCandidateWindow == NULL ||
 +			mImmNotifyIME == NULL)
 +		{
 +			// If any of the above API entires are not found, we can't use IMM API.  
 +			// So, turn off the IMM support.  We should log some warning message in 
 +			// the case, since it is very unusual; these APIs are available from 
 +			// the beginning, and all versions of IMM32.DLL should have them all.  
 +			// Unfortunately, this code may be executed before initialization of 
 +			// the logging channel (llwarns), and we can't do it here...  Yes, this 
 +			// is one of disadvantages to use static constraction to DLL loading. 
 +			FreeLibrary(mHImmDll);
 +			mHImmDll = NULL;
 +
 +			// If we unload the library, make sure all the function pointers are cleared
 +			mImmIsIME = NULL;
 +			mImmGetDefaultIMEWnd = NULL;
 +			mImmGetContext = NULL;
 +			mImmReleaseContext = NULL;
 +			mImmGetOpenStatus = NULL;
 +			mImmSetOpenStatus = NULL;
 +			mImmGetConversionStatus = NULL;
 +			mImmSetConversionStatus = NULL;
 +			mImmGetCompostitionWindow = NULL;
 +			mImmSetCompostitionWindow = NULL;
 +			mImmGetCompositionString = NULL;
 +			mImmSetCompositionString = NULL;
 +			mImmSetCompositionFont = NULL;
 +			mImmSetCandidateWindow = NULL;
 +			mImmNotifyIME = NULL;
 +		}
 +	}
 +}
 +
 +
 +// static 
 +BOOL	LLWinImm::isIME(HKL hkl)															
 +{ 
 +	if ( sTheInstance.mImmIsIME )
 +		return sTheInstance.mImmIsIME(hkl); 
 +	return FALSE;
 +}
 +
 +// static 
 +HIMC		LLWinImm::getContext(HWND hwnd)
 +{
 +	if ( sTheInstance.mImmGetContext )
 +		return sTheInstance.mImmGetContext(hwnd); 
 +	return 0;
 +}
 +
 +//static 
 +BOOL		LLWinImm::releaseContext(HWND hwnd, HIMC himc)
 +{ 
 +	if ( sTheInstance.mImmIsIME )
 +		return sTheInstance.mImmReleaseContext(hwnd, himc); 
 +	return FALSE;
 +}
 +
 +// static 
 +BOOL		LLWinImm::getOpenStatus(HIMC himc)
 +{ 
 +	if ( sTheInstance.mImmGetOpenStatus )
 +		return sTheInstance.mImmGetOpenStatus(himc); 
 +	return FALSE;
 +}
 +
 +// static 
 +BOOL		LLWinImm::setOpenStatus(HIMC himc, BOOL status)									
 +{ 
 +	if ( sTheInstance.mImmSetOpenStatus )
 +		return sTheInstance.mImmSetOpenStatus(himc, status); 
 +	return FALSE;
 +}
 +
 +// static 
 +BOOL		LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)	
 +{ 
 +	if ( sTheInstance.mImmGetConversionStatus )
 +		return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); 
 +	return FALSE;
 +}
 +
 +// static 
 +BOOL		LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)		
 +{ 
 +	if ( sTheInstance.mImmSetConversionStatus )
 +		return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); 
 +	return FALSE;
 +}
 +
 +// static 
 +BOOL		LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					
 +{ 
 +	if ( sTheInstance.mImmGetCompostitionWindow )
 +		return sTheInstance.mImmGetCompostitionWindow(himc, form);	
 +	return FALSE;
 +}
 +
 +// static 
 +BOOL		LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)					
 +{ 
 +	if ( sTheInstance.mImmSetCompostitionWindow )
 +		return sTheInstance.mImmSetCompostitionWindow(himc, form);	
 +	return FALSE;
 +}
 +
 +
 +// static 
 +LONG		LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length)					
 +{ 
 +	if ( sTheInstance.mImmGetCompositionString )
 +		return sTheInstance.mImmGetCompositionString(himc, index, data, length);	
 +	return FALSE;
 +}
 +
 +
 +// static 
 +BOOL		LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)					
 +{ 
 +	if ( sTheInstance.mImmSetCompositionString )
 +		return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);	
 +	return FALSE;
 +}
 +
 +// static 
 +BOOL		LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)					
 +{ 
 +	if ( sTheInstance.mImmSetCompositionFont )
 +		return sTheInstance.mImmSetCompositionFont(himc, pFont);	
 +	return FALSE;
 +}
 +
 +// static 
 +BOOL		LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)					
 +{ 
 +	if ( sTheInstance.mImmSetCandidateWindow )
 +		return sTheInstance.mImmSetCandidateWindow(himc, form);	
 +	return FALSE;
 +}
 +
 +// static 
 +BOOL		LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)					
 +{ 
 +	if ( sTheInstance.mImmNotifyIME )
 +		return sTheInstance.mImmNotifyIME(himc, action, index, value);	
 +	return FALSE;
 +}
 +
 +
 +
 +
 +// ----------------------------------------------------------------------------------------
 +LLWinImm::~LLWinImm()
 +{
 +	if (mHImmDll != NULL)
 +	{
 +		FreeLibrary(mHImmDll);
 +		mHImmDll = NULL;
 +	}
 +}
 +
 +
 +LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
 +							 const std::string& title, const std::string& 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,
 +							 U32 fsaa_samples)
 +	: LLWindow(callbacks, fullscreen, flags)
 +{
 +	mFSAASamples = fsaa_samples;
 +	mIconResource = gIconResource;
 +	mOverrideAspectRatio = 0.f;
 +	mNativeAspectRatio = 0.f;
 +	mMousePositionModified = FALSE;
 +	mInputProcessingPaused = FALSE;
 +	mPreeditor = NULL;
 +	mhDC = NULL;
 +	mhRC = NULL;
 +
 +	// Initialize the keyboard
 +	gKeyboard = new LLKeyboardWin32();
 +	gKeyboard->setCallbacks(callbacks);
 +
 +	// Initialize the Drag and Drop functionality
 +	mDragDrop = new LLDragDropWin32;
 +
 +	// Initialize (boot strap) the Language text input management,
 +	// based on the system's (user's) default settings.
 +	allowLanguageTextInput(mPreeditor, FALSE);
 +
 +	WNDCLASS		wc;
 +	RECT			window_rect;
 +
 +	// Set the window title
 +	if (title.empty())
 +	{
 +		mWindowTitle = new WCHAR[50];
 +		wsprintf(mWindowTitle, L"OpenGL Window");
 +	}
 +	else
 +	{
 +		mWindowTitle = new WCHAR[256]; // Assume title length < 255 chars.
 +		mbstowcs(mWindowTitle, title.c_str(), 255);
 +		mWindowTitle[255] = 0;
 +	}
 +
 +	// Set the window class name
 +	if (name.empty())
 +	{
 +		mWindowClassName = new WCHAR[50];
 +		wsprintf(mWindowClassName, L"OpenGL Window");
 +	}
 +	else
 +	{
 +		mWindowClassName = new WCHAR[256]; // Assume title length < 255 chars.
 +		mbstowcs(mWindowClassName, name.c_str(), 255);
 +		mWindowClassName[255] = 0;
 +	}
 +
 +
 +	// We're not clipping yet
 +	SetRect( &mOldMouseClip, 0, 0, 0, 0 );
 +
 +	// Make an instance of our window then define the window class
 +	mhInstance = GetModuleHandle(NULL);
 +	mWndProc = NULL;
 +
 +	mSwapMethod = SWAP_METHOD_UNDEFINED;
 +
 +	// No WPARAM yet.
 +	mLastSizeWParam = 0;
 +
 +	// Windows GDI rects don't include rightmost pixel
 +	window_rect.left = (long) 0;
 +	window_rect.right = (long) width;
 +	window_rect.top = (long) 0;
 +	window_rect.bottom = (long) height;
 +
 +	// Grab screen size to sanitize the window
 +	S32 window_border_y = GetSystemMetrics(SM_CYBORDER);
 +	S32 virtual_screen_x = GetSystemMetrics(SM_XVIRTUALSCREEN); 
 +	S32 virtual_screen_y = GetSystemMetrics(SM_YVIRTUALSCREEN); 
 +	S32 virtual_screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
 +	S32 virtual_screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
 +
 +	if (x < virtual_screen_x) x = virtual_screen_x;
 +	if (y < virtual_screen_y - window_border_y) y = virtual_screen_y - window_border_y;
 +
 +	if (x + width > virtual_screen_x + virtual_screen_width) x = virtual_screen_x + virtual_screen_width - width;
 +	if (y + height > virtual_screen_y + virtual_screen_height) y = virtual_screen_y + virtual_screen_height - height;
 +
 +	if (!sIsClassRegistered)
 +	{
 +		// Force redraw when resized and create a private device context
 +
 +		// Makes double click messages.
 +		wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
 +
 +		// Set message handler function
 +		wc.lpfnWndProc = (WNDPROC) mainWindowProc;
 +
 +		// unused
 +		wc.cbClsExtra = 0;
 +		wc.cbWndExtra = 0;
 +
 +		wc.hInstance = mhInstance;
 +		wc.hIcon = LoadIcon(mhInstance, mIconResource);
 +
 +		// We will set the cursor ourselves
 +		wc.hCursor = NULL;
 +
 +		// background color is not used
 +		if (clearBg)
 +		{
 +			wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
 +		}
 +		else
 +		{
 +			wc.hbrBackground = (HBRUSH) NULL;
 +		}
 +
 +		// we don't use windows menus
 +		wc.lpszMenuName = NULL;
 +
 +		wc.lpszClassName = mWindowClassName;
 +
 +		if (!RegisterClass(&wc))
 +		{
 +			OSMessageBox(mCallbacks->translateString("MBRegClassFailed"), 
 +				mCallbacks->translateString("MBError"), OSMB_OK);
 +			return;
 +		}
 +		sIsClassRegistered = TRUE;
 +	}
 +
 +	//-----------------------------------------------------------------------
 +	// Get the current refresh rate
 +	//-----------------------------------------------------------------------
 +
 +	DEVMODE dev_mode;
 +	DWORD current_refresh;
 +	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
 +	{
 +		current_refresh = dev_mode.dmDisplayFrequency;
 +		mNativeAspectRatio = ((F32)dev_mode.dmPelsWidth) / ((F32)dev_mode.dmPelsHeight);
 +	}
 +	else
 +	{
 +		current_refresh = 60;
 +	}
 +
 +	//-----------------------------------------------------------------------
 +	// Drop resolution and go fullscreen
 +	// use a display mode with our desired size and depth, with a refresh
 +	// rate as close at possible to the users' default
 +	//-----------------------------------------------------------------------
 +	if (mFullscreen)
 +	{
 +		BOOL success = FALSE;
 +		DWORD closest_refresh = 0;
 +
 +		for (S32 mode_num = 0;; mode_num++)
 +		{
 +			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
 +			{
 +				break;
 +			}
 +
 +			if (dev_mode.dmPelsWidth == width &&
 +				dev_mode.dmPelsHeight == height &&
 +				dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
 +			{
 +				success = TRUE;
 +				if ((dev_mode.dmDisplayFrequency - current_refresh)
 +					< (closest_refresh - current_refresh))
 +				{
 +					closest_refresh = dev_mode.dmDisplayFrequency;
 +				}
 +			}
 +		}
 +
 +		if (closest_refresh == 0)
 +		{
 +			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
 +			success = FALSE;
 +		}
 +
 +		// If we found a good resolution, use it.
 +		if (success)
 +		{
 +			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
 +		}
 +
 +		// Keep a copy of the actual current device mode in case we minimize 
 +		// and change the screen resolution.   JC
 +		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
 +
 +		// If it failed, we don't want to run fullscreen
 +		if (success)
 +		{
 +			mFullscreen = TRUE;
 +			mFullscreenWidth   = dev_mode.dmPelsWidth;
 +			mFullscreenHeight  = dev_mode.dmPelsHeight;
 +			mFullscreenBits    = dev_mode.dmBitsPerPel;
 +			mFullscreenRefresh = dev_mode.dmDisplayFrequency;
 +
 +			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
 +				<< "x"   << dev_mode.dmPelsHeight
 +				<< "x"   << dev_mode.dmBitsPerPel
 +				<< " @ " << dev_mode.dmDisplayFrequency
 +				<< LL_ENDL;
 +		}
 +		else
 +		{
 +			mFullscreen = FALSE;
 +			mFullscreenWidth   = -1;
 +			mFullscreenHeight  = -1;
 +			mFullscreenBits    = -1;
 +			mFullscreenRefresh = -1;
 +
 +			std::map<std::string,std::string> args;
 +			args["[WIDTH]"] = llformat("%d", width);
 +			args["[HEIGHT]"] = llformat ("%d", height);
 +			OSMessageBox(mCallbacks->translateString("MBFullScreenErr", args),
 +				mCallbacks->translateString("MBError"), OSMB_OK);
 +		}
 +	}
 +
 +	// TODO: add this after resolving _WIN32_WINNT issue
 +	//	if (!fullscreen)
 +	//	{
 +	//		TRACKMOUSEEVENT track_mouse_event;
 +	//		track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT );
 +	//		track_mouse_event.dwFlags = TME_LEAVE;
 +	//		track_mouse_event.hwndTrack = mWindowHandle;
 +	//		track_mouse_event.dwHoverTime = HOVER_DEFAULT;
 +	//		TrackMouseEvent( &track_mouse_event ); 
 +	//	}
 +
 +
 +	//-----------------------------------------------------------------------
 +	// Create GL drawing context
 +	//-----------------------------------------------------------------------
 +	LLCoordScreen windowPos(x,y);
 +	LLCoordScreen windowSize(window_rect.right - window_rect.left,
 +							 window_rect.bottom - window_rect.top);
 +	if (!switchContext(mFullscreen, windowSize, TRUE, &windowPos))
 +	{
 +		return;
 +	}
 +	
 +	//start with arrow cursor
 +	initCursors();
 +	setCursor( UI_CURSOR_ARROW );
 +
 +	// Initialize (boot strap) the Language text input management,
 +	// based on the system's (or user's) default settings.
 +	allowLanguageTextInput(NULL, FALSE);
 +}
 +
 +
 +LLWindowWin32::~LLWindowWin32()
 +{
 +	delete mDragDrop;
 +
 +	delete [] mWindowTitle;
 +	mWindowTitle = NULL;
 +
 +	delete [] mSupportedResolutions;
 +	mSupportedResolutions = NULL;
 +
 +	delete mWindowClassName;
 +	mWindowClassName = NULL;
 +}
 +
 +void LLWindowWin32::show()
 +{
 +	ShowWindow(mWindowHandle, SW_SHOW);
 +	SetForegroundWindow(mWindowHandle);
 +	SetFocus(mWindowHandle);
 +}
 +
 +void LLWindowWin32::hide()
 +{
 +	setMouseClipping(FALSE);
 +	ShowWindow(mWindowHandle, SW_HIDE);
 +}
 +
 +void LLWindowWin32::minimize()
 +{
 +	setMouseClipping(FALSE);
 +	showCursor();
 +	ShowWindow(mWindowHandle, SW_MINIMIZE);
 +}
 +
 +
 +void LLWindowWin32::restore()
 +{
 +	ShowWindow(mWindowHandle, SW_RESTORE);
 +	SetForegroundWindow(mWindowHandle);
 +	SetFocus(mWindowHandle);
 +}
 +
 +
 +// close() destroys all OS-specific code associated with a window.
 +// Usually called from LLWindowManager::destroyWindow()
 +void LLWindowWin32::close()
 +{
 +	LL_DEBUGS("Window") << "Closing LLWindowWin32" << LL_ENDL;
 +	// Is window is already closed?
 +	if (!mWindowHandle)
 +	{
 +		return;
 +	}
 +
 +	mDragDrop->reset();
 +
 +	// Make sure cursor is visible and we haven't mangled the clipping state.
 +	setMouseClipping(FALSE);
 +	showCursor();
 +
 +	// Go back to screen mode written in the registry.
 +	if (mFullscreen)
 +	{
 +		resetDisplayResolution();
 +	}
 +
 +	// Clean up remaining GL state
 +	LL_DEBUGS("Window") << "Shutting down GL" << LL_ENDL;
 +	gGLManager.shutdownGL();
 +
 +	LL_DEBUGS("Window") << "Releasing Context" << LL_ENDL;
 +	if (mhRC)
 +	{
 +		if (!wglMakeCurrent(NULL, NULL))
 +		{
 +			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL;
 +		}
 +
 +		if (!wglDeleteContext(mhRC))
 +		{
 +			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL;
 +		}
 +
 +		mhRC = NULL;
 +	}
 +
 +	// Restore gamma to the system values.
 +	restoreGamma();
 +
 +	if (mhDC && !ReleaseDC(mWindowHandle, mhDC))
 +	{
 +		LL_WARNS("Window") << "Release of ghDC failed" << LL_ENDL;
 +		mhDC = NULL;
 +	}
 +
 +	LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
 +	
 +	// Don't process events in our mainWindowProc any longer.
 +	SetWindowLong(mWindowHandle, GWL_USERDATA, NULL);
 +
 +	// Make sure we don't leave a blank toolbar button.
 +	ShowWindow(mWindowHandle, SW_HIDE);
 +
 +	// This causes WM_DESTROY to be sent *immediately*
 +	if (!DestroyWindow(mWindowHandle))
 +	{
 +		OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"),
 +			mCallbacks->translateString("MBShutdownErr"),
 +			OSMB_OK);
 +	}
 +
 +	mWindowHandle = NULL;
 +}
 +
 +BOOL LLWindowWin32::isValid()
 +{
 +	return (mWindowHandle != NULL);
 +}
 +
 +BOOL LLWindowWin32::getVisible()
 +{
 +	return (mWindowHandle && IsWindowVisible(mWindowHandle));
 +}
 +
 +BOOL LLWindowWin32::getMinimized()
 +{
 +	return (mWindowHandle && IsIconic(mWindowHandle));
 +}
 +
 +BOOL LLWindowWin32::getMaximized()
 +{
 +	return (mWindowHandle && IsZoomed(mWindowHandle));
 +}
 +
 +BOOL LLWindowWin32::maximize()
 +{
 +	BOOL success = FALSE;
 +	if (!mWindowHandle) return success;
 +
 +	WINDOWPLACEMENT placement;
 +	placement.length = sizeof(WINDOWPLACEMENT);
 +
 +	success = GetWindowPlacement(mWindowHandle, &placement);
 +	if (!success) return success;
 +
 +	placement.showCmd = SW_MAXIMIZE;
 +
 +	success = SetWindowPlacement(mWindowHandle, &placement);
 +	return success;
 +}
 +
 +BOOL LLWindowWin32::getFullscreen()
 +{
 +	return mFullscreen;
 +}
 +
 +BOOL LLWindowWin32::getPosition(LLCoordScreen *position)
 +{
 +	RECT window_rect;
 +
 +	if (!mWindowHandle ||
 +		!GetWindowRect(mWindowHandle, &window_rect) ||
 +		NULL == position)
 +	{
 +		return FALSE;
 +	}
 +
 +	position->mX = window_rect.left;
 +	position->mY = window_rect.top;
 +	return TRUE;
 +}
 +
 +BOOL LLWindowWin32::getSize(LLCoordScreen *size)
 +{
 +	RECT window_rect;
 +
 +	if (!mWindowHandle ||
 +		!GetWindowRect(mWindowHandle, &window_rect) ||
 +		NULL == size)
 +	{
 +		return FALSE;
 +	}
 +
 +	size->mX = window_rect.right - window_rect.left;
 +	size->mY = window_rect.bottom - window_rect.top;
 +	return TRUE;
 +}
 +
 +BOOL LLWindowWin32::getSize(LLCoordWindow *size)
 +{
 +	RECT client_rect;
 +
 +	if (!mWindowHandle ||
 +		!GetClientRect(mWindowHandle, &client_rect) ||
 +		NULL == size)
 +	{
 +		return FALSE;
 +	}
 +
 +	size->mX = client_rect.right - client_rect.left;
 +	size->mY = client_rect.bottom - client_rect.top;
 +	return TRUE;
 +}
 +
 +BOOL LLWindowWin32::setPosition(const LLCoordScreen position)
 +{
 +	LLCoordScreen size;
 +
 +	if (!mWindowHandle)
 +	{
 +		return FALSE;
 +	}
 +	getSize(&size);
 +	moveWindow(position, size);
 +	return TRUE;
 +}
 +
 +BOOL LLWindowWin32::setSize(const LLCoordScreen size)
 +{
 +	LLCoordScreen position;
 +
 +	getPosition(&position);
 +	if (!mWindowHandle)
 +	{
 +		return FALSE;
 +	}
 +
 +	moveWindow(position, size);
 +	return TRUE;
 +}
 +
 +// changing fullscreen resolution
 +BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp)
 +{
 +	GLuint	pixel_format;
 +	DEVMODE dev_mode;
 +	DWORD	current_refresh;
 +	DWORD	dw_ex_style;
 +	DWORD	dw_style;
 +	RECT	window_rect;
 +	S32 width = size.mX;
 +	S32 height = size.mY;
 +	BOOL auto_show = FALSE;
 +
 +	if (mhRC)
 +	{
 +		auto_show = TRUE;
 +		resetDisplayResolution();
 +	}
 +
 +	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
 +	{
 +		current_refresh = dev_mode.dmDisplayFrequency;
 +	}
 +	else
 +	{
 +		current_refresh = 60;
 +	}
 +
 +	gGLManager.shutdownGL();
 +	//destroy gl context
 +	if (mhRC)
 +	{
 +		if (!wglMakeCurrent(NULL, NULL))
 +		{
 +			LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL;
 +		}
 +
 +		if (!wglDeleteContext(mhRC))
 +		{
 +			LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL;
 +		}
 +
 +		mhRC = NULL;
 +	}
 +
 +	if (fullscreen)
 +	{
 +		mFullscreen = TRUE;
 +		BOOL success = FALSE;
 +		DWORD closest_refresh = 0;
 +
 +		for (S32 mode_num = 0;; mode_num++)
 +		{
 +			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
 +			{
 +				break;
 +			}
 +
 +			if (dev_mode.dmPelsWidth == width &&
 +				dev_mode.dmPelsHeight == height &&
 +				dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
 +			{
 +				success = TRUE;
 +				if ((dev_mode.dmDisplayFrequency - current_refresh)
 +					< (closest_refresh - current_refresh))
 +				{
 +					closest_refresh = dev_mode.dmDisplayFrequency;
 +				}
 +			}
 +		}
 +
 +		if (closest_refresh == 0)
 +		{
 +			LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
 +			return FALSE;
 +		}
 +
 +		// If we found a good resolution, use it.
 +		if (success)
 +		{
 +			success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
 +		}
 +
 +		// Keep a copy of the actual current device mode in case we minimize 
 +		// and change the screen resolution.   JC
 +		EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
 +
 +		if (success)
 +		{
 +			mFullscreen = TRUE;
 +			mFullscreenWidth   = dev_mode.dmPelsWidth;
 +			mFullscreenHeight  = dev_mode.dmPelsHeight;
 +			mFullscreenBits    = dev_mode.dmBitsPerPel;
 +			mFullscreenRefresh = dev_mode.dmDisplayFrequency;
 +
 +			LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
 +				<< "x"   << dev_mode.dmPelsHeight
 +				<< "x"   << dev_mode.dmBitsPerPel
 +				<< " @ " << dev_mode.dmDisplayFrequency
 +				<< LL_ENDL;
 +
 +			window_rect.left = (long) 0;
 +			window_rect.right = (long) width;			// Windows GDI rects don't include rightmost pixel
 +			window_rect.top = (long) 0;
 +			window_rect.bottom = (long) height;
 +			dw_ex_style = WS_EX_APPWINDOW;
 +			dw_style = WS_POPUP;
 +
 +			// Move window borders out not to cover window contents
 +			AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style);
 +		}
 +		// If it failed, we don't want to run fullscreen
 +		else
 +		{
 +			mFullscreen = FALSE;
 +			mFullscreenWidth   = -1;
 +			mFullscreenHeight  = -1;
 +			mFullscreenBits    = -1;
 +			mFullscreenRefresh = -1;
 +
 +			LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL;
 +			return FALSE;
 +		}
 +	}
 +	else
 +	{
 +		mFullscreen = FALSE;
 +		window_rect.left = (long) (posp ? posp->mX : 0);
 +		window_rect.right = (long) width + window_rect.left;			// Windows GDI rects don't include rightmost pixel
 +		window_rect.top = (long) (posp ? posp->mY : 0);
 +		window_rect.bottom = (long) height + window_rect.top;
 +		// Window with an edge
 +		dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
 +		dw_style = WS_OVERLAPPEDWINDOW;
 +	}
 +
 +	// don't post quit messages when destroying old windows
 +	mPostQuit = FALSE;
 +
 +	// create window
 +	DestroyWindow(mWindowHandle);
 +	mWindowHandle = CreateWindowEx(dw_ex_style,
 +		mWindowClassName,
 +		mWindowTitle,
 +		WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
 +		window_rect.left,								// x pos
 +		window_rect.top,								// y pos
 +		window_rect.right - window_rect.left,			// width
 +		window_rect.bottom - window_rect.top,			// height
 +		NULL,
 +		NULL,
 +		mhInstance,
 +		NULL);
 +
 +	//-----------------------------------------------------------------------
 +	// Create GL drawing context
 +	//-----------------------------------------------------------------------
 +	static PIXELFORMATDESCRIPTOR pfd =
 +	{
 +		sizeof(PIXELFORMATDESCRIPTOR), 
 +			1,
 +			PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 
 +			PFD_TYPE_RGBA,
 +			BITS_PER_PIXEL,
 +			0, 0, 0, 0, 0, 0,	// RGB bits and shift, unused
 +			8,					// alpha bits
 +			0,					// alpha shift
 +			0,					// accum bits
 +			0, 0, 0, 0,			// accum RGBA
 +			24,					// depth bits
 +			8,					// stencil bits, avi added for stencil test
 +			0,
 +			PFD_MAIN_PLANE,
 +			0,
 +			0, 0, 0
 +	};
 +
 +	if (!(mhDC = GetDC(mWindowHandle)))
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBDevContextErr"),
 +			mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
 +			mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	// Verify what pixel format we actually received.
 +	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
 +		&pfd))
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"),
 +			mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (pfd.cColorBits < 32)
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"),
 +			mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (pfd.cAlphaBits < 8)
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBAlpha"),
 +			mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (!SetPixelFormat(mhDC, pixel_format, &pfd))
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
 +			mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (!(mhRC = wglCreateContext(mhDC)))
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBGLContextErr"),
 +			mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (!wglMakeCurrent(mhDC, mhRC))
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"),
 +			mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	gGLManager.initWGL();
 +
 +	if (wglChoosePixelFormatARB)
 +	{
 +		// OK, at this point, use the ARB wglChoosePixelFormatsARB function to see if we
 +		// can get exactly what we want.
 +		GLint attrib_list[256];
 +		S32 cur_attrib = 0;
 +
 +		attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB;
 +		attrib_list[cur_attrib++] = 24;
 +
 +		attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB;
 +		attrib_list[cur_attrib++] = 8;
 +
 +		attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB;
 +		attrib_list[cur_attrib++] = GL_TRUE;
 +
 +		attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB;
 +		attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB;
 +
 +		attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB;
 +		attrib_list[cur_attrib++] = GL_TRUE;
 +
 +		attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB;
 +		attrib_list[cur_attrib++] = GL_TRUE;
 +
 +		attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
 +		attrib_list[cur_attrib++] = 24;
 +
 +		attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
 +		attrib_list[cur_attrib++] = 8;
 +
 +		U32 end_attrib = 0;
 +		if (mFSAASamples > 0)
 +		{
 +			end_attrib = cur_attrib;
 +			attrib_list[cur_attrib++] = WGL_SAMPLE_BUFFERS_ARB;
 +			attrib_list[cur_attrib++] = GL_TRUE;
 +
 +			attrib_list[cur_attrib++] = WGL_SAMPLES_ARB;
 +			attrib_list[cur_attrib++] = mFSAASamples;
 +		}
 +
 +		// End the list
 +		attrib_list[cur_attrib++] = 0;
 +
 +		GLint pixel_formats[256];
 +		U32 num_formats = 0;
 +
 +		// First we try and get a 32 bit depth pixel format
 +		BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
 +		if (!result)
 +		{
 +			close();
 +			show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit");
 +			return FALSE;
 +		}
 +
 +		if (!num_formats)
 +		{
 +			if (end_attrib > 0)
 +			{
 +				LL_INFOS("Window") << "No valid pixel format for " << mFSAASamples << "x anti-aliasing." << LL_ENDL;
 +				attrib_list[end_attrib] = 0;
 +
 +				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
 +				if (!result)
 +				{
 +					close();
 +					show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit no AA");
 +					return FALSE;
 +				}
 +			}
 +
 +			if (!num_formats)
 +			{
 +				LL_INFOS("Window") << "No 32 bit z-buffer, trying 24 bits instead" << LL_ENDL;
 +				// Try 24-bit format
 +				attrib_list[1] = 24;
 +				BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
 +				if (!result)
 +				{
 +					close();
 +					show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
 +					return FALSE;
 +				}
 +
 +				if (!num_formats)
 +				{
 +					LL_WARNS("Window") << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << LL_ENDL;
 +					attrib_list[1] = 16;
 +					BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
 +					if (!result || !num_formats)
 +					{
 +						close();
 +						show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
 +						return FALSE;
 +					}
 +				}
 +			}
 +
 +			LL_INFOS("Window") << "Choosing pixel formats: " << num_formats << " pixel formats returned" << LL_ENDL;
 +		}
 +
 +		
 +
 +		S32 swap_method = 0;
 +		S32 cur_format = num_formats-1;
 +		GLint swap_query = WGL_SWAP_METHOD_ARB;
 +
 +		BOOL found_format = FALSE;
 +
 +		while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
 +		{
 +			if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0)
 +			{
 +				found_format = TRUE;
 +			}
 +			else
 +			{
 +				--cur_format;
 +			}
 +		}
 +		
 +		pixel_format = pixel_formats[cur_format];
 +		
 +		if (mhDC != 0)											// Does The Window Have A Device Context?
 +		{
 +			wglMakeCurrent(mhDC, 0);							// Set The Current Active Rendering Context To Zero
 +			if (mhRC != 0)										// Does The Window Have A Rendering Context?
 +			{
 +				wglDeleteContext (mhRC);							// Release The Rendering Context
 +				mhRC = 0;										// Zero The Rendering Context
 +
 +			}
 +			ReleaseDC (mWindowHandle, mhDC);						// Release The Device Context
 +			mhDC = 0;											// Zero The Device Context
 +		}
 +		DestroyWindow (mWindowHandle);									// Destroy The Window
 +		
 +
 +		mWindowHandle = CreateWindowEx(dw_ex_style,
 +			mWindowClassName,
 +			mWindowTitle,
 +			WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
 +			window_rect.left,								// x pos
 +			window_rect.top,								// y pos
 +			window_rect.right - window_rect.left,			// width
 +			window_rect.bottom - window_rect.top,			// height
 +			NULL,
 +			NULL,
 +			mhInstance,
 +			NULL);
 +
 +		if (!(mhDC = GetDC(mWindowHandle)))
 +		{
 +			close();
 +			OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 +			return FALSE;
 +		}
 +
 +		if (!SetPixelFormat(mhDC, pixel_format, &pfd))
 +		{
 +			close();
 +			OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
 +				mCallbacks->translateString("MBError"), OSMB_OK);
 +			return FALSE;
 +		}
 +
 +		if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
 +		{
 +			switch (swap_method)
 +			{
 +			case WGL_SWAP_EXCHANGE_ARB:
 +				mSwapMethod = SWAP_METHOD_EXCHANGE;
 +				LL_DEBUGS("Window") << "Swap Method: Exchange" << LL_ENDL;
 +				break;
 +			case WGL_SWAP_COPY_ARB:
 +				mSwapMethod = SWAP_METHOD_COPY;
 +				LL_DEBUGS("Window") << "Swap Method: Copy" << LL_ENDL;
 +				break;
 +			case WGL_SWAP_UNDEFINED_ARB:
 +				mSwapMethod = SWAP_METHOD_UNDEFINED;
 +				LL_DEBUGS("Window") << "Swap Method: Undefined" << LL_ENDL;
 +				break;
 +			default:
 +				mSwapMethod = SWAP_METHOD_UNDEFINED;
 +				LL_DEBUGS("Window") << "Swap Method: Unknown" << LL_ENDL;
 +				break;
 +			}
 +		}		
 +	}
 +	else
 +	{
 +		LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL;
 +	}
 +
 +	// Verify what pixel format we actually received.
 +	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
 +		&pfd))
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	LL_INFOS("Window") << "GL buffer: Color Bits " << S32(pfd.cColorBits) 
 +		<< " Alpha Bits " << S32(pfd.cAlphaBits)
 +		<< " Depth Bits " << S32(pfd.cDepthBits) 
 +		<< LL_ENDL;
 +
 +	// make sure we have 32 bits per pixel
 +	if (pfd.cColorBits < 32 || GetDeviceCaps(mhDC, BITSPIXEL) < 32)
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (pfd.cAlphaBits < 8)
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (!(mhRC = wglCreateContext(mhDC)))
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (!wglMakeCurrent(mhDC, mhRC))
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	if (!gGLManager.initGL())
 +	{
 +		close();
 +		OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
 +		return FALSE;
 +	}
 +
 +	// Disable vertical sync for swap
 +	if (disable_vsync && wglSwapIntervalEXT)
 +	{
 +		LL_DEBUGS("Window") << "Disabling vertical sync" << LL_ENDL;
 +		wglSwapIntervalEXT(0);
 +	}
 +	else
 +	{
 +		LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL;
 +	}
 +
 +	SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
 +
 +	// register this window as handling drag/drop events from the OS
 +	DragAcceptFiles( mWindowHandle, TRUE );
 +
 +	mDragDrop->init( mWindowHandle );
 +	
 +	//register joystick timer callback
 +	SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer
 +
 +	// ok to post quit messages now
 +	mPostQuit = TRUE;
 +
 +	if (auto_show)
 +	{
 +		show();
 +		glClearColor(0.0f, 0.0f, 0.0f, 0.f);
 +		glClear(GL_COLOR_BUFFER_BIT);
 +		swapBuffers();
 +	}
 +
 +	return TRUE;
 +}
 +
 +void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size )
 +{
 +	if( mIsMouseClipping )
 +	{
 +		RECT client_rect_in_screen_space;
 +		if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
 +		{
 +			ClipCursor( &client_rect_in_screen_space );
 +		}
 +	}
 +
 +	// if the window was already maximized, MoveWindow seems to still set the maximized flag even if
 +	// the window is smaller than maximized.
 +	// So we're going to do a restore first (which is a ShowWindow call) (SL-44655).
 +
 +	// THIS CAUSES DEV-15484 and DEV-15949 
 +	//ShowWindow(mWindowHandle, SW_RESTORE);
 +	// NOW we can call MoveWindow
 +	MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE);
 +}
 +
 +BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
 +{
 +	LLCoordScreen screen_pos;
 +
 +	mMousePositionModified = TRUE;
 +	if (!mWindowHandle)
 +	{
 +		return FALSE;
 +	}
 +
 +	if (!convertCoords(position, &screen_pos))
 +	{
 +		return FALSE;
 +	}
 +
 +	// Inform the application of the new mouse position (needed for per-frame
 +	// hover/picking to function).
 +	LLCoordGL gl_pos;
 +	convertCoords(position, &gl_pos);
 +	mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
 +	
 +	// DEV-18951 VWR-8524 Camera moves wildly when alt-clicking.
 +	// Because we have preemptively notified the application of the new
 +	// mouse position via handleMouseMove() above, we need to clear out
 +	// any stale mouse move events.  RN/JC
 +	MSG msg;
 +	while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
 +	{ }
 +
 +	return SetCursorPos(screen_pos.mX, screen_pos.mY);
 +}
 +
 +BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)
 +{
 +	POINT cursor_point;
 +	LLCoordScreen screen_pos;
 +
 +	if (!mWindowHandle ||
 +		!GetCursorPos(&cursor_point))
 +	{
 +		return FALSE;
 +	}
 +
 +	screen_pos.mX = cursor_point.x;
 +	screen_pos.mY = cursor_point.y;
 +
 +	return convertCoords(screen_pos, position);
 +}
 +
 +void LLWindowWin32::hideCursor()
 +{
 +	while (ShowCursor(FALSE) >= 0)
 +	{
 +		// nothing, wait for cursor to push down
 +	}
 +	mCursorHidden = TRUE;
 +	mHideCursorPermanent = TRUE;
 +}
 +
 +void LLWindowWin32::showCursor()
 +{
 +	// makes sure the cursor shows up
 +	while (ShowCursor(TRUE) < 0)
 +	{
 +		// do nothing, wait for cursor to pop out
 +	}
 +	mCursorHidden = FALSE;
 +	mHideCursorPermanent = FALSE;
 +}
 +
 +void LLWindowWin32::showCursorFromMouseMove()
 +{
 +	if (!mHideCursorPermanent)
 +	{
 +		showCursor();
 +	}
 +}
 +
 +void LLWindowWin32::hideCursorUntilMouseMove()
 +{
 +	if (!mHideCursorPermanent)
 +	{
 +		hideCursor();
 +		mHideCursorPermanent = FALSE;
 +	}
 +}
 +
 +BOOL LLWindowWin32::isCursorHidden()
 +{
 +	return mCursorHidden;
 +}
 +
 +
 +HCURSOR LLWindowWin32::loadColorCursor(LPCTSTR name)
 +{
 +	return (HCURSOR)LoadImage(mhInstance,
 +							  name,
 +							  IMAGE_CURSOR,
 +							  0,	// default width
 +							  0,	// default height
 +							  LR_DEFAULTCOLOR);
 +}
 +
 +
 +void LLWindowWin32::initCursors()
 +{
 +	mCursor[ UI_CURSOR_ARROW ]		= LoadCursor(NULL, IDC_ARROW);
 +	mCursor[ UI_CURSOR_WAIT ]		= LoadCursor(NULL, IDC_WAIT);
 +	mCursor[ UI_CURSOR_HAND ]		= LoadCursor(NULL, IDC_HAND);
 +	mCursor[ UI_CURSOR_IBEAM ]		= LoadCursor(NULL, IDC_IBEAM);
 +	mCursor[ UI_CURSOR_CROSS ]		= LoadCursor(NULL, IDC_CROSS);
 +	mCursor[ UI_CURSOR_SIZENWSE ]	= LoadCursor(NULL, IDC_SIZENWSE);
 +	mCursor[ UI_CURSOR_SIZENESW ]	= LoadCursor(NULL, IDC_SIZENESW);
 +	mCursor[ UI_CURSOR_SIZEWE ]		= LoadCursor(NULL, IDC_SIZEWE);  
 +	mCursor[ UI_CURSOR_SIZENS ]		= LoadCursor(NULL, IDC_SIZENS);  
 +	mCursor[ UI_CURSOR_NO ]			= LoadCursor(NULL, IDC_NO);
 +	mCursor[ UI_CURSOR_WORKING ]	= LoadCursor(NULL, IDC_APPSTARTING); 
 +
 +	HMODULE module = GetModuleHandle(NULL);
 +	mCursor[ UI_CURSOR_TOOLGRAB ]	= LoadCursor(module, TEXT("TOOLGRAB"));
 +	mCursor[ UI_CURSOR_TOOLLAND ]	= LoadCursor(module, TEXT("TOOLLAND"));
 +	mCursor[ UI_CURSOR_TOOLFOCUS ]	= LoadCursor(module, TEXT("TOOLFOCUS"));
 +	mCursor[ UI_CURSOR_TOOLCREATE ]	= LoadCursor(module, TEXT("TOOLCREATE"));
 +	mCursor[ UI_CURSOR_ARROWDRAG ]	= LoadCursor(module, TEXT("ARROWDRAG"));
 +	mCursor[ UI_CURSOR_ARROWCOPY ]	= LoadCursor(module, TEXT("ARROWCOPY"));
 +	mCursor[ UI_CURSOR_ARROWDRAGMULTI ]	= LoadCursor(module, TEXT("ARROWDRAGMULTI"));
 +	mCursor[ UI_CURSOR_ARROWCOPYMULTI ]	= LoadCursor(module, TEXT("ARROWCOPYMULTI"));
 +	mCursor[ UI_CURSOR_NOLOCKED ]	= LoadCursor(module, TEXT("NOLOCKED"));
 +	mCursor[ UI_CURSOR_ARROWLOCKED ]= LoadCursor(module, TEXT("ARROWLOCKED"));
 +	mCursor[ UI_CURSOR_GRABLOCKED ]	= LoadCursor(module, TEXT("GRABLOCKED"));
 +	mCursor[ UI_CURSOR_TOOLTRANSLATE ]	= LoadCursor(module, TEXT("TOOLTRANSLATE"));
 +	mCursor[ UI_CURSOR_TOOLROTATE ]	= LoadCursor(module, TEXT("TOOLROTATE")); 
 +	mCursor[ UI_CURSOR_TOOLSCALE ]	= LoadCursor(module, TEXT("TOOLSCALE"));
 +	mCursor[ UI_CURSOR_TOOLCAMERA ]	= LoadCursor(module, TEXT("TOOLCAMERA"));
 +	mCursor[ UI_CURSOR_TOOLPAN ]	= LoadCursor(module, TEXT("TOOLPAN"));
 +	mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN"));
 +	mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3"));
 +	mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
 +
 +	// Color cursors
 +	mCursor[UI_CURSOR_TOOLPLAY] = loadColorCursor(TEXT("TOOLPLAY"));
 +	mCursor[UI_CURSOR_TOOLPAUSE] = loadColorCursor(TEXT("TOOLPAUSE"));
 +	mCursor[UI_CURSOR_TOOLMEDIAOPEN] = loadColorCursor(TEXT("TOOLMEDIAOPEN"));
 +
 +	// Note: custom cursors that are not found make LoadCursor() return NULL.
 +	for( S32 i = 0; i < UI_CURSOR_COUNT; i++ )
 +	{
 +		if( !mCursor[i] )
 +		{
 +			mCursor[i] = LoadCursor(NULL, IDC_ARROW);
 +		}
 +	}
 +}
 +
 +
 +
 +void LLWindowWin32::setCursor(ECursorType cursor)
 +{
 +	if (cursor == UI_CURSOR_ARROW
 +		&& mBusyCount > 0)
 +	{
 +		cursor = UI_CURSOR_WORKING;
 +	}
 +
 +	if( mCurrentCursor != cursor )
 +	{
 +		mCurrentCursor = cursor;
 +		SetCursor( mCursor[cursor] );
 +	}
 +}
 +
 +ECursorType LLWindowWin32::getCursor() const
 +{
 +	return mCurrentCursor;
 +}
 +
 +void LLWindowWin32::captureMouse()
 +{
 +	SetCapture(mWindowHandle);
 +}
 +
 +void LLWindowWin32::releaseMouse()
 +{
 +	// *NOTE:Mani ReleaseCapture will spawn new windows messages...
 +	// which will in turn call our MainWindowProc. It therefore requires
 +	// pausing *and more importantly resumption* of the mainlooptimeout...
 +	// just like DispatchMessage below.
 +	mCallbacks->handlePauseWatchdog(this);
 +	ReleaseCapture();
 +	mCallbacks->handleResumeWatchdog(this);
 +}
 +
 +
 +void LLWindowWin32::delayInputProcessing()
 +{
 +	mInputProcessingPaused = TRUE;
 +}
 +
 +void LLWindowWin32::gatherInput()
 +{
 +	MSG		msg;
 +	int		msg_count = 0;
 +
 +	LLMemType m1(LLMemType::MTYPE_GATHER_INPUT);
 +
 +	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE)
 +	{
 +		mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput");
 +		TranslateMessage(&msg);
 +
 +		// turn watchdog off in here to not fail if windows is doing something wacky
 +		mCallbacks->handlePauseWatchdog(this);
 +		DispatchMessage(&msg);
 +		mCallbacks->handleResumeWatchdog(this);
 +		msg_count++;
 +
 +		if ( mInputProcessingPaused )
 +		{
 +			break;
 +		}
 +		/* Attempted workaround for problem where typing fast and hitting
 +		   return would result in only part of the text being sent. JC
 +
 +		BOOL key_posted = TranslateMessage(&msg);
 +		DispatchMessage(&msg);
 +		msg_count++;
 +
 +		// If a key was translated, a WM_CHAR might have been posted to the end
 +		// of the event queue.  We need it immediately.
 +		if (key_posted && msg.message == WM_KEYDOWN)
 +		{
 +			if (PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, PM_REMOVE))
 +			{
 +				TranslateMessage(&msg);
 +				DispatchMessage(&msg);
 +				msg_count++;
 +			}
 +		}
 +		*/
 +		mCallbacks->handlePingWatchdog(this, "Main:AsyncCallbackGatherInput");
 +		// For async host by name support.  Really hacky.
 +		if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message))
 +		{
 +			gAsyncMsgCallback(msg);
 +		}
 +	}
 +
 +	mInputProcessingPaused = FALSE;
 +
 +	// clear this once we've processed all mouse messages that might have occurred after
 +	// we slammed the mouse position
 +	mMousePositionModified = FALSE;
 +}
 +
 +static LLFastTimer::DeclareTimer FTM_KEYHANDLER("Handle Keyboard");
 +static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse");
 +
 +LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param)
 +{
 +	LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
 +
 +
 +	if (NULL != window_imp)
 +	{
 +		window_imp->mCallbacks->handleResumeWatchdog(window_imp);
 +		window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:StartWndProc");
 +		// Has user provided their own window callback?
 +		if (NULL != window_imp->mWndProc)
 +		{
 +			if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param))
 +			{
 +				// user has handled window message
 +				return 0;
 +			}
 +		}
 +
 +		window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:PreSwitchWndProc");
 +		
 +		// Juggle to make sure we can get negative positions for when
 +		// mouse is outside window.
 +		LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param));
 +
 +		// This doesn't work, as LOWORD returns unsigned short.
 +		//LLCoordWindow window_coord(LOWORD(l_param), HIWORD(l_param));
 +		LLCoordGL gl_coord;
 +
 +		// pass along extended flag in mask
 +		MASK mask = (l_param>>16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0;
 +		BOOL eat_keystroke = TRUE;
 +
 +		switch(u_msg)
 +		{
 +			RECT	update_rect;
 +			S32		update_width;
 +			S32		update_height;
 +
 +		case WM_TIMER:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_TIMER");
 +			window_imp->mCallbacks->handleTimerEvent(window_imp);
 +			break;
 +
 +		case WM_DEVICECHANGE:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DEVICECHANGE");
 +			if (gDebugWindowProc)
 +			{
 +				llinfos << "  WM_DEVICECHANGE: wParam=" << w_param 
 +						<< "; lParam=" << l_param << llendl;
 +			}
 +			if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL)
 +			{
 +				if (window_imp->mCallbacks->handleDeviceChange(window_imp))
 +				{
 +					return 0;
 +				}
 +			}
 +			break;
 +
 +		case WM_PAINT:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PAINT");
 +			GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE);
 +			update_width = update_rect.right - update_rect.left + 1;
 +			update_height = update_rect.bottom - update_rect.top + 1;
 +			window_imp->mCallbacks->handlePaint(window_imp, update_rect.left, update_rect.top,
 +				update_width, update_height);
 +			break;
 +		case WM_PARENTNOTIFY:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PARENTNOTIFY");
 +			u_msg = u_msg;
 +			break;
 +
 +		case WM_SETCURSOR:
 +			// This message is sent whenever the cursor is moved in a window.
 +			// You need to set the appropriate cursor appearance.
 +
 +			// Only take control of cursor over client region of window
 +			// This allows Windows(tm) to handle resize cursors, etc.
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETCURSOR");
 +			if (LOWORD(l_param) == HTCLIENT)
 +			{
 +				SetCursor(window_imp->mCursor[ window_imp->mCurrentCursor] );
 +				return 0;
 +			}
 +			break;
 +
 +		case WM_ENTERMENULOOP:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ENTERMENULOOP");
 +			window_imp->mCallbacks->handleWindowBlock(window_imp);
 +			break;
 +
 +		case WM_EXITMENULOOP:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_EXITMENULOOP");
 +			window_imp->mCallbacks->handleWindowUnblock(window_imp);
 +			break;
 +
 +		case WM_ACTIVATEAPP:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATEAPP");
 +			{
 +				// This message should be sent whenever the app gains or loses focus.
 +				BOOL activating = (BOOL) w_param;
 +				BOOL minimized = window_imp->getMinimized();
 +
 +				if (gDebugWindowProc)
 +				{
 +					LL_INFOS("Window") << "WINDOWPROC ActivateApp "
 +						<< " activating " << S32(activating)
 +						<< " minimized " << S32(minimized)
 +						<< " fullscreen " << S32(window_imp->mFullscreen)
 +						<< LL_ENDL;
 +				}
 +
 +				if (window_imp->mFullscreen)
 +				{
 +					// When we run fullscreen, restoring or minimizing the app needs 
 +					// to switch the screen resolution
 +					if (activating)
 +					{
 +						window_imp->setFullscreenResolution();
 +						window_imp->restore();
 +					}
 +					else
 +					{
 +						window_imp->minimize();
 +						window_imp->resetDisplayResolution();
 +					}
 +				}
 +
 +				window_imp->mCallbacks->handleActivateApp(window_imp, activating);
 +
 +				break;
 +			}
 +
 +		case WM_ACTIVATE:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATE");
 +			{
 +				// Can be one of WA_ACTIVE, WA_CLICKACTIVE, or WA_INACTIVE
 +				BOOL activating = (LOWORD(w_param) != WA_INACTIVE);
 +
 +				BOOL minimized = BOOL(HIWORD(w_param));
 +
 +				if (!activating && LLWinImm::isAvailable() && window_imp->mPreeditor)
 +				{
 +					window_imp->interruptLanguageTextInput();
 +				}
 +
 +				// JC - I'm not sure why, but if we don't report that we handled the 
 +				// WM_ACTIVATE message, the WM_ACTIVATEAPP messages don't work 
 +				// properly when we run fullscreen.
 +				if (gDebugWindowProc)
 +				{
 +					LL_INFOS("Window") << "WINDOWPROC Activate "
 +						<< " activating " << S32(activating) 
 +						<< " minimized " << S32(minimized)
 +						<< LL_ENDL;
 +				}
 +
 +				// Don't handle this.
 +				break;
 +			}
 +
 +		case WM_QUERYOPEN:
 +			// TODO: use this to return a nice icon
 +			break;
 +
 +		case WM_SYSCOMMAND:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSCOMMAND");
 +			switch(w_param)
 +			{
 +			case SC_KEYMENU: 
 +				// Disallow the ALT key from triggering the default system menu.
 +				return 0;		
 +
 +			case SC_SCREENSAVE:
 +			case SC_MONITORPOWER:
 +				// eat screen save messages and prevent them!
 +				return 0;
 +			}
 +			break;
 +
 +		case WM_CLOSE:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CLOSE");
 +			// Will the app allow the window to close?
 +			if (window_imp->mCallbacks->handleCloseRequest(window_imp))
 +			{
 +				// Get the app to initiate cleanup.
 +				window_imp->mCallbacks->handleQuit(window_imp);
 +				// The app is responsible for calling destroyWindow when done with GL
 +			}
 +			return 0;
 +
 +		case WM_DESTROY:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DESTROY");
 +			if (window_imp->shouldPostQuit())
 +			{
 +				PostQuitMessage(0);  // Posts WM_QUIT with an exit code of 0
 +			}
 +			return 0;
 +
 +		case WM_COMMAND:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COMMAND");
 +			if (!HIWORD(w_param)) // this message is from a menu
 +			{
 +				window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param));
 +			}
 +			break;
 +
 +		case WM_SYSKEYDOWN:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSKEYDOWN");
 +			// allow system keys, such as ALT-F4 to be processed by Windows
 +			eat_keystroke = FALSE;
 +		case WM_KEYDOWN:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN");
 +			{
 +				if (gDebugWindowProc)
 +				{
 +					LL_INFOS("Window") << "Debug WindowProc WM_KEYDOWN "
 +						<< " key " << S32(w_param) 
 +						<< LL_ENDL;
 +				}
 +				if(gKeyboard->handleKeyDown(w_param, mask) && eat_keystroke)
 +				{
 +					return 0;
 +				}
 +				// pass on to windows if we didn't handle it
 +				break;
 +			}
 +		case WM_SYSKEYUP:
 +			eat_keystroke = FALSE;
 +		case WM_KEYUP:
 +		{
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP");
 +			LLFastTimer t2(FTM_KEYHANDLER);
 +
 +			if (gDebugWindowProc)
 +			{
 +				LL_INFOS("Window") << "Debug WindowProc WM_KEYUP "
 +					<< " key " << S32(w_param) 
 +					<< LL_ENDL;
 +			}
 +			if (gKeyboard->handleKeyUp(w_param, mask) && eat_keystroke)
 +			{
 +				return 0;
 +			}
 +
 +			// pass on to windows
 +			break;
 +		}
 +		case WM_IME_SETCONTEXT:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_SETCONTEXT");
 +			if (gDebugWindowProc)
 +			{
 +				llinfos << "WM_IME_SETCONTEXT" << llendl;
 +			}
 +			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 +			{
 +				l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW;
 +				// Invoke DefWinProc with the modified LPARAM.
 +			}
 +			break;
 +
 +		case WM_IME_STARTCOMPOSITION:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_STARTCOMPOSITION");
 +			if (gDebugWindowProc)
 +			{
 +				llinfos << "WM_IME_STARTCOMPOSITION" << llendl;
 +			}
 +			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 +			{
 +				window_imp->handleStartCompositionMessage();
 +				return 0;
 +			}
 +			break;
 +
 +		case WM_IME_ENDCOMPOSITION:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_ENDCOMPOSITION");
 +			if (gDebugWindowProc)
 +			{
 +				llinfos << "WM_IME_ENDCOMPOSITION" << llendl;
 +			}
 +			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 +			{
 +				return 0;
 +			}
 +			break;
 +
 +		case WM_IME_COMPOSITION:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_COMPOSITION");
 +			if (gDebugWindowProc)
 +			{
 +				llinfos << "WM_IME_COMPOSITION" << llendl;
 +			}
 +			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 +			{
 +				window_imp->handleCompositionMessage(l_param);
 +				return 0;
 +			}
 +			break;
 +
 +		case WM_IME_REQUEST:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_REQUEST");
 +			if (gDebugWindowProc)
 +			{
 +				llinfos << "WM_IME_REQUEST" << llendl;
 +			}
 +			if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 +			{
 +				LRESULT result = 0;
 +				if (window_imp->handleImeRequests(w_param, l_param, &result))
 +				{
 +					return result;
 +				}
 +			}
 +			break;
 +
 +		case WM_CHAR:
 +			// Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need
 +			// to figure out how that works. - Doug
 +			//
 +			// ... Well, I don't think so.
 +			// How it works is explained in Win32 API document, but WM_UNICHAR didn't work
 +			// as specified at least on Windows XP SP1 Japanese version.  I have never used
 +			// it since then, and I'm not sure whether it has been fixed now, but I don't think
 +			// it is worth trying.  The good old WM_CHAR works just fine even for supplementary
 +			// characters.  We just need to take care of surrogate pairs sent as two WM_CHAR's
 +			// by ourselves.  It is not that tough.  -- Alissa Sabre @ SL
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CHAR");
 +			if (gDebugWindowProc)
 +			{
 +				LL_INFOS("Window") << "Debug WindowProc WM_CHAR "
 +					<< " key " << S32(w_param) 
 +					<< LL_ENDL;
 +			}
 +			// Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE,
 +			// we *did* processed the event, so I believe we should not pass it to DefWindowProc...
 +			window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE));
 +			return 0;
 +
 +		case WM_LBUTTONDOWN:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN");
 +				LLFastTimer t2(FTM_MOUSEHANDLER);
 +				if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 +				{
 +					window_imp->interruptLanguageTextInput();
 +				}
 +
 +				// Because we move the cursor position in the app, we need to query
 +				// to find out where the cursor at the time the event is handled.
 +				// If we don't do this, many clicks could get buffered up, and if the
 +				// first click changes the cursor position, all subsequent clicks
 +				// will occur at the wrong location.  JC
 +				LLCoordWindow cursor_coord_window;
 +				if (window_imp->mMousePositionModified)
 +				{
 +					window_imp->getCursorPosition(&cursor_coord_window);
 +					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 +				}
 +				else
 +				{
 +					window_imp->convertCoords(window_coord, &gl_coord);
 +				}
 +				MASK mask = gKeyboard->currentMask(TRUE);
 +				// generate move event to update mouse coordinates
 +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 +				if (window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask))
 +				{
 +					return 0;
 +				}
 +			}
 +			break;
 +
 +		case WM_LBUTTONDBLCLK:
 +		//RN: ignore right button double clicks for now
 +		//case WM_RBUTTONDBLCLK:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDBLCLK");
 +				// Because we move the cursor position in the app, we need to query
 +				// to find out where the cursor at the time the event is handled.
 +				// If we don't do this, many clicks could get buffered up, and if the
 +				// first click changes the cursor position, all subsequent clicks
 +				// will occur at the wrong location.  JC
 +				LLCoordWindow cursor_coord_window;
 +				if (window_imp->mMousePositionModified)
 +				{
 +					window_imp->getCursorPosition(&cursor_coord_window);
 +					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 +				}
 +				else
 +				{
 +					window_imp->convertCoords(window_coord, &gl_coord);
 +				}
 +				MASK mask = gKeyboard->currentMask(TRUE);
 +				// generate move event to update mouse coordinates
 +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 +				if (window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask) )
 +				{
 +					return 0;
 +				}
 +			}
 +			break;
 +
 +		case WM_LBUTTONUP:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP");
 +				LLFastTimer t2(FTM_MOUSEHANDLER);
 +				//if (gDebugClicks)
 +				//{
 +				//	LL_INFOS("Window") << "WndProc left button up" << LL_ENDL;
 +				//}
 +				// Because we move the cursor position in the app, we need to query
 +				// to find out where the cursor at the time the event is handled.
 +				// If we don't do this, many clicks could get buffered up, and if the
 +				// first click changes the cursor position, all subsequent clicks
 +				// will occur at the wrong location.  JC
 +				LLCoordWindow cursor_coord_window;
 +				if (window_imp->mMousePositionModified)
 +				{
 +					window_imp->getCursorPosition(&cursor_coord_window);
 +					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 +				}
 +				else
 +				{
 +					window_imp->convertCoords(window_coord, &gl_coord);
 +				}
 +				MASK mask = gKeyboard->currentMask(TRUE);
 +				// generate move event to update mouse coordinates
 +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 +				if (window_imp->mCallbacks->handleMouseUp(window_imp, gl_coord, mask))
 +				{
 +					return 0;
 +				}
 +			}
 +			break;
 +
 +		case WM_RBUTTONDBLCLK:
 +		case WM_RBUTTONDOWN:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONDOWN");
 +				LLFastTimer t2(FTM_MOUSEHANDLER);
 +				if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 +				{
 +					window_imp->interruptLanguageTextInput();
 +				}
 +
 +				// Because we move the cursor position in the llviewerapp, we need to query
 +				// to find out where the cursor at the time the event is handled.
 +				// If we don't do this, many clicks could get buffered up, and if the
 +				// first click changes the cursor position, all subsequent clicks
 +				// will occur at the wrong location.  JC
 +				LLCoordWindow cursor_coord_window;
 +				if (window_imp->mMousePositionModified)
 +				{
 +					window_imp->getCursorPosition(&cursor_coord_window);
 +					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 +				}
 +				else
 +				{
 +					window_imp->convertCoords(window_coord, &gl_coord);
 +				}
 +				MASK mask = gKeyboard->currentMask(TRUE);
 +				// generate move event to update mouse coordinates
 +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 +				if (window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask))
 +				{
 +					return 0;
 +				}
 +			}
 +			break;
 +
 +		case WM_RBUTTONUP:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONUP");
 +				LLFastTimer t2(FTM_MOUSEHANDLER);
 +				// Because we move the cursor position in the app, we need to query
 +				// to find out where the cursor at the time the event is handled.
 +				// If we don't do this, many clicks could get buffered up, and if the
 +				// first click changes the cursor position, all subsequent clicks
 +				// will occur at the wrong location.  JC
 +				LLCoordWindow cursor_coord_window;
 +				if (window_imp->mMousePositionModified)
 +				{
 +					window_imp->getCursorPosition(&cursor_coord_window);
 +					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 +				}
 +				else
 +				{
 +					window_imp->convertCoords(window_coord, &gl_coord);
 +				}
 +				MASK mask = gKeyboard->currentMask(TRUE);
 +				// generate move event to update mouse coordinates
 +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 +				if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask))
 +				{
 +					return 0;
 +				}
 +			}
 +			break;
 +
 +		case WM_MBUTTONDOWN:
 +//		case WM_MBUTTONDBLCLK:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN");
 +				LLFastTimer t2(FTM_MOUSEHANDLER);
 +				if (LLWinImm::isAvailable() && window_imp->mPreeditor)
 +				{
 +					window_imp->interruptLanguageTextInput();
 +				}
 +
 +				// Because we move the cursor position in tllviewerhe app, we need to query
 +				// to find out where the cursor at the time the event is handled.
 +				// If we don't do this, many clicks could get buffered up, and if the
 +				// first click changes the cursor position, all subsequent clicks
 +				// will occur at the wrong location.  JC
 +				LLCoordWindow cursor_coord_window;
 +				if (window_imp->mMousePositionModified)
 +				{
 +					window_imp->getCursorPosition(&cursor_coord_window);
 +					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 +				}
 +				else
 +				{
 +					window_imp->convertCoords(window_coord, &gl_coord);
 +				}
 +				MASK mask = gKeyboard->currentMask(TRUE);
 +				// generate move event to update mouse coordinates
 +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 +				if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask))
 +				{
 +					return 0;
 +				}
 +			}
 +			break;
 +
 +		case WM_MBUTTONUP:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP");
 +				LLFastTimer t2(FTM_MOUSEHANDLER);
 +				// Because we move the cursor position in tllviewerhe app, we need to query
 +				// to find out where the cursor at the time the event is handled.
 +				// If we don't do this, many clicks could get buffered up, and if the
 +				// first click changes the cursor position, all subsequent clicks
 +				// will occur at the wrong location.  JC
 +				LLCoordWindow cursor_coord_window;
 +				if (window_imp->mMousePositionModified)
 +				{
 +					window_imp->getCursorPosition(&cursor_coord_window);
 +					window_imp->convertCoords(cursor_coord_window, &gl_coord);
 +				}
 +				else
 +				{
 +					window_imp->convertCoords(window_coord, &gl_coord);
 +				}
 +				MASK mask = gKeyboard->currentMask(TRUE);
 +				// generate move event to update mouse coordinates
 +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 +				if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask))
 +				{
 +					return 0;
 +				}
 +			}
 +			break;
 +
 +		case WM_MOUSEWHEEL:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEWHEEL");
 +				static short z_delta = 0;
 +
 +				z_delta += HIWORD(w_param);
 +				// cout << "z_delta " << z_delta << endl;
 +
 +				// current mouse wheels report changes in increments of zDelta (+120, -120)
 +				// Future, higher resolution mouse wheels may report smaller deltas.
 +				// So we sum the deltas and only act when we've exceeded WHEEL_DELTA
 +				//
 +				// If the user rapidly spins the wheel, we can get messages with
 +				// large deltas, like 480 or so.  Thus we need to scroll more quickly.
 +				if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta)
 +				{
 +					window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA);
 +					z_delta = 0;
 +				}
 +				return 0;
 +			}
 +			/*
 +			// TODO: add this after resolving _WIN32_WINNT issue
 +			case WM_MOUSELEAVE:
 +			{
 +			window_imp->mCallbacks->handleMouseLeave(window_imp);
 +
 +			//				TRACKMOUSEEVENT track_mouse_event;
 +			//				track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT );
 +			//				track_mouse_event.dwFlags = TME_LEAVE;
 +			//				track_mouse_event.hwndTrack = h_wnd;
 +			//				track_mouse_event.dwHoverTime = HOVER_DEFAULT;
 +			//				TrackMouseEvent( &track_mouse_event ); 
 +			return 0;
 +			}
 +			*/
 +			// Handle mouse movement within the window
 +		case WM_MOUSEMOVE:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE");
 +				window_imp->convertCoords(window_coord, &gl_coord);
 +				MASK mask = gKeyboard->currentMask(TRUE);
 +				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
 +				return 0;
 +			}
 +
 +		case WM_SIZE:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SIZE");
 +				S32 width = S32( LOWORD(l_param) );
 +				S32 height = S32( HIWORD(l_param) );
 +
 +				if (gDebugWindowProc)
 +				{
 +					BOOL maximized = ( w_param == SIZE_MAXIMIZED );
 +					BOOL restored  = ( w_param == SIZE_RESTORED );
 +					BOOL minimized = ( w_param == SIZE_MINIMIZED );
 +
 +					LL_INFOS("Window") << "WINDOWPROC Size "
 +						<< width << "x" << height
 +						<< " max " << S32(maximized)
 +						<< " min " << S32(minimized)
 +						<< " rest " << S32(restored)
 +						<< LL_ENDL;
 +				}
 +
 +				// There's an odd behavior with WM_SIZE that I would call a bug. If 
 +				// the window is maximized, and you call MoveWindow() with a size smaller
 +				// than a maximized window, it ends up sending WM_SIZE with w_param set 
 +				// to SIZE_MAXIMIZED -- which isn't true. So the logic below doesn't work.
 +				// (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see 
 +				// LLWindowWin32::moveWindow in this file). 
 +
 +				// If we are now restored, but we weren't before, this
 +				// means that the window was un-minimized.
 +				if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED)
 +				{
 +					window_imp->mCallbacks->handleActivate(window_imp, TRUE);
 +				}
 +
 +				// handle case of window being maximized from fully minimized state
 +				if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED)
 +				{
 +					window_imp->mCallbacks->handleActivate(window_imp, TRUE);
 +				}
 +
 +				// Also handle the minimization case
 +				if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED)
 +				{
 +					window_imp->mCallbacks->handleActivate(window_imp, FALSE);
 +				}
 +
 +				// Actually resize all of our views
 +				if (w_param != SIZE_MINIMIZED)
 +				{
 +					// Ignore updates for minimizing and minimized "windows"
 +					window_imp->mCallbacks->handleResize(	window_imp, 
 +						LOWORD(l_param), 
 +						HIWORD(l_param) );
 +				}
 +
 +				window_imp->mLastSizeWParam = w_param;
 +
 +				return 0;
 +			}
 +
 +		case WM_SETFOCUS:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETFOCUS");
 +			if (gDebugWindowProc)
 +			{
 +				LL_INFOS("Window") << "WINDOWPROC SetFocus" << LL_ENDL;
 +			}
 +			window_imp->mCallbacks->handleFocus(window_imp);
 +			return 0;
 +
 +		case WM_KILLFOCUS:
 +			window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KILLFOCUS");
 +			if (gDebugWindowProc)
 +			{
 +				LL_INFOS("Window") << "WINDOWPROC KillFocus" << LL_ENDL;
 +			}
 +			window_imp->mCallbacks->handleFocusLost(window_imp);
 +			return 0;
 +
 +		case WM_COPYDATA:
 +			{
 +				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA");
 +				// received a URL
 +				PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param;
 +				window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData);
 +			};
 +			return 0;			
 +
 +		case WM_DROPFILES:
 +			{
 +				// HDROP contains what we need
 +				HDROP hdrop = (HDROP)w_param;
 +
 +				// get location in window space where drop occured and convert to OpenGL coordinate space
 +				POINT pt;
 +				DragQueryPoint( hdrop, &pt );
 +				LLCoordGL gl_coord;
 +				LLCoordWindow cursor_coord_window( pt.x, pt.y );
 +				window_imp->convertCoords(cursor_coord_window, &gl_coord);
 +
 +				// get payload (eventually, this needs to more advanced and grab size of payload dynamically
 +				static char file_name[ 1024 ];
 +				DragQueryFileA( hdrop, 0, file_name, 1024 );
 +				void* url = (void*)( file_name );
 +
 +				// if it's a .URL or .lnk ("shortcut") file
 +				if ( std::string( file_name ).find( ".lnk" ) != std::string::npos ||
 +					  std::string( file_name ).find( ".URL" ) != std::string::npos )
 +				{
 +					// read through file - looks like a 2 line file with second line URL= but who knows..
 +					std::ifstream file_handle( file_name );
 +					if ( file_handle.is_open() )
 +					{
 +						std::string line;
 +						while ( ! file_handle.eof() )
 +						{
 +							std::getline( file_handle, line );
 +							if ( ! file_handle.eof() )
 +							{
 +								std::string prefix( "URL=" );
 +								if ( line.find( prefix, 0 ) != std::string::npos )
 +								{
 +									line = line.substr( 4 );  // skip off the URL= bit
 +									strcpy( (char*)url, line.c_str() );
 +									break;
 +								};
 +							};
 +						};
 +						file_handle.close();
 +					};
 +				};
 +
 +				MASK mask = gKeyboard->currentMask(TRUE);
 +
 +				if ( window_imp->completeDropRequest( gl_coord, mask, (char*)url ) )
 +				{
 +					return 0;
 +				};
 +			}
 +			break;
 +		}
 +
 +	window_imp->mCallbacks->handlePauseWatchdog(window_imp);	
 +	}
 +
 +
 +	// pass unhandled messages down to Windows
 +	return DefWindowProc(h_wnd, u_msg, w_param, l_param);
 +}
 +
 +BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to)
 +{
 +	S32		client_height;
 +	RECT	client_rect;
 +	LLCoordWindow window_position;
 +
 +	if (!mWindowHandle ||
 +		!GetClientRect(mWindowHandle, &client_rect) ||
 +		NULL == to)
 +	{
 +		return FALSE;
 +	}
 +
 +	to->mX = from.mX;
 +	client_height = client_rect.bottom - client_rect.top;
 +	to->mY = client_height - from.mY - 1;
 +
 +	return TRUE;
 +}
 +
 +BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to)
 +{
 +	S32		client_height;
 +	RECT	client_rect;
 +
 +	if (!mWindowHandle ||
 +		!GetClientRect(mWindowHandle, &client_rect) ||
 +		NULL == to)
 +	{
 +		return FALSE;
 +	}
 +
 +	to->mX = from.mX;
 +	client_height = client_rect.bottom - client_rect.top;
 +	to->mY = client_height - from.mY - 1;
 +
 +	return TRUE;
 +}
 +
 +BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to)
 +{	
 +	POINT mouse_point;
 +
 +	mouse_point.x = from.mX;
 +	mouse_point.y = from.mY;
 +	BOOL result = ScreenToClient(mWindowHandle, &mouse_point);
 +
 +	if (result)
 +	{
 +		to->mX = mouse_point.x;
 +		to->mY = mouse_point.y;
 +	}
 +
 +	return result;
 +}
 +
 +BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to)
 +{
 +	POINT mouse_point;
 +
 +	mouse_point.x = from.mX;
 +	mouse_point.y = from.mY;
 +	BOOL result = ClientToScreen(mWindowHandle, &mouse_point);
 +
 +	if (result)
 +	{
 +		to->mX = mouse_point.x;
 +		to->mY = mouse_point.y;
 +	}
 +
 +	return result;
 +}
 +
 +BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to)
 +{
 +	LLCoordWindow window_coord;
 +
 +	if (!mWindowHandle || (NULL == to))
 +	{
 +		return FALSE;
 +	}
 +
 +	convertCoords(from, &window_coord);
 +	convertCoords(window_coord, to);
 +	return TRUE;
 +}
 +
 +BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to)
 +{
 +	LLCoordWindow window_coord;
 +
 +	if (!mWindowHandle || (NULL == to))
 +	{
 +		return FALSE;
 +	}
 +
 +	convertCoords(from, &window_coord);
 +	convertCoords(window_coord, to);
 +	return TRUE;
 +}
 +
 +
 +BOOL LLWindowWin32::isClipboardTextAvailable()
 +{
 +	return IsClipboardFormatAvailable(CF_UNICODETEXT);
 +}
 +
 +
 +BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst)
 +{
 +	BOOL success = FALSE;
 +
 +	if (IsClipboardFormatAvailable(CF_UNICODETEXT))
 +	{
 +		if (OpenClipboard(mWindowHandle))
 +		{
 +			HGLOBAL h_data = GetClipboardData(CF_UNICODETEXT);
 +			if (h_data)
 +			{
 +				WCHAR *utf16str = (WCHAR*) GlobalLock(h_data);
 +				if (utf16str)
 +				{
 +					dst = utf16str_to_wstring(utf16str);
 +					LLWStringUtil::removeCRLF(dst);
 +					GlobalUnlock(h_data);
 +					success = TRUE;
 +				}
 +			}
 +			CloseClipboard();
 +		}
 +	}
 +
 +	return success;
 +}
 +
 +
 +BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr)
 +{
 +	BOOL success = FALSE;
 +
 +	if (OpenClipboard(mWindowHandle))
 +	{
 +		EmptyClipboard();
 +
 +		// Provide a copy of the data in Unicode format.
 +		LLWString sanitized_string(wstr);
 +		LLWStringUtil::addCRLF(sanitized_string);
 +		llutf16string out_utf16 = wstring_to_utf16str(sanitized_string);
 +		const size_t size_utf16 = (out_utf16.length() + 1) * sizeof(WCHAR);
 +
 +		// Memory is allocated and then ownership of it is transfered to the system.
 +		HGLOBAL hglobal_copy_utf16 = GlobalAlloc(GMEM_MOVEABLE, size_utf16); 
 +		if (hglobal_copy_utf16)
 +		{
 +			WCHAR* copy_utf16 = (WCHAR*) GlobalLock(hglobal_copy_utf16);
 +			if (copy_utf16)
 +			{
 +				memcpy(copy_utf16, out_utf16.c_str(), size_utf16);	/* Flawfinder: ignore */
 +				GlobalUnlock(hglobal_copy_utf16);
 +
 +				if (SetClipboardData(CF_UNICODETEXT, hglobal_copy_utf16))
 +				{
 +					success = TRUE;
 +				}
 +			}
 +		}
 +
 +		CloseClipboard();
 +	}
 +
 +	return success;
 +}
 +
 +// Constrains the mouse to the window.
 +void LLWindowWin32::setMouseClipping( BOOL b )
 +{
 +	if( b != mIsMouseClipping )
 +	{
 +		BOOL success = FALSE;
 +
 +		if( b )
 +		{
 +			GetClipCursor( &mOldMouseClip );
 +
 +			RECT client_rect_in_screen_space;
 +			if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
 +			{
 +				success = ClipCursor( &client_rect_in_screen_space );
 +			}
 +		}
 +		else
 +		{
 +			// Must restore the old mouse clip, which may be set by another window.
 +			success = ClipCursor( &mOldMouseClip );
 +			SetRect( &mOldMouseClip, 0, 0, 0, 0 );
 +		}
 +
 +		if( success )
 +		{
 +			mIsMouseClipping = b;
 +		}
 +	}
 +}
 +
 +BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp )
 +{
 +	BOOL success = FALSE;
 +
 +	RECT client_rect;
 +	if( mWindowHandle && GetClientRect(mWindowHandle, &client_rect) )
 +	{
 +		POINT top_left;
 +		top_left.x = client_rect.left;
 +		top_left.y = client_rect.top;
 +		ClientToScreen(mWindowHandle, &top_left); 
 +
 +		POINT bottom_right;
 +		bottom_right.x = client_rect.right;
 +		bottom_right.y = client_rect.bottom;
 +		ClientToScreen(mWindowHandle, &bottom_right); 
 +
 +		SetRect( rectp,
 +			top_left.x,
 +			top_left.y,
 +			bottom_right.x,
 +			bottom_right.y );
 +
 +		success = TRUE;
 +	}
 +
 +	return success;
 +}
 +
 +void LLWindowWin32::flashIcon(F32 seconds)
 +{
 +	FLASHWINFO flash_info;
 +
 +	flash_info.cbSize = sizeof(FLASHWINFO);
 +	flash_info.hwnd = mWindowHandle;
 +	flash_info.dwFlags = FLASHW_TRAY;
 +	flash_info.uCount = UINT(seconds / ICON_FLASH_TIME);
 +	flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds
 +	FlashWindowEx(&flash_info);
 +}
 +
 +F32 LLWindowWin32::getGamma()
 +{
 +	return mCurrentGamma;
 +}
 +
 +BOOL LLWindowWin32::restoreGamma()
 +{
 +	return SetDeviceGammaRamp(mhDC, mPrevGammaRamp);
 +}
 +
 +BOOL LLWindowWin32::setGamma(const F32 gamma)
 +{
 +	mCurrentGamma = gamma;
 +
 +	LL_DEBUGS("Window") << "Setting gamma to " << gamma << LL_ENDL;
 +
 +	for ( int i = 0; i < 256; ++i )
 +	{
 +		int mult = 256 - ( int ) ( ( gamma - 1.0f ) * 128.0f );
 +
 +		int value = mult * i;
 +
 +		if ( value > 0xffff )
 +			value = 0xffff;
 +
 +		mCurrentGammaRamp [ 0 * 256 + i ] = 
 +			mCurrentGammaRamp [ 1 * 256 + i ] = 
 +				mCurrentGammaRamp [ 2 * 256 + i ] = ( WORD )value;
 +	};
 +
 +	return SetDeviceGammaRamp ( mhDC, mCurrentGammaRamp );
 +}
 +
 +void LLWindowWin32::setFSAASamples(const U32 fsaa_samples)
 +{
 +	mFSAASamples = fsaa_samples;
 +}
 +
 +U32 LLWindowWin32::getFSAASamples()
 +{
 +	return mFSAASamples;
 +}
 +
 +LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_resolutions)
 +{
 +	if (!mSupportedResolutions)
 +	{
 +		mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
 +		DEVMODE dev_mode;
 +
 +		mNumSupportedResolutions = 0;
 +		for (S32 mode_num = 0; mNumSupportedResolutions < MAX_NUM_RESOLUTIONS; mode_num++)
 +		{
 +			if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
 +			{
 +				break;
 +			}
 +
 +			if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL &&
 +				dev_mode.dmPelsWidth >= 800 &&
 +				dev_mode.dmPelsHeight >= 600)
 +			{
 +				BOOL resolution_exists = FALSE;
 +				for(S32 i = 0; i < mNumSupportedResolutions; i++)
 +				{
 +					if (mSupportedResolutions[i].mWidth == dev_mode.dmPelsWidth &&
 +						mSupportedResolutions[i].mHeight == dev_mode.dmPelsHeight)
 +					{
 +						resolution_exists = TRUE;
 +					}
 +				}
 +				if (!resolution_exists)
 +				{
 +					mSupportedResolutions[mNumSupportedResolutions].mWidth = dev_mode.dmPelsWidth;
 +					mSupportedResolutions[mNumSupportedResolutions].mHeight = dev_mode.dmPelsHeight;
 +					mNumSupportedResolutions++;
 +				}
 +			}
 +		}
 +	}
 +
 +	num_resolutions = mNumSupportedResolutions;
 +	return mSupportedResolutions;
 +}
 +
 +
 +F32 LLWindowWin32::getNativeAspectRatio()
 +{
 +	if (mOverrideAspectRatio > 0.f)
 +	{
 +		return mOverrideAspectRatio;
 +	}
 +	else if (mNativeAspectRatio > 0.f)
 +	{
 +		// we grabbed this value at startup, based on the user's desktop settings
 +		return mNativeAspectRatio;
 +	}
 +	// RN: this hack presumes that the largest supported resolution is monitor-limited
 +	// and that pixels in that mode are square, therefore defining the native aspect ratio
 +	// of the monitor...this seems to work to a close approximation for most CRTs/LCDs
 +	S32 num_resolutions;
 +	LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions);
 +
 +	return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight);
 +}
 +
 +F32 LLWindowWin32::getPixelAspectRatio()
 +{
 +	F32 pixel_aspect = 1.f;
 +	if (getFullscreen())
 +	{
 +		LLCoordScreen screen_size;
 +		getSize(&screen_size);
 +		pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
 +	}
 +
 +	return pixel_aspect;
 +}
 +
 +// Change display resolution.  Returns true if successful.
 +// protected
 +BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
 +{
 +	DEVMODE dev_mode;
 +	dev_mode.dmSize = sizeof(dev_mode);
 +	BOOL success = FALSE;
 +
 +	// Don't change anything if we don't have to
 +	if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
 +	{
 +		if (dev_mode.dmPelsWidth        == width &&
 +			dev_mode.dmPelsHeight       == height &&
 +			dev_mode.dmBitsPerPel       == bits &&
 +			dev_mode.dmDisplayFrequency == refresh )
 +		{
 +			// ...display mode identical, do nothing
 +			return TRUE;
 +		}
 +	}
 +
 +	memset(&dev_mode, 0, sizeof(dev_mode));
 +	dev_mode.dmSize = sizeof(dev_mode);
 +	dev_mode.dmPelsWidth        = width;
 +	dev_mode.dmPelsHeight       = height;
 +	dev_mode.dmBitsPerPel       = bits;
 +	dev_mode.dmDisplayFrequency = refresh;
 +	dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
 +
 +	// CDS_FULLSCREEN indicates that this is a temporary change to the device mode.
 +	LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN);
 +
 +	success = (DISP_CHANGE_SUCCESSFUL == cds_result);
 +
 +	if (!success)
 +	{
 +		LL_WARNS("Window") << "setDisplayResolution failed, "
 +			<< width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL;
 +	}
 +
 +	return success;
 +}
 +
 +// protected
 +BOOL LLWindowWin32::setFullscreenResolution()
 +{
 +	if (mFullscreen)
 +	{
 +		return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh);
 +	}
 +	else
 +	{
 +		return FALSE;
 +	}
 +}
 +
 +// protected
 +BOOL LLWindowWin32::resetDisplayResolution()
 +{
 +	LL_DEBUGS("Window") << "resetDisplayResolution START" << LL_ENDL;
 +
 +	LONG cds_result = ChangeDisplaySettings(NULL, 0);
 +
 +	BOOL success = (DISP_CHANGE_SUCCESSFUL == cds_result);
 +
 +	if (!success)
 +	{
 +		LL_WARNS("Window") << "resetDisplayResolution failed" << LL_ENDL;
 +	}
 +
 +	LL_DEBUGS("Window") << "resetDisplayResolution END" << LL_ENDL;
 +
 +	return success;
 +}
 +
 +void LLWindowWin32::swapBuffers()
 +{
 +	SwapBuffers(mhDC);
 +}
 +
 +
 +//
 +// LLSplashScreenImp
 +//
 +LLSplashScreenWin32::LLSplashScreenWin32()
 +:	mWindow(NULL)
 +{
 +}
 +
 +LLSplashScreenWin32::~LLSplashScreenWin32()
 +{
 +}
 +
 +void LLSplashScreenWin32::showImpl()
 +{
 +	// This appears to work.  ???
 +	HINSTANCE hinst = GetModuleHandle(NULL);
 +
 +	mWindow = CreateDialog(hinst, 
 +		TEXT("SPLASHSCREEN"), 
 +		NULL,	// no parent
 +		(DLGPROC) LLSplashScreenWin32::windowProc); 
 +	ShowWindow(mWindow, SW_SHOW);
 +}
 +
 +
 +void LLSplashScreenWin32::updateImpl(const std::string& mesg)
 +{
 +	if (!mWindow) return;
 +
 +	WCHAR w_mesg[1024];
 +	mbstowcs(w_mesg, mesg.c_str(), 1024);
 +
 +	SendDlgItemMessage(mWindow,
 +		666,		// HACK: text id
 +		WM_SETTEXT,
 +		FALSE,
 +		(LPARAM)w_mesg);
 +}
 +
 +
 +void LLSplashScreenWin32::hideImpl()
 +{
 +	if (mWindow)
 +	{
 +		DestroyWindow(mWindow);
 +		mWindow = NULL; 
 +	}
 +}
 +
 +
 +// static
 +LRESULT CALLBACK LLSplashScreenWin32::windowProc(HWND h_wnd, UINT u_msg,
 +											WPARAM w_param, LPARAM l_param)
 +{
 +	// Just give it to windows
 +	return DefWindowProc(h_wnd, u_msg, w_param, l_param);
 +}
 +
 +//
 +// Helper Funcs
 +//
 +
 +S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type)
 +{
 +	UINT uType;
 +
 +	switch(type)
 +	{
 +	case OSMB_OK:
 +		uType = MB_OK;
 +		break;
 +	case OSMB_OKCANCEL:
 +		uType = MB_OKCANCEL;
 +		break;
 +	case OSMB_YESNO:
 +		uType = MB_YESNO;
 +		break;
 +	default:
 +		uType = MB_OK;
 +		break;
 +	}
 +
 +	// HACK! Doesn't properly handle wide strings!
 +	int retval_win = MessageBoxA(NULL, text.c_str(), caption.c_str(), uType);
 +	S32 retval;
 +
 +	switch(retval_win)
 +	{
 +	case IDYES:
 +		retval = OSBTN_YES;
 +		break;
 +	case IDNO:
 +		retval = OSBTN_NO;
 +		break;
 +	case IDOK:
 +		retval = OSBTN_OK;
 +		break;
 +	case IDCANCEL:
 +		retval = OSBTN_CANCEL;
 +		break;
 +	default:
 +		retval = OSBTN_CANCEL;
 +		break;
 +	}
 +
 +	return retval;
 +}
 +
 +
 +void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url )
 +{
 +	bool found = false;
 +	S32 i;
 +	for (i = 0; i < gURLProtocolWhitelistCount; i++)
 +	{
 +		if (escaped_url.find(gURLProtocolWhitelist[i]) == 0)
 +		{
 +			found = true;
 +			break;
 +		}
 +	}
 +
 +	if (!found)
 +	{
 +		LL_WARNS("Window") << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << LL_ENDL;
 +		return;
 +	}
 +
 +	LL_INFOS("Window") << "Opening URL " << escaped_url << LL_ENDL;
 +
 +	// replaced ShellExecute code with ShellExecuteEx since ShellExecute doesn't work
 +	// reliablly on Vista.
 +
 +	// this is madness.. no, this is..
 +	LLWString url_wstring = utf8str_to_wstring( escaped_url );
 +	llutf16string url_utf16 = wstring_to_utf16str( url_wstring );
 +
 +	// let the OS decide what to use to open the URL
 +	SHELLEXECUTEINFO sei = { sizeof( sei ) };
 +	sei.fMask = SEE_MASK_FLAG_DDEWAIT;
 +	sei.nShow = SW_SHOWNORMAL;
 +	sei.lpVerb = L"open";
 +	sei.lpFile = url_utf16.c_str();
 +	ShellExecuteEx( &sei );
 +
 +	//// TODO: LEAVING OLD CODE HERE SO I DON'T BONE OTHER MERGES
 +	//// DELETE THIS ONCE THE MERGES ARE DONE
 +
 +	// Figure out the user's default web browser
 +	// HKEY_CLASSES_ROOT\http\shell\open\command
 +	/*
 +	std::string reg_path_str = gURLProtocolWhitelistHandler[i] + "\\shell\\open\\command";
 +	WCHAR reg_path_wstr[256];
 +	mbstowcs( reg_path_wstr, reg_path_str.c_str(), LL_ARRAY_SIZE(reg_path_wstr) );
 +
 +	HKEY key;
 +	WCHAR browser_open_wstr[1024];
 +	DWORD buffer_length = 1024;
 +	RegOpenKeyEx(HKEY_CLASSES_ROOT, reg_path_wstr, 0, KEY_QUERY_VALUE, &key);
 +	RegQueryValueEx(key, NULL, NULL, NULL, (LPBYTE)browser_open_wstr, &buffer_length);
 +	RegCloseKey(key);
 +
 +	// Convert to STL string
 +	LLWString browser_open_wstring = utf16str_to_wstring(browser_open_wstr);
 +
 +	if (browser_open_wstring.length() < 2)
 +	{
 +		LL_WARNS("Window") << "Invalid browser executable in registry " << browser_open_wstring << LL_ENDL;
 +		return;
 +	}
 +
 +	// Extract the process that's supposed to be launched
 +	LLWString browser_executable;
 +	if (browser_open_wstring[0] == '"')
 +	{
 +		// executable is quoted, find the matching quote
 +		size_t quote_pos = browser_open_wstring.find('"', 1);
 +		// copy out the string including both quotes
 +		browser_executable = browser_open_wstring.substr(0, quote_pos+1);
 +	}
 +	else
 +	{
 +		// executable not quoted, find a space
 +		size_t space_pos = browser_open_wstring.find(' ', 1);
 +		browser_executable = browser_open_wstring.substr(0, space_pos);
 +	}
 +
 +	LL_DEBUGS("Window") << "Browser reg key: " << wstring_to_utf8str(browser_open_wstring) << LL_ENDL;
 +	LL_INFOS("Window") << "Browser executable: " << wstring_to_utf8str(browser_executable) << LL_ENDL;
 +
 +	// Convert URL to wide string for Windows API
 +	// Assume URL is UTF8, as can come from scripts
 +	LLWString url_wstring = utf8str_to_wstring(escaped_url);
 +	llutf16string url_utf16 = wstring_to_utf16str(url_wstring);
 +
 +	// Convert executable and path to wide string for Windows API
 +	llutf16string browser_exec_utf16 = wstring_to_utf16str(browser_executable);
 +
 +	// ShellExecute returns HINSTANCE for backwards compatiblity.
 +	// MS docs say to cast to int and compare to 32.
 +	HWND our_window = NULL;
 +	LPCWSTR directory_wstr = NULL;
 +	int retval = (int) ShellExecute(our_window, 	// Flawfinder: ignore
 +									L"open", 
 +									browser_exec_utf16.c_str(), 
 +									url_utf16.c_str(), 
 +									directory_wstr,
 +									SW_SHOWNORMAL);
 +	if (retval > 32)
 +	{
 +		LL_DEBUGS("Window") << "load_url success with " << retval << LL_ENDL;
 +	}
 +	else
 +	{
 +		LL_INFOS("Window") << "load_url failure with " << retval << LL_ENDL;
 +	}
 +	*/
 +}
 +
 +
 +BOOL LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b )
 +{
 +	BOOL retval = FALSE;
 +
 +	static CHOOSECOLOR cc;
 +	static COLORREF crCustColors[16];
 +	cc.lStructSize = sizeof(CHOOSECOLOR);
 +	cc.hwndOwner = mWindowHandle;
 +	cc.hInstance = NULL;
 +	cc.rgbResult = RGB ((*r * 255.f),(*g *255.f),(*b * 255.f));
 +	//cc.rgbResult = RGB (0x80,0x80,0x80); 
 +	cc.lpCustColors = crCustColors;
 +	cc.Flags = CC_RGBINIT | CC_FULLOPEN;
 +	cc.lCustData = 0;
 +	cc.lpfnHook = NULL;
 +	cc.lpTemplateName = NULL;
 + 
 +	// This call is modal, so pause agent
 +	//send_agent_pause();	// this is in newview and we don't want to set up a dependency
 +	{
 +		retval = ChooseColor(&cc);
 +	}
 +	//send_agent_resume();	// this is in newview and we don't want to set up a dependency
 +
 +	*b = ((F32)((cc.rgbResult >> 16) & 0xff)) / 255.f;
 +
 +	*g = ((F32)((cc.rgbResult >> 8) & 0xff)) / 255.f;
 +	
 +	*r = ((F32)(cc.rgbResult & 0xff)) / 255.f;
 +
 +	return (retval);
 +}
 +
 +void *LLWindowWin32::getPlatformWindow()
 +{
 +	return (void*)mWindowHandle;
 +}
 +
 +void LLWindowWin32::bringToFront()
 +{
 +	BringWindowToTop(mWindowHandle);
 +}
 +
 +// set (OS) window focus back to the client
 +void LLWindowWin32::focusClient()
 +{
 +	SetFocus ( mWindowHandle );
 +}
 +
 +void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
 +{
 +	if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable())
 +	{
 +		return;
 +	}
 +
 +	if (preeditor != mPreeditor && !b)
 +	{
 +		// This condition may occur with a call to
 +		// setEnabled(BOOL) from LLTextEditor or LLLineEditor
 +		// when the control is not focused.
 +		// We need to silently ignore the case so that
 +		// the language input status of the focused control
 +		// is not disturbed.
 +		return;
 +	}
 +
 +	// Take care of old and new preeditors.
 +	if (preeditor != mPreeditor || !b)
 +	{
 +		if (sLanguageTextInputAllowed)
 +		{
 +			interruptLanguageTextInput();
 +		}
 +		mPreeditor = (b ? preeditor : NULL);
 +	}
 +
 +	sLanguageTextInputAllowed = b;
 +
 +	if ( sLanguageTextInputAllowed )
 +	{
 +		// Allowing: Restore the previous IME status, so that the user has a feeling that the previous 
 +		// text input continues naturally.  Be careful, however, the IME status is meaningful only during the user keeps 
 +		// using same Input Locale (aka Keyboard Layout).
 +		if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale)
 +		{
 +			HIMC himc = LLWinImm::getContext(mWindowHandle);
 +			LLWinImm::setOpenStatus(himc, TRUE);
 +			LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode);
 +			LLWinImm::releaseContext(mWindowHandle, himc);
 +		}
 +	}
 +	else
 +	{
 +		// Disallowing: Turn off the IME so that succeeding key events bypass IME and come to us directly.
 +		// However, do it after saving the current IME  status.  We need to restore the status when
 +		//   allowing language text input again.
 +		sWinInputLocale = GetKeyboardLayout(0);
 +		sWinIMEOpened = LLWinImm::isIME(sWinInputLocale);
 +		if (sWinIMEOpened)
 +		{
 +			HIMC himc = LLWinImm::getContext(mWindowHandle);
 +			sWinIMEOpened = LLWinImm::getOpenStatus(himc);
 +			if (sWinIMEOpened)
 +			{
 +				LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode);
 +
 +				// We need both ImmSetConversionStatus and ImmSetOpenStatus here to surely disable IME's 
 +				// keyboard hooking, because Some IME reacts only on the former and some other on the latter...
 +				LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode);
 +				LLWinImm::setOpenStatus(himc, FALSE);
 +			}
 +			LLWinImm::releaseContext(mWindowHandle, himc);
 + 		}
 +	}
 +}
 +
 +void LLWindowWin32::fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds, 
 +		CANDIDATEFORM *form)
 +{
 +	LLCoordWindow caret_coord, top_left, bottom_right;
 +	convertCoords(caret, &caret_coord);
 +	convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left);
 +	convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right);
 +
 +	memset(form, 0, sizeof(CANDIDATEFORM));
 +	form->dwStyle = CFS_EXCLUDE;
 +	form->ptCurrentPos.x = caret_coord.mX;
 +	form->ptCurrentPos.y = caret_coord.mY;
 +	form->rcArea.left   = top_left.mX;
 +	form->rcArea.top    = top_left.mY;
 +	form->rcArea.right  = bottom_right.mX;
 +	form->rcArea.bottom = bottom_right.mY;
 +}
 +
 +
 +// Put the IME window at the right place (near current text input).   Point coordinates should be the top of the current text line.
 +void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position )
 +{
 +	if (sLanguageTextInputAllowed && LLWinImm::isAvailable())
 +	{
 +		HIMC himc = LLWinImm::getContext(mWindowHandle);
 +
 +		LLCoordWindow win_pos;
 +		convertCoords( position, &win_pos );
 +
 +		if ( win_pos.mX >= 0 && win_pos.mY >= 0 && 
 +			(win_pos.mX != sWinIMEWindowPosition.mX) || (win_pos.mY != sWinIMEWindowPosition.mY) )
 +		{
 +			COMPOSITIONFORM ime_form;
 +			memset( &ime_form, 0, sizeof(ime_form) );
 +			ime_form.dwStyle = CFS_POINT;
 +			ime_form.ptCurrentPos.x = win_pos.mX;
 +			ime_form.ptCurrentPos.y = win_pos.mY;
 +
 +			LLWinImm::setCompositionWindow( himc, &ime_form );
 +
 +			sWinIMEWindowPosition.set( win_pos.mX, win_pos.mY );
 +		}
 +
 +		LLWinImm::releaseContext(mWindowHandle, himc);
 +	}
 +}
 +
 +
 +void LLWindowWin32::fillCharPosition(const LLCoordGL& caret, const LLRect& bounds, const LLRect& control,
 +		IMECHARPOSITION *char_position)
 +{
 +	LLCoordScreen caret_coord, top_left, bottom_right;
 +	convertCoords(caret, &caret_coord);
 +	convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left);
 +	convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right);
 +
 +	char_position->pt.x = caret_coord.mX;
 +	char_position->pt.y = top_left.mY;	// Windows wants the coordinate of upper left corner of a character...
 +	char_position->cLineHeight = bottom_right.mY - top_left.mY;
 +	char_position->rcDocument.left   = top_left.mX;
 +	char_position->rcDocument.top    = top_left.mY;
 +	char_position->rcDocument.right  = bottom_right.mX;
 +	char_position->rcDocument.bottom = bottom_right.mY;
 +}
 +
 +void LLWindowWin32::fillCompositionLogfont(LOGFONT *logfont)
 +{
 +	// Our font is a list of FreeType recognized font files that may
 +	// not have a corresponding ones in Windows' fonts.  Hence, we
 +	// can't simply tell Windows which font we are using.  We will
 +	// notify a _standard_ font for a current input locale instead.
 +	// We use a hard-coded knowledge about the Windows' standard
 +	// configuration to do so...
 +
 +	memset(logfont, 0, sizeof(LOGFONT));
 +
 +	const WORD lang_id = LOWORD(GetKeyboardLayout(0));
 +	switch (PRIMARYLANGID(lang_id))
 +	{
 +	case LANG_CHINESE:
 +		// We need to identify one of two Chinese fonts.
 +		switch (SUBLANGID(lang_id))
 +		{
 +		case SUBLANG_CHINESE_SIMPLIFIED:
 +		case SUBLANG_CHINESE_SINGAPORE:
 +			logfont->lfCharSet = GB2312_CHARSET;
 +			lstrcpy(logfont->lfFaceName, TEXT("SimHei"));
 +			break;
 +		case SUBLANG_CHINESE_TRADITIONAL:
 +		case SUBLANG_CHINESE_HONGKONG:
 +		case SUBLANG_CHINESE_MACAU:
 +		default:
 +			logfont->lfCharSet = CHINESEBIG5_CHARSET;
 +			lstrcpy(logfont->lfFaceName, TEXT("MingLiU"));
 +			break;			
 +		}
 +		break;
 +	case LANG_JAPANESE:
 +		logfont->lfCharSet = SHIFTJIS_CHARSET;
 +		lstrcpy(logfont->lfFaceName, TEXT("MS Gothic"));
 +		break;		
 +	case LANG_KOREAN:
 +		logfont->lfCharSet = HANGUL_CHARSET;
 +		lstrcpy(logfont->lfFaceName, TEXT("Gulim"));
 +		break;
 +	default:
 +		logfont->lfCharSet = ANSI_CHARSET;
 +		lstrcpy(logfont->lfFaceName, TEXT("Tahoma"));
 +		break;
 +	}
 +							
 +	logfont->lfHeight = mPreeditor->getPreeditFontSize();
 +	logfont->lfWeight = FW_NORMAL;
 +}	
 +
 +U32 LLWindowWin32::fillReconvertString(const LLWString &text,
 +	S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string)
 +{
 +	const llutf16string text_utf16 = wstring_to_utf16str(text);
 +	const DWORD required_size = sizeof(RECONVERTSTRING) + (text_utf16.length() + 1) * sizeof(WCHAR);
 +	if (reconvert_string && reconvert_string->dwSize >= required_size)
 +	{
 +		const DWORD focus_utf16_at = wstring_utf16_length(text, 0, focus);
 +		const DWORD focus_utf16_length = wstring_utf16_length(text, focus, focus_length);
 +
 +		reconvert_string->dwVersion = 0;
 +		reconvert_string->dwStrLen = text_utf16.length();
 +		reconvert_string->dwStrOffset = sizeof(RECONVERTSTRING);
 +		reconvert_string->dwCompStrLen = focus_utf16_length;
 +		reconvert_string->dwCompStrOffset = focus_utf16_at * sizeof(WCHAR);
 +		reconvert_string->dwTargetStrLen = 0;
 +		reconvert_string->dwTargetStrOffset = focus_utf16_at * sizeof(WCHAR);
 +
 +		const LPWSTR text = (LPWSTR)((BYTE *)reconvert_string + sizeof(RECONVERTSTRING));
 +		memcpy(text, text_utf16.c_str(), (text_utf16.length() + 1) * sizeof(WCHAR));
 +	}
 +	return required_size;
 +}
 +
 +void LLWindowWin32::updateLanguageTextInputArea()
 +{
 +	if (!mPreeditor || !LLWinImm::isAvailable())
 +	{
 +		return;
 +	}
 +
 +	LLCoordGL caret_coord;
 +	LLRect preedit_bounds;
 +	if (mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL))
 +	{
 +		mLanguageTextInputPointGL = caret_coord;
 +		mLanguageTextInputAreaGL = preedit_bounds;
 +
 +		CANDIDATEFORM candidate_form;
 +		fillCandidateForm(caret_coord, preedit_bounds, &candidate_form);
 +
 +		HIMC himc = LLWinImm::getContext(mWindowHandle);
 +		// Win32 document says there may be up to 4 candidate windows.
 +		// This magic number 4 appears only in the document, and
 +		// there are no constant/macro for the value...
 +		for (int i = 3; i >= 0; --i)
 +		{
 +			candidate_form.dwIndex = i;
 +			LLWinImm::setCandidateWindow(himc, &candidate_form);
 +		}
 +		LLWinImm::releaseContext(mWindowHandle, himc);
 +	}
 +}
 +
 +void LLWindowWin32::interruptLanguageTextInput()
 +{
 +	if (mPreeditor)
 +	{
 +		if (LLWinImm::isAvailable())
 +		{
 +			HIMC himc = LLWinImm::getContext(mWindowHandle);
 +			LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
 +			LLWinImm::releaseContext(mWindowHandle, himc);
 +		}
 +
 +		// Win32 document says there will be no composition string
 +		// after NI_COMPOSITIONSTR returns.  The following call to
 +		// resetPreedit should be a NOP unless IME goes mad...
 +		mPreeditor->resetPreedit();
 +	}
 +}
 +
 +void LLWindowWin32::handleStartCompositionMessage()
 +{
 +	// Let IME know the font to use in feedback UI.
 +	LOGFONT logfont;
 +	fillCompositionLogfont(&logfont);
 +	HIMC himc = LLWinImm::getContext(mWindowHandle);
 +	LLWinImm::setCompositionFont(himc, &logfont);
 +	LLWinImm::releaseContext(mWindowHandle, himc);
 +}
 +
 +// Handle WM_IME_COMPOSITION message.
 +
 +void LLWindowWin32::handleCompositionMessage(const U32 indexes)
 +{
 +	BOOL needs_update = FALSE;
 +	LLWString result_string;
 +	LLWString preedit_string;
 +	S32 preedit_string_utf16_length = 0;
 +	LLPreeditor::segment_lengths_t preedit_segment_lengths;
 +	LLPreeditor::standouts_t preedit_standouts;
 +
 +	// Step I: Receive details of preedits from IME.
 +
 +	HIMC himc = LLWinImm::getContext(mWindowHandle);
 +
 +	if (indexes & GCS_RESULTSTR)
 +	{
 +		LONG size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, NULL, 0);
 +		if (size >= 0)
 +		{
 +			const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1];
 +			size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, data, size);
 +			if (size > 0)
 +			{
 +				result_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
 +			}
 +			delete[] data;
 +			needs_update = TRUE;
 +		}
 +	}
 +	
 +	if (indexes & GCS_COMPSTR)
 +	{
 +		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, NULL, 0);
 +		if (size >= 0)
 +		{
 +			const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1];
 +			size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, data, size);
 +			if (size > 0)
 +			{
 +				preedit_string_utf16_length = size / sizeof(WCHAR);
 +				preedit_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
 +			}
 +			delete[] data;
 +			needs_update = TRUE;
 +		}
 +	}
 +
 +	if ((indexes & GCS_COMPCLAUSE) && preedit_string.length() > 0)
 +	{
 +		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, NULL, 0);
 +		if (size > 0)
 +		{
 +			const LPDWORD data = new DWORD[size / sizeof(DWORD)];
 +			size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, data, size);
 +			if (size >= sizeof(DWORD) * 2
 +				&& data[0] == 0 && data[size / sizeof(DWORD) - 1] == preedit_string_utf16_length)
 +			{
 +				preedit_segment_lengths.resize(size / sizeof(DWORD) - 1);
 +				S32 offset = 0;
 +				for (U32 i = 0; i < preedit_segment_lengths.size(); i++)
 +				{
 +					const S32 length = wstring_wstring_length_from_utf16_length(preedit_string, offset, data[i + 1] - data[i]);
 +					preedit_segment_lengths[i] = length;
 +					offset += length;
 +				}
 +			}
 +			delete[] data;
 +		}
 +	}
 +
 +	if ((indexes & GCS_COMPATTR) && preedit_segment_lengths.size() > 1)
 +	{
 +		LONG size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, NULL, 0);
 +		if (size > 0)
 +		{
 +			const LPBYTE data = new BYTE[size / sizeof(BYTE)];
 +			size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, data, size);
 +			if (size == preedit_string_utf16_length)
 +			{
 +				preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
 +				S32 offset = 0;
 +				for (U32 i = 0; i < preedit_segment_lengths.size(); i++)
 +				{
 +					if (ATTR_TARGET_CONVERTED == data[offset] || ATTR_TARGET_NOTCONVERTED == data[offset])
 +					{
 +						preedit_standouts[i] = TRUE;
 +					}
 +					offset += wstring_utf16_length(preedit_string, offset, preedit_segment_lengths[i]);
 +				}
 +			}
 +			delete[] data;
 +		}
 +	}
 +
 +	S32 caret_position = preedit_string.length();
 +	if (indexes & GCS_CURSORPOS)
 +	{
 +		const S32 caret_position_utf16 = LLWinImm::getCompositionString(himc, GCS_CURSORPOS, NULL, 0);
 +		if (caret_position_utf16 >= 0 && caret_position <= preedit_string_utf16_length)
 +		{
 +			caret_position = wstring_wstring_length_from_utf16_length(preedit_string, 0, caret_position_utf16);
 +		}
 +	}
 +
 +	if (indexes == 0)
 +	{
 +		// I'm not sure this condition really happens, but
 +		// Windows SDK document says it is an indication
 +		// of "reset everything."
 +		needs_update = TRUE;
 +	}
 +
 +	LLWinImm::releaseContext(mWindowHandle, himc);
 +
 +	// Step II: Update the active preeditor.
 +
 +	if (needs_update)
 +	{
 +		mPreeditor->resetPreedit();
 +
 +		if (result_string.length() > 0)
 +		{
 +			for (LLWString::const_iterator i = result_string.begin(); i != result_string.end(); i++)
 +			{
 +				mPreeditor->handleUnicodeCharHere(*i);
 +			}
 +		}
 +
 +		if (preedit_string.length() == 0)
 + 		{
 +			preedit_segment_lengths.clear();
 +			preedit_standouts.clear();
 +		}
 +		else
 +		{
 +			if (preedit_segment_lengths.size() == 0)
 +			{
 +				preedit_segment_lengths.assign(1, preedit_string.length());
 +			}
 +			if (preedit_standouts.size() == 0)
 +			{
 +				preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
 +			}
 +		}
 +		mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
 +
 +		// Some IME doesn't query char position after WM_IME_COMPOSITION,
 +		// so we need to update them actively.
 +		updateLanguageTextInputArea();
 +	}
 +}
 +
 +// Given a text and a focus range, find_context finds and returns a
 +// surrounding context of the focused subtext.  A variable pointed
 +// to by offset receives the offset in llwchars of the beginning of
 +// the returned context string in the given wtext.
 +
 +static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_length, S32 *offset)
 +{
 +	static const S32 CONTEXT_EXCESS = 30;	// This value is by experiences.
 +
 +	const S32 e = llmin((S32) wtext.length(), focus + focus_length + CONTEXT_EXCESS);
 +	S32 end = focus + focus_length;
 +	while (end < e && '\n' != wtext[end])
 +	{
 +		end++;
 +	}
 +
 +	const S32 s = llmax(0, focus - CONTEXT_EXCESS);
 +	S32 start = focus;
 +	while (start > s && '\n' != wtext[start - 1])
 +	{
 +		--start;
 +	}
 +
 +	*offset = start;
 +	return wtext.substr(start, end - start);
 +}
 +
 +// final stage of handling drop requests - both from WM_DROPFILES message
 +// for files and via IDropTarget interface requests.
 +BOOL LLWindowWin32::completeDropRequest( const LLCoordGL gl_coord, const MASK mask, const std::string url )
 +{
 +	if ( mCallbacks->handleDrop( this, gl_coord, mask, url ) )
 +	{
 +		return TRUE;
 +	};
 +
 +	return FALSE;
 +};
 +
 +// Handle WM_IME_REQUEST message.
 +// If it handled the message, returns TRUE.  Otherwise, FALSE.
 +// When it handled the message, the value to be returned from
 +// the Window Procedure is set to *result.
 +
 +BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
 +{
 +	if ( mPreeditor )
 +	{
 +		switch (request)
 +		{
 +			case IMR_CANDIDATEWINDOW:		// http://msdn2.microsoft.com/en-us/library/ms776080.aspx
 +			{
 +				LLCoordGL caret_coord;
 +				LLRect preedit_bounds;
 +				mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL);
 +				
 +				CANDIDATEFORM *const form = (CANDIDATEFORM *)param;
 +				DWORD const dwIndex = form->dwIndex;
 +				fillCandidateForm(caret_coord, preedit_bounds, form);
 +				form->dwIndex = dwIndex;
 +
 +				*result = 1;
 +				return TRUE;
 +			}
 +			case IMR_QUERYCHARPOSITION:
 +			{
 +				IMECHARPOSITION *const char_position = (IMECHARPOSITION *)param;
 +
 +				// char_position->dwCharPos counts in number of
 +				// WCHARs, i.e., UTF-16 encoding units, so we can't simply pass the
 +				// number to getPreeditLocation.  
 +
 +				const LLWString & wtext = mPreeditor->getPreeditString();
 +				S32 preedit, preedit_length;
 +				mPreeditor->getPreeditRange(&preedit, &preedit_length);
 +				LLCoordGL caret_coord;
 +				LLRect preedit_bounds, text_control;
 +				const S32 position = wstring_wstring_length_from_utf16_length(wtext, preedit, char_position->dwCharPos);
 +
 +				if (!mPreeditor->getPreeditLocation(position, &caret_coord, &preedit_bounds, &text_control))
 +				{
 +					LL_WARNS("Window") << "*** IMR_QUERYCHARPOSITON called but getPreeditLocation failed." << LL_ENDL;
 +					return FALSE;
 +				}
 +				fillCharPosition(caret_coord, preedit_bounds, text_control, char_position);
 +
 +				*result = 1;
 +				return TRUE;
 +			}
 +			case IMR_COMPOSITIONFONT:
 +			{
 +				fillCompositionLogfont((LOGFONT *)param);
 +
 +				*result = 1;
 +				return TRUE;
 +			}
 +			case IMR_RECONVERTSTRING:
 +			{
 +				mPreeditor->resetPreedit();
 +				const LLWString & wtext = mPreeditor->getPreeditString();
 +				S32 select, select_length;
 +				mPreeditor->getSelectionRange(&select, &select_length);
 +
 +				S32 context_offset;
 +				const LLWString context = find_context(wtext, select, select_length, &context_offset);
 +
 +				RECONVERTSTRING * const reconvert_string = (RECONVERTSTRING *)param;
 +				const U32 size = fillReconvertString(context, select - context_offset, select_length, reconvert_string);
 +				if (reconvert_string)
 +				{
 +					if (select_length == 0)
 +					{
 +						// Let the IME to decide the reconversion range, and
 +						// adjust the reconvert_string structure accordingly.
 +						HIMC himc = LLWinImm::getContext(mWindowHandle);
 +						const BOOL adjusted = LLWinImm::setCompositionString(himc,
 +									SCS_QUERYRECONVERTSTRING, reconvert_string, size, NULL, 0);
 +						LLWinImm::releaseContext(mWindowHandle, himc);
 +						if (adjusted)
 +						{
 +							const llutf16string & text_utf16 = wstring_to_utf16str(context);
 +							const S32 new_preedit_start = reconvert_string->dwCompStrOffset / sizeof(WCHAR);
 +							const S32 new_preedit_end = new_preedit_start + reconvert_string->dwCompStrLen;
 +							select = utf16str_wstring_length(text_utf16, new_preedit_start);
 +							select_length = utf16str_wstring_length(text_utf16, new_preedit_end) - select;
 +							select += context_offset;
 +						}
 +					}
 +					mPreeditor->markAsPreedit(select, select_length);
 +				}
 +
 +				*result = size;
 +				return TRUE;
 +			}
 +			case IMR_CONFIRMRECONVERTSTRING:
 +			{
 +				*result = FALSE;
 +				return TRUE;
 +			}
 +			case IMR_DOCUMENTFEED:
 +			{
 +				const LLWString & wtext = mPreeditor->getPreeditString();
 +				S32 preedit, preedit_length;
 +				mPreeditor->getPreeditRange(&preedit, &preedit_length);
 +				
 +				S32 context_offset;
 +				LLWString context = find_context(wtext, preedit, preedit_length, &context_offset);
 +				preedit -= context_offset;
 +				if (preedit_length)
 +				{
 +					// IMR_DOCUMENTFEED may be called when we have an active preedit.
 +					// We should pass the context string *excluding* the preedit string.
 +					// Otherwise, some IME are confused.
 +					context.erase(preedit, preedit_length);
 +				}
 +				
 +				RECONVERTSTRING *reconvert_string = (RECONVERTSTRING *)param;
 +				*result = fillReconvertString(context, preedit, 0, reconvert_string);
 +				return TRUE;
 +			}
 +			default:
 +				return FALSE;
 +		}
 +	}
 +
 +	return FALSE;
 +}
 +
 +//static
 +std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
 +{
 +	// Fonts previously in getFontListSans() have moved to fonts.xml.
 +	return std::vector<std::string>();
 +}
 +
 +
 +#endif // LL_WINDOWS
 diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index e14324c9f1..1382cf93a2 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -39,6 +39,7 @@  #include <windows.h>  #include "llwindow.h" +#include "lldragdropwin32.h"  // Hack for async host by name  #define LL_WM_HOST_RESOLVED      (WM_APP + 1) @@ -112,6 +113,8 @@ public:  	/*virtual*/ void interruptLanguageTextInput();  	/*virtual*/ void spawnWebBrowser(const std::string& escaped_url); +	BOOL completeDropRequest( const LLCoordGL gl_coord, const MASK mask, const std::string url ); +  	static std::vector<std::string> getDynamicFallbackFontList();  protected: @@ -206,6 +209,8 @@ protected:  	LLPreeditor		*mPreeditor; +	LLDragDropWin32* mDragDrop; +  	friend class LLWindowManager;  }; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6f6d5fb979..70c79b4555 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5393,6 +5393,17 @@        <key>Value</key>        <integer>0</integer>      </map> +	<key>PrimMediaDragNDrop</key> +	<map> +		<key>Comment</key> +		<string>Enable drag and drop</string> +		<key>Persist</key> +		<integer>1</integer> +		<key>Type</key> +		<string>Boolean</string> +		<key>Value</key> +		<integer>1</integer> +	</map>      <key>PrimMediaMaxRetries</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index fc09c946af..a13963ec37 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -79,6 +79,7 @@  #include "timing.h"  #include "llviewermenu.h"  #include "lltooltip.h" +#include "llmediaentry.h"  // newview includes  #include "llagent.h" @@ -817,6 +818,48 @@ BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MAS    	// Always handled as far as the OS is concerned.  	return TRUE;  } + +BOOL LLViewerWindow::handleDrop( LLWindow *window,  LLCoordGL pos, MASK mask, std::string data ) +{ +	if (gSavedSettings.getBOOL("PrimMediaDragNDrop")) +	{ +		LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY,  TRUE /*BOOL pick_transparent*/ ); + +		LLUUID object_id = pick_info.getObjectID(); +		S32 object_face = pick_info.mObjectFace; +		std::string url = data; + +		llinfos << "### Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << llendl; + +		LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject())); +		if (obj) +		{ +			LLTextureEntry *te = obj->getTE(object_face); +			if (te) +			{ +				if (! te->hasMedia()) +				{ +					// Create new media entry +					LLSD media_data; +					// XXX Should we really do Home URL too? +					media_data[LLMediaEntry::HOME_URL_KEY] = url; +					media_data[LLMediaEntry::CURRENT_URL_KEY] = url; +					media_data[LLMediaEntry::AUTO_PLAY_KEY] = true; +					obj->syncMediaData(object_face, media_data, true, true); +					// XXX This shouldn't be necessary, should it ?!? +					obj->getMediaImpl(object_face)->navigateReload(); +					obj->sendMediaDataUpdate(); +				} +				else { +					// just navigate to the URL +					obj->getMediaImpl(object_face)->navigateTo(url); +				} +			} +		} +	} +  	// Always handled as far as the OS is concerned. +	return TRUE; +}  BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)  { diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index c2906b1718..9b473568b2 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -170,7 +170,8 @@ public:  	/*virtual*/ BOOL handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask);  	/*virtual*/ BOOL handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask);  	/*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask); -	/*virtual*/ void handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask); +	/*virtual*/ BOOL handleDrop(LLWindow *window,  LLCoordGL pos, MASK mask, std::string data); +				void handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask);  	/*virtual*/ void handleMouseLeave(LLWindow *window);  	/*virtual*/ void handleResize(LLWindow *window,  S32 x,  S32 y);  	/*virtual*/ void handleFocus(LLWindow *window); | 
