From caa631bf5b69ef1e39989b8e1e4b3372491cb9b4 Mon Sep 17 00:00:00 2001
From: callum <none@none>
Date: Tue, 27 Oct 2009 17:52:04 -0700
Subject: [PATCH] Added IDropTarget interface. Still lots of cleanup but this
 works ok. You can drag over from Firefox or IE onto a prim

---
 indra/llwindow/lldragdropwin32.cpp   |  295 ++
 indra/llwindow/lldragdropwin32.h     |   55 +
 indra/llwindow/llwindowcallbacks.cpp |    2 +-
 indra/llwindow/llwindowcallbacks.h   |    2 +-
 indra/llwindow/llwindowwin32.cpp     | 7371 +++++++++++++-------------
 indra/llwindow/llwindowwin32.h       |    5 +
 indra/newview/llviewerwindow.cpp     |    4 +-
 indra/newview/llviewerwindow.h       |    2 +-
 8 files changed, 4057 insertions(+), 3679 deletions(-)
 create mode 100644 indra/llwindow/lldragdropwin32.cpp
 create mode 100644 indra/llwindow/lldragdropwin32.h

diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp
new file mode 100644
index 00000000000..0daff853955
--- /dev/null
+++ b/indra/llwindow/lldragdropwin32.cpp
@@ -0,0 +1,295 @@
+/**
+ * @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( pt.x, pt.y);
+						LLCoordWindow cursor_coord_window( pt.x, pt.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 << "###         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 00000000000..6137e5eb655
--- /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 fda2c7ee6f2..1098529e1cd 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -163,7 +163,7 @@ void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *da
 {
 }
 
-BOOL LLWindowCallbacks::handleDrop(LLWindow *window, LLCoordGL pos, MASK mask, void *data)
+BOOL LLWindowCallbacks::handleDrop(LLWindow *window, LLCoordGL pos, MASK mask, std::string data )
 {
 	return FALSE;
 }
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index e1e257943a4..3a09100168b 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -68,7 +68,7 @@ class LLWindowCallbacks
 	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, 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 94c3e1af8c3..da096b9a0a2 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1,2366 +1,2376 @@
-/** 
- * @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>
+/** 
+ * @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 (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 this window as handling drag/drop events from the OS
-	DragAcceptFiles( mWindowHandle, TRUE );
-	
-	//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 ];
+#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 );
+				void* url = (void*)( file_name );
 
 				// if it's a .URL or .lnk ("shortcut") file
 				if ( std::string( file_name ).find( ".lnk" ) != std::string::npos ||
@@ -2390,1316 +2400,1329 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
 				};
 
 				MASK mask = gKeyboard->currentMask(TRUE);
-				if (window_imp->mCallbacks->handleDrop(window_imp, gl_coord, mask, 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);
-}
-
-// 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
+
+				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 e14324c9f17..1382cf93a2b 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 @@ class LLWindowWin32 : public LLWindow
 	/*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 @@ class LLWindowWin32 : public LLWindow
 
 	LLPreeditor		*mPreeditor;
 
+	LLDragDropWin32* mDragDrop;
+
 	friend class LLWindowManager;
 };
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index a0802430865..220f90c2f52 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -817,7 +817,7 @@ BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MAS
 	return TRUE;
 }
 
-BOOL LLViewerWindow::handleDrop(LLWindow *window,  LLCoordGL pos, MASK mask, void* data)
+BOOL LLViewerWindow::handleDrop( LLWindow *window,  LLCoordGL pos, MASK mask, std::string data )
 {
 	if (gSavedSettings.getBOOL("PrimMediaDragNDrop"))
 	{
@@ -825,7 +825,7 @@ BOOL LLViewerWindow::handleDrop(LLWindow *window,  LLCoordGL pos, MASK mask, voi
 
 		LLUUID object_id = pick_info.getObjectID();
 		S32 object_face = pick_info.mObjectFace;
-		std::string url = std::string( (char*)data );
+		std::string url = data;
 
 		llinfos << "### Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << llendl;
 
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 44704b99e39..cf024df9bf9 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -170,7 +170,7 @@ class LLViewerWindow : public LLWindowCallbacks
 	/*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*/ BOOL handleDrop(LLWindow *window,  LLCoordGL pos, MASK mask, void* data);
+	/*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);
-- 
GitLab