Back to index

lightning-sunbird  0.9+nobinonly
nsWindow.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* vim:set ts=2 sts=2 sw=2 et cin: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Dean Tessman <dean_tessman@hotmail.com>
00025  *   Ere Maijala <ere@atp.fi>
00026  *   Mark Hammond <markh@activestate.com>
00027  *   Michael Lowe <michael.lowe@bigfoot.com>
00028  *   Peter Bajusz <hyp-x@inf.bme.hu>
00029  *   Pierre Phaneuf <pp@ludusdesign.com>
00030  *   Robert O'Callahan <roc+moz@cs.cmu.edu>
00031  *   Roy Yokoyama <yokoyama@netscape.com>
00032  *   Makoto Kato  <m_kato@ga2.so-net.ne.jp>
00033  *   Masayuki Nakano <masayuki@d-toybox.com>
00034  *   Dainis Jonitis <Dainis_Jonitis@swh-t.lv>
00035  *   Christian Biesinger <cbiesinger@web.de>
00036  *
00037  * Alternatively, the contents of this file may be used under the terms of
00038  * either the GNU General Public License Version 2 or later (the "GPL"), or
00039  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00040  * in which case the provisions of the GPL or the LGPL are applicable instead
00041  * of those above. If you wish to allow use of your version of this file only
00042  * under the terms of either the GPL or the LGPL, and not to allow others to
00043  * use your version of this file under the terms of the MPL, indicate your
00044  * decision by deleting the provisions above and replace them with the notice
00045  * and other provisions required by the GPL or the LGPL. If you do not delete
00046  * the provisions above, a recipient may use your version of this file under
00047  * the terms of any one of the MPL, the GPL or the LGPL.
00048  *
00049  * ***** END LICENSE BLOCK ***** */
00050 
00051 #if defined(DEBUG_ftang)
00052 //#define KE_DEBUG
00053 //#define DEBUG_IME
00054 //#define DEBUG_IME2
00055 //#define DEBUG_KBSTATE
00056 #endif
00057 
00058 #include "nsWindow.h"
00059 #include "plevent.h"
00060 #include "nsIAppShell.h"
00061 #include "nsIFontMetrics.h"
00062 #include "nsIFontEnumerator.h"
00063 #include "nsIFontPackageService.h"
00064 #include "nsIPrefBranch.h"
00065 #include "nsIPrefService.h"
00066 #include "nsFont.h"
00067 #include "nsGUIEvent.h"
00068 #include "nsIRenderingContext.h"
00069 #include "nsIDeviceContext.h"
00070 #include "nsIScreenManager.h"
00071 #include "nsRect.h"
00072 #include "nsTransform2D.h"
00073 #include "nsIEventQueue.h"
00074 #include "nsIObserverService.h"
00075 #include "imgIContainer.h"
00076 #include "gfxIImageFrame.h"
00077 #include "nsNativeCharsetUtils.h"
00078 #include <windows.h>
00079 #include <process.h>
00080 #include <imm.h>
00081 
00082 #ifdef WINCE
00083 
00084 #define NS_VK_APP1  0x0201
00085 #define NS_VK_APP2  0x0202
00086 #define NS_VK_APP3  0x0203
00087 #define NS_VK_APP4  0x0204
00088 #define NS_VK_APP5  0x0205
00089 #define NS_VK_APP6  0x0206
00090 #define NS_VK_APP7  0x0207
00091 #define NS_VK_APP8  0x0208
00092 #define NS_VK_APP9  0x0209
00093 #define NS_VK_APP10 0x020A
00094 #define NS_VK_APP11 0x020B
00095 
00096 #include "aygshell.h"
00097 #include "imm.h"
00098 #include "tpcshell.h"
00099 #endif
00100 
00101 // unknwn.h is needed to build with WIN32_LEAN_AND_MEAN
00102 #include <unknwn.h>
00103 
00104 //#include <winuser.h>
00105 #include <zmouse.h>
00106 //#include "sysmets.h"
00107 #include "nsGfxCIID.h"
00108 #include "resource.h"
00109 #include <commctrl.h>
00110 #include "prtime.h"
00111 #include "nsIRenderingContextWin.h"
00112 #include "nsIImage.h"
00113 
00114 #ifdef ACCESSIBILITY
00115 #include "OLEIDL.H"
00116 #include "winable.h"
00117 #include "nsIAccessible.h"
00118 #include "nsIAccessibleDocument.h"
00119 #include "nsIAccessNode.h"
00120 #ifndef WM_GETOBJECT
00121 #define WM_GETOBJECT 0x03d
00122 #endif
00123 #endif
00124 
00125 #include <imm.h>
00126 #include "aimm.h"
00127 
00128 #ifndef WINCE
00129 #include <pbt.h>
00130 #ifndef PBT_APMRESUMEAUTOMATIC
00131 #define PBT_APMRESUMEAUTOMATIC 0x0012
00132 #endif
00133 #endif
00134 
00135 #include "nsNativeDragTarget.h"
00136 #include "nsIRollupListener.h"
00137 #include "nsIMenuRollup.h"
00138 #include "nsIRegion.h"
00139 
00140 //~~~ windowless plugin support
00141 #include "nsplugindefs.h"
00142 
00143 // For clipboard support
00144 #include "nsIServiceManager.h"
00145 #include "nsIClipboard.h"
00146 #include "nsWidgetsCID.h"
00147 
00148 #include "nsITimer.h"
00149 
00150 #include "nsITheme.h"
00151 
00152 // For SetIcon
00153 #include "nsILocalFile.h"
00154 #include "nsCRT.h"
00155 #include "nsAppDirectoryServiceDefs.h"
00156 #include "nsXPIDLString.h"
00157 #include "nsIFile.h"
00158 
00159 #include "prprf.h"
00160 #include "prmem.h"
00161 
00162 static const char kMozHeapDumpMessageString[] = "MOZ_HeapDump";
00163 
00164 #define kWindowPositionSlop 20
00165 
00166 #ifndef SPI_GETWHEELSCROLLLINES
00167 #define SPI_GETWHEELSCROLLLINES 104
00168 #endif
00169 
00170 #ifndef MAPVK_VSC_TO_VK
00171 #define MAPVK_VSC_TO_VK  1
00172 #define MAPVK_VK_TO_CHAR 2
00173 #endif
00174   
00175 #ifndef WM_MOUSEHWHEEL
00176 #define WM_MOUSEHWHEEL 0x020E
00177 #endif
00178 
00179 #ifndef SPI_GETWHEELSCROLLCHARS
00180 #define SPI_GETWHEELSCROLLCHARS 0x006C
00181 #endif
00182 
00183 #ifdef MOZ_XUL
00184 
00185 #ifndef AC_SRC_ALPHA
00186 #define AC_SRC_ALPHA            0x01
00187 #endif
00188 
00189 #ifndef WS_EX_LAYERED
00190 #define WS_EX_LAYERED           0x00080000
00191 #endif
00192 
00193 #ifndef ULW_ALPHA
00194 #define ULW_ALPHA               0x00000002
00195 #endif
00196 
00197 
00198 typedef BOOL WINAPI UpdateLayeredWindowProc (HWND hWnd, HDC hdcDst, POINT *pptDst,
00199                                              SIZE *psize, HDC hdcSrc, POINT *pptSrc,
00200                                              COLORREF crKey, BLENDFUNCTION *pblend,
00201                                              DWORD dwFlags);
00202 
00203 
00204 static UpdateLayeredWindowProc* GetUpdateLayeredWindowProc()
00205 {
00206   HMODULE user32 = ::GetModuleHandle("user32.dll");
00207 
00208   return NS_REINTERPRET_CAST(UpdateLayeredWindowProc*,
00209     (user32) ? ::GetProcAddress(user32, "UpdateLayeredWindow") : nsnull);
00210 }
00211 
00212 static UpdateLayeredWindowProc* pUpdateLayeredWindow = GetUpdateLayeredWindowProc();
00213 
00214 static inline PRBool IsAlphaTranslucencySupported() { return pUpdateLayeredWindow != nsnull; }
00215 
00216 #endif
00217 
00218 
00219 #ifdef WINCE
00220 
00221 static UINT   gSoftkeyTimerId = 0;
00222 static UINT   gSoftkeyTimerHit = 0;
00223 static PRBool gOverrideHWKeys = PR_TRUE;
00224 static PRInt32 gSoftkeyContextDelay = 1000;
00225 static PRInt32 gBackRepeatDelay = 500;
00226 
00227 // We want the back key to be able to repeat while the key is held down.
00228 VOID CALLBACK BackSoftkeyTimer(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
00229 {
00230   keybd_event(VK_BACK, 0, 0, 0);
00231   keybd_event(VK_BACK, 0, KEYEVENTF_KEYUP, 0);
00232 }
00233 
00234 // for the soft keys, we want to generate a different event when they are held down.
00235 VOID CALLBACK RightSoftkeyTimer(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
00236 {
00237   gSoftkeyTimerHit=1;
00238 
00239   nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
00240   if (observerService)
00241     observerService->NotifyObservers(nsnull, "softkey", NS_LITERAL_STRING("right+shift").get());
00242 
00243 }
00244 
00245 VOID CALLBACK LeftSoftkeyTimer(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
00246 {
00247   gSoftkeyTimerHit=1;
00248 
00249   nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
00250   if (observerService)
00251     observerService->NotifyObservers(nsnull, "softkey", NS_LITERAL_STRING("left+shift").get());
00252 }
00253 
00254 void CreateSoftKeyMenuBar(HWND wnd)
00255 {
00256   if (!wnd)
00257     return;
00258 
00259 
00260   if (SHFindMenuBar(wnd))
00261     return;
00262 
00263   SHMENUBARINFO mbi;
00264   ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
00265   mbi.cbSize = sizeof(SHMENUBARINFO);
00266   mbi.hwndParent = wnd;
00267 
00268   //  On windows ce smartphone, events never occur if the
00269   //  menubar is empty.  This doesn't work: 
00270   //  mbi.dwFlags = SHCMBF_EMPTYBAR;
00271 
00272   mbi.nToolBarId = IDC_DUMMY_CE_MENUBAR;
00273   mbi.hInstRes   = GetModuleHandle(NULL);
00274   
00275   if (!SHCreateMenuBar(&mbi))
00276     return;
00277 
00278   SetWindowPos(mbi.hwndMB, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE);
00279 
00280   PostMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK,
00281               MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
00282                          SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
00283   
00284   PostMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TSOFT1, 
00285               MAKELPARAM (SHMBOF_NODEFAULT | SHMBOF_NOTIFY, 
00286                           SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
00287   
00288   PostMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TSOFT2, 
00289               MAKELPARAM (SHMBOF_NODEFAULT | SHMBOF_NOTIFY, 
00290                           SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
00291 }
00292 
00293 #endif
00294 
00295 static PRBool IsCursorTranslucencySupported() {
00296   static PRBool didCheck = PR_FALSE;
00297   static PRBool isSupported = PR_FALSE;
00298   if (!didCheck) {
00299     didCheck = PR_TRUE;
00300     // Cursor translucency is supported on Windows XP and newer
00301     OSVERSIONINFO osversion;
00302     memset(&osversion, 0, sizeof(OSVERSIONINFO));
00303     osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00304     if (GetVersionEx(&osversion))
00305       isSupported = osversion.dwMajorVersion > 5 || // Newer Windows versions
00306                     osversion.dwMajorVersion == 5 &&
00307                        osversion.dwMinorVersion >= 1; // WinXP, Server 2003
00308   }
00309 
00310   return isSupported;
00311 }
00312 
00313 
00314 static PRBool IsWin2k()
00315 {
00316   static PRBool didCheck = PR_FALSE;
00317   static PRBool isWin2k = PR_FALSE;
00318 
00319   if (!didCheck) {
00320     didCheck = PR_TRUE;
00321     OSVERSIONINFO versionInfo;
00322   
00323     versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
00324     if (::GetVersionEx(&versionInfo))
00325       isWin2k = versionInfo.dwMajorVersion == 5 &&
00326                 versionInfo.dwMinorVersion == 0;
00327   }
00328 
00329   return isWin2k;
00330 }
00331 
00332 
00333 // Pick some random timer ID.  Is there a better way?
00334 #define NS_FLASH_TIMER_ID 0x011231984
00335 
00336 static NS_DEFINE_CID(kCClipboardCID,       NS_CLIPBOARD_CID);
00337 static NS_DEFINE_IID(kRenderingContextCID, NS_RENDERING_CONTEXT_CID);
00338 
00339 // When we build we are currently (11/27/01) setting the WINVER to 0x0400
00340 // Which means we do not compile in the system resource for the HAND cursor
00341 // this enables us still define the resource and if it isn't there then we will
00342 // get our own hand cursor.
00343 // 32649 is the resource number as defined by WINUSER.H for this cursor
00344 // if the resource is defined by the build env. then it will find it when asked
00345 // if not, then we get our own cursor.
00346 #ifndef IDC_HAND
00347 #define IDC_HAND MAKEINTRESOURCE(32649)
00348 #endif
00349 
00350 static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1";
00351 
00353 // Manager for Registering and unregistering OLE
00354 // This is needed for drag & drop & Clipboard support
00356 class OleRegisterMgr {
00357 public:
00358   ~OleRegisterMgr();
00359 protected:
00360   OleRegisterMgr();
00361 
00362   static OleRegisterMgr mSingleton;
00363 };
00364 OleRegisterMgr OleRegisterMgr::mSingleton;
00365 
00366 OleRegisterMgr::OleRegisterMgr()
00367 {
00368   //DWORD dwVer = ::OleBuildVersion();
00369 
00370   if (FAILED(::OleInitialize(NULL))) {
00371     NS_ASSERTION(0, "***** OLE has not been initialized!\n");
00372   } else {
00373 #ifdef DEBUG
00374     //printf("***** OLE has been initialized!\n");
00375 #endif
00376   }
00377 }
00378 
00379 OleRegisterMgr::~OleRegisterMgr()
00380 {
00381 #ifdef DEBUG
00382   //printf("***** OLE has been Uninitialized!\n");
00383 #endif
00384   ::OleUninitialize();
00385 }
00386 
00388 // nsWindow Class static variable definitions
00390 PRUint32   nsWindow::sInstanceCount            = 0;
00391 
00392 PRBool     nsWindow::sIMEIsComposing           = PR_FALSE;
00393 PRBool     nsWindow::sIMEIsStatusChanged       = PR_FALSE;
00394 
00395 DWORD      nsWindow::sIMEProperty              = 0;
00396 nsString*  nsWindow::sIMECompUnicode           = NULL;
00397 PRUint8*   nsWindow::sIMEAttributeArray        = NULL;
00398 PRInt32    nsWindow::sIMEAttributeArrayLength  = 0;
00399 PRInt32    nsWindow::sIMEAttributeArraySize    = 0;
00400 PRUint32*  nsWindow::sIMECompClauseArray       = NULL;
00401 PRInt32    nsWindow::sIMECompClauseArrayLength = 0;
00402 PRInt32    nsWindow::sIMECompClauseArraySize   = 0;
00403 long       nsWindow::sIMECursorPosition        = 0;
00404 PRUnichar* nsWindow::sIMEReconvertUnicode      = NULL;
00405 
00406 RECT*      nsWindow::sIMECompCharPos           = nsnull;
00407 PRInt32    nsWindow::sIMECaretHeight           = 0;
00408 
00409 BOOL nsWindow::sIsRegistered       = FALSE;
00410 BOOL nsWindow::sIsPopupClassRegistered = FALSE;
00411 UINT nsWindow::uMSH_MOUSEWHEEL     = 0;
00412 UINT nsWindow::uWM_MSIME_RECONVERT = 0; // reconvert message for MSIME
00413 UINT nsWindow::uWM_MSIME_MOUSE     = 0; // mouse message for MSIME
00414 UINT nsWindow::uWM_ATOK_RECONVERT  = 0; // reconvert message for ATOK
00415 UINT nsWindow::uWM_HEAP_DUMP       = 0; // Heap Dump to a file
00416 
00417 HCURSOR        nsWindow::gHCursor            = NULL;
00418 imgIContainer* nsWindow::gCursorImgContainer = nsnull;
00419 
00420 
00421 #ifdef ACCESSIBILITY
00422 BOOL nsWindow::gIsAccessibilityOn = FALSE;
00423 #endif
00424 nsWindow* nsWindow::gCurrentWindow = nsnull;
00426 
00428 // Rollup Listener - static variable definitions
00430 static nsIRollupListener * gRollupListener           = nsnull;
00431 static nsIWidget         * gRollupWidget             = nsnull;
00432 static PRBool              gRollupConsumeRollupEvent = PR_FALSE;
00433 
00434 // Hook Data Memebers for Dropdowns
00435 //
00436 // gProcessHook Tells the hook methods whether they should be
00437 //              processing the hook messages
00438 //
00439 static HHOOK        gMsgFilterHook = NULL;
00440 static HHOOK        gCallProcHook  = NULL;
00441 static HHOOK        gCallMouseHook = NULL;
00442 static PRPackedBool gProcessHook   = PR_FALSE;
00443 static UINT         gRollupMsgId   = 0;
00444 static HWND         gRollupMsgWnd  = NULL;
00445 static UINT         gHookTimerId   = 0;
00447 
00448 
00450 // Mouse Clicks - static variable definitions
00451 // for figuring out 1 - 3 Clicks
00453 static POINT gLastMousePoint;
00454 static POINT gLastMouseMovePoint;
00455 static LONG  gLastMouseDownTime = 0L;
00456 static LONG  gLastClickCount    = 0L;
00457 static BYTE  gLastMouseButton = 0;
00459 
00460 // The last user input event time in microseconds. If there are any pending
00461 // native toolkit input events it returns the current time. The value is
00462 // compatible with PR_IntervalToMicroseconds(PR_IntervalNow()).
00463 static PRUint32 gLastInputEventTime = 0;
00464 
00465 static int gTrimOnMinimize = 2; // uninitialized, but still true
00466 
00467 #if 0
00468 static PRBool is_vk_down(int vk)
00469 {
00470    SHORT st = GetKeyState(vk);
00471 #ifdef DEBUG
00472    printf("is_vk_down vk=%x st=%x\n",vk, st);
00473 #endif
00474    return (st < 0);
00475 }
00476 #define IS_VK_DOWN is_vk_down
00477 #else
00478 #define IS_VK_DOWN(a) (GetKeyState(a) < 0)
00479 #endif
00480 
00481 
00482 //
00483 // input method offsets
00484 //
00485 #define IME_X_OFFSET  0
00486 #define IME_Y_OFFSET  0
00487 
00488 
00489 
00490 #define IS_IME_CODEPAGE(cp) ((932==(cp))||(936==(cp))||(949==(cp))||(950==(cp)))
00491 
00492 //
00493 // Macro for Active Input Method Manager (AIMM) support.
00494 // Use AIMM method instead of Win32 Imm APIs.
00495 //
00496 #define NS_IMM_GETCOMPOSITIONSTRINGA(hIMC, dwIndex, pBuf, dwBufLen, compStrLen) \
00497 { \
00498   compStrLen = 0; \
00499   if (nsToolkit::gAIMMApp) \
00500     nsToolkit::gAIMMApp->GetCompositionStringA(hIMC, dwIndex, dwBufLen, &(compStrLen), pBuf); \
00501    else { \
00502       nsIMM &theIMM = nsIMM::LoadModule(); \
00503       compStrLen = theIMM.GetCompositionStringA(hIMC, dwIndex, pBuf, dwBufLen); \
00504    } \
00505 }
00506 
00507 #define NS_IMM_GETCOMPOSITIONSTRINGW(hIMC, dwIndex, pBuf, dwBufLen, compStrLen) \
00508 { \
00509   compStrLen = 0; \
00510   if (nsToolkit::gAIMMApp) \
00511     nsToolkit::gAIMMApp->GetCompositionStringW(hIMC, dwIndex, dwBufLen, &(compStrLen), pBuf); \
00512     else { \
00513       nsIMM &theIMM = nsIMM::LoadModule(); \
00514       compStrLen = theIMM.GetCompositionStringW(hIMC, dwIndex, pBuf, dwBufLen); \
00515     } \
00516 }
00517 
00518 #define NS_IMM_GETCONTEXT(hWnd, hIMC) \
00519 { \
00520   hIMC = NULL; \
00521   if (nsToolkit::gAIMMApp) \
00522     nsToolkit::gAIMMApp->GetContext(hWnd, &(hIMC)); \
00523   else { \
00524     nsIMM& theIMM = nsIMM::LoadModule(); \
00525     hIMC = (HIMC)theIMM.GetContext(hWnd);  \
00526   } \
00527 }
00528 
00529 #define NS_IMM_RELEASECONTEXT(hWnd, hIMC) \
00530 { \
00531   if (nsToolkit::gAIMMApp) \
00532     nsToolkit::gAIMMApp->ReleaseContext(hWnd, hIMC); \
00533   else { \
00534     nsIMM &theIMM = nsIMM::LoadModule(); \
00535     theIMM.ReleaseContext(hWnd, hIMC); \
00536   } \
00537 }
00538 
00539 #define NS_IMM_NOTIFYIME(hIMC, dwAction, dwIndex, dwValue, bRtn) \
00540 { \
00541   bRtn = TRUE; \
00542   if (nsToolkit::gAIMMApp) { \
00543     bRtn = (nsToolkit::gAIMMApp->NotifyIME(hIMC, dwAction, dwIndex, dwValue) == S_OK); \
00544   }\
00545   else { \
00546     nsIMM &theIMM = nsIMM::LoadModule(); \
00547     (theIMM.NotifyIME(hIMC, dwAction, dwIndex, dwValue)); \
00548   } \
00549 }
00550 
00551 #define NS_IMM_SETCANDIDATEWINDOW(hIMC, candForm) \
00552 { \
00553   if (nsToolkit::gAIMMApp) \
00554     nsToolkit::gAIMMApp->SetCandidateWindow(hIMC, candForm); \
00555   else { \
00556     nsIMM &theIMM = nsIMM::LoadModule(); \
00557     theIMM.SetCandidateWindow(hIMC, candForm); \
00558   } \
00559 }
00560 
00561 #define NS_IMM_SETCOMPOSITIONWINDOW(hIMC, compForm) \
00562 { \
00563   if (nsToolkit::gAIMMApp) \
00564     nsToolkit::gAIMMApp->SetCompositionWindow(hIMC, compForm); \
00565   else { \
00566     nsIMM &theIMM = nsIMM::LoadModule(); \
00567     theIMM.SetCompositionWindow(hIMC, compForm); \
00568   } \
00569 }
00570 
00571 #define NS_IMM_GETCOMPOSITIONWINDOW(hIMC, compForm) \
00572 { \
00573   if (nsToolkit::gAIMMApp) \
00574     nsToolkit::gAIMMApp->GetCompositionWindow(hIMC, compForm); \
00575   else { \
00576     nsIMM &theIMM = nsIMM::LoadModule(); \
00577     theIMM.GetCompositionWindow(hIMC, compForm); \
00578   } \
00579 }
00580 
00581 #define NS_IMM_GETPROPERTY(hKL, dwIndex, dwProp) \
00582 { \
00583   if (nsToolkit::gAIMMApp) \
00584     nsToolkit::gAIMMApp->GetProperty(hKL, dwIndex, &(dwProp)); \
00585   else { \
00586     nsIMM& theIMM = nsIMM::LoadModule(); \
00587     dwProp = (DWORD)theIMM.GetProperty(hKL, dwIndex);  \
00588   } \
00589 }
00590 
00591 #define NS_IMM_GETDEFAULTIMEWND(hWnd, phDefWnd) \
00592 { \
00593   if (nsToolkit::gAIMMApp) \
00594     return nsToolkit::gAIMMApp->GetDefaultIMEWnd(hWnd, phDefWnd); \
00595   else { \
00596     nsIMM& theIMM = nsIMM::LoadModule(); \
00597     *(phDefWnd) = (HWND)theIMM.GetDefaultIMEWnd(hWnd);  \
00598   } \
00599 }
00600 
00601 #define NS_IMM_GETOPENSTATUS(hIMC, bRtn) \
00602 { \
00603   if (nsToolkit::gAIMMApp) \
00604     bRtn = nsToolkit::gAIMMApp->GetOpenStatus(hIMC); \
00605   else { \
00606     nsIMM& theIMM = nsIMM::LoadModule(); \
00607     bRtn = theIMM.GetOpenStatus(hIMC);  \
00608   } \
00609 }
00610 
00611 #define NS_IMM_SETOPENSTATUS(hIMC, bOpen) \
00612 { \
00613   if (nsToolkit::gAIMMApp) \
00614     nsToolkit::gAIMMApp->SetOpenStatus(hIMC, bOpen); \
00615   else { \
00616     nsIMM& theIMM = nsIMM::LoadModule(); \
00617     theIMM.SetOpenStatus(hIMC, bOpen);  \
00618   } \
00619 }
00620 
00621 //
00622 // Macro for Input Method A/W conversion.
00623 //
00624 // On Windows 2000, ImmGetCompositionStringA() doesn't work well using IME of
00625 // different code page.  (See BUG # 29606)
00626 // And ImmGetCompositionStringW() doesn't work on Windows 9x.
00627 //
00628 
00629 #define NS_IMM_GETCOMPOSITIONSTRING(hIMC, dwIndex, cBuf, dwBufLen, lRtn) \
00630 { \
00631   if (nsToolkit::mUseImeApiW) { \
00632     NS_IMM_GETCOMPOSITIONSTRINGW(hIMC, dwIndex, cBuf, dwBufLen, lRtn); \
00633   } else { \
00634     NS_IMM_GETCOMPOSITIONSTRINGA(hIMC, dwIndex, cBuf, dwBufLen, lRtn); \
00635   } \
00636 }
00637 
00638 //
00639 // for reconversion define
00640 //
00641 
00642 // VC++5.0 header doesn't have reconvertion structure and message.
00643 #ifndef WM_IME_REQUEST
00644 #define WM_IME_REQUEST                  0x0288
00645 #endif    // #ifndef WM_IME_REQUEST
00646 
00647 #ifndef IMR_RECONVERTSTRING
00648 #define IMR_RECONVERTSTRING             0x0004
00649 typedef struct tagRECONVERTSTRING {
00650     DWORD dwSize;
00651     DWORD dwVersion;
00652     DWORD dwStrLen;
00653     DWORD dwStrOffset;
00654     DWORD dwCompStrLen;
00655     DWORD dwCompStrOffset;
00656     DWORD dwTargetStrLen;
00657     DWORD dwTargetStrOffset;
00658 } RECONVERTSTRING, FAR * LPRECONVERTSTRING;
00659 #endif    // #ifndef IMR_RECONVERTSTRING
00660 
00661 #ifndef IMR_QUERYCHARPOSITION
00662 #define IMR_QUERYCHARPOSITION           0x0006
00663 typedef struct tagIMECHARPOSITION {
00664     DWORD dwSize;
00665     DWORD dwCharPos;
00666     POINT pt;
00667     UINT  cLineHeight;
00668     RECT  rcDocument;
00669 } IMECHARPOSITION, *PIMECHARPOSITION;
00670 #endif    // #ifndef IMR_QUERYCHARPOSITION
00671 
00672 // from http://msdn.microsoft.com/library/specs/msime.h
00673 #define RWM_RECONVERT       TEXT("MSIMEReconvert")
00674 #define RWM_MOUSE           TEXT("MSIMEMouseOperation")
00675 
00676 #define IMEMOUSE_NONE       0x00    // no mouse button was pushed
00677 #define IMEMOUSE_LDOWN      0x01
00678 #define IMEMOUSE_RDOWN      0x02
00679 #define IMEMOUSE_MDOWN      0x04
00680 #define IMEMOUSE_WUP        0x10    // wheel up
00681 #define IMEMOUSE_WDOWN      0x20    // wheel down
00682 
00683 // from http://www.justsystem.co.jp/tech/atok/api12_04.html#4_11
00684 #define MSGNAME_ATOK_RECONVERT TEXT("Atok Message for ReconvertString")
00685 
00686 //
00687 // App Command messages for IntelliMouse and Natural Keyboard Pro
00688 //
00689 // These messages are not included in Visual C++ 6.0, but are in 7.0
00690 //
00691 #ifndef WM_APPCOMMAND
00692 #define WM_APPCOMMAND  0x0319
00693 #endif
00694 
00695 #ifndef APPCOMMAND_BROWSER_BACKWARD
00696 #define APPCOMMAND_BROWSER_BACKWARD       1
00697 #define APPCOMMAND_BROWSER_FORWARD        2
00698 #define APPCOMMAND_BROWSER_REFRESH        3
00699 #define APPCOMMAND_BROWSER_STOP           4
00700 // keep these around in case we want them later
00701 //#define APPCOMMAND_BROWSER_SEARCH         5
00702 //#define APPCOMMAND_BROWSER_FAVORITES      6
00703 //#define APPCOMMAND_BROWSER_HOME           7
00704 //#define APPCOMMAND_VOLUME_MUTE            8
00705 //#define APPCOMMAND_VOLUME_DOWN            9
00706 //#define APPCOMMAND_VOLUME_UP              10
00707 //#define APPCOMMAND_MEDIA_NEXTTRACK        11
00708 //#define APPCOMMAND_MEDIA_PREVIOUSTRACK    12
00709 //#define APPCOMMAND_MEDIA_STOP             13
00710 //#define APPCOMMAND_MEDIA_PLAY_PAUSE       14
00711 //#define APPCOMMAND_LAUNCH_MAIL            15
00712 //#define APPCOMMAND_LAUNCH_MEDIA_SELECT    16
00713 //#define APPCOMMAND_LAUNCH_APP1            17
00714 //#define APPCOMMAND_LAUNCH_APP2            18
00715 //#define APPCOMMAND_BASS_DOWN              19
00716 //#define APPCOMMAND_BASS_BOOST             20
00717 //#define APPCOMMAND_BASS_UP                21
00718 //#define APPCOMMAND_TREBLE_DOWN            22
00719 //#define APPCOMMAND_TREBLE_UP              23
00720 
00721 //#define FAPPCOMMAND_MOUSE 0x8000
00722 //#define FAPPCOMMAND_KEY   0
00723 //#define FAPPCOMMAND_OEM   0x1000
00724 #define FAPPCOMMAND_MASK  0xF000
00725 
00726 #define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK))
00727 //#define GET_DEVICE_LPARAM(lParam)     ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK))
00728 //#define GET_MOUSEORKEY_LPARAM         GET_DEVICE_LPARAM
00729 //#define GET_FLAGS_LPARAM(lParam)      (LOWORD(lParam))
00730 //#define GET_KEYSTATE_LPARAM(lParam)   GET_FLAGS_LPARAM(lParam)
00731 
00732 #endif  // #ifndef APPCOMMAND_BROWSER_BACKWARD
00733 
00734 static PRBool LangIDToCP(WORD aLangID, UINT& oCP)
00735 {
00736   int localeid=MAKELCID(aLangID,SORT_DEFAULT);
00737   int numchar=GetLocaleInfo(localeid,LOCALE_IDEFAULTANSICODEPAGE,NULL,0);
00738   char cp_on_stack[32];
00739   char* cp_name;
00740 
00741   if (numchar > 32)
00742     cp_name  = new char[numchar];
00743   else
00744     cp_name = cp_on_stack;
00745   if (cp_name) {
00746     GetLocaleInfo(localeid,LOCALE_IDEFAULTANSICODEPAGE,cp_name,numchar);
00747     oCP = atoi(cp_name);
00748     if (cp_name != cp_on_stack)
00749       delete [] cp_name;
00750     return PR_TRUE;
00751   } else {
00752     oCP = CP_ACP;
00753     return PR_FALSE;
00754   }
00755 }
00756 
00757 /* This object maintains a correlation between attention timers and the
00758    windows to which they belong. It's lighter than a hashtable (expected usage
00759    is really just one at a time) and allows nsWindow::GetNSWindowPtr
00760    to remain private. */
00761 class nsAttentionTimerMonitor {
00762 public:
00763   nsAttentionTimerMonitor() : mHeadTimer(0) { }
00764   ~nsAttentionTimerMonitor() {
00765     TimerInfo *current, *next;
00766     for (current = mHeadTimer; current; current = next) {
00767       next = current->next;
00768       delete current;
00769     }
00770   }
00771   void AddTimer(HWND timerWindow, HWND flashWindow, PRInt32 maxFlashCount, UINT timerID) {
00772     TimerInfo *info;
00773     PRBool    newInfo = PR_FALSE;
00774     info = FindInfo(timerWindow);
00775     if (!info) {
00776       info = new TimerInfo;
00777       newInfo = PR_TRUE;
00778     }
00779     if (info) {
00780       info->timerWindow = timerWindow;
00781       info->flashWindow = flashWindow;
00782       info->maxFlashCount = maxFlashCount;
00783       info->flashCount = 0;
00784       info->timerID = timerID;
00785       info->hasFlashed = PR_FALSE;
00786       info->next = 0;
00787       if (newInfo)
00788         AppendTimer(info);
00789     }
00790   }
00791   HWND GetFlashWindowFor(HWND timerWindow) {
00792     TimerInfo *info = FindInfo(timerWindow);
00793     return info ? info->flashWindow : 0;
00794   }
00795   PRInt32 GetMaxFlashCount(HWND timerWindow) {
00796     TimerInfo *info = FindInfo(timerWindow);
00797     return info ? info->maxFlashCount : -1;
00798   }
00799   PRInt32 GetFlashCount(HWND timerWindow) {
00800     TimerInfo *info = FindInfo(timerWindow);
00801     return info ? info->flashCount : -1;
00802   }
00803   void IncrementFlashCount(HWND timerWindow) {
00804     TimerInfo *info = FindInfo(timerWindow);
00805     ++(info->flashCount);
00806   }
00807   void KillTimer(HWND timerWindow) {
00808     TimerInfo *info = FindInfo(timerWindow);
00809     if (info) {
00810       // make sure it's unflashed and kill the timer
00811 
00812       if (info->hasFlashed)
00813         ::FlashWindow(info->flashWindow, FALSE);
00814 
00815       ::KillTimer(info->timerWindow, info->timerID);
00816       RemoveTimer(info);
00817       delete info;
00818     }
00819   }
00820   void SetFlashed(HWND timerWindow) {
00821     TimerInfo *info = FindInfo(timerWindow);
00822     if (info)
00823       info->hasFlashed = PR_TRUE;
00824   }
00825 
00826 private:
00827   struct TimerInfo {
00828     HWND       timerWindow,
00829                flashWindow;
00830     UINT       timerID;
00831     PRInt32    maxFlashCount;
00832     PRInt32    flashCount;
00833     PRBool     hasFlashed;
00834     TimerInfo *next;
00835   };
00836   TimerInfo *FindInfo(HWND timerWindow) {
00837     TimerInfo *scan;
00838     for (scan = mHeadTimer; scan; scan = scan->next)
00839       if (scan->timerWindow == timerWindow)
00840         break;
00841     return scan;
00842   }
00843   void AppendTimer(TimerInfo *info) {
00844     if (!mHeadTimer)
00845       mHeadTimer = info;
00846     else {
00847       TimerInfo *scan, *last;
00848       for (scan = mHeadTimer; scan; scan = scan->next)
00849         last = scan;
00850       last->next = info;
00851     }
00852   }
00853   void RemoveTimer(TimerInfo *info) {
00854     TimerInfo *scan, *last = 0;
00855     for (scan = mHeadTimer; scan && scan != info; scan = scan->next)
00856       last = scan;
00857     if (scan) {
00858       if (last)
00859         last->next = scan->next;
00860       else
00861         mHeadTimer = scan->next;
00862     }
00863   }
00864 
00865   TimerInfo *mHeadTimer;
00866 };
00867 
00868 static nsAttentionTimerMonitor *gAttentionTimerMonitor = 0;
00869 
00870 HWND nsWindow::GetTopLevelHWND(HWND aWnd, PRBool aStopOnFirstTopLevel)
00871 {
00872   HWND curWnd = aWnd;
00873   HWND topWnd = NULL;
00874 
00875   while (curWnd)
00876   {
00877     topWnd = curWnd;
00878 
00879 #ifndef WINCE
00880     if (aStopOnFirstTopLevel)
00881     {
00882       DWORD style = nsToolkit::mGetWindowLong(curWnd, GWL_STYLE);
00883 
00884       if (!(style & WS_CHILDWINDOW))    // first top-level window
00885         break;
00886     }
00887 #endif
00888 
00889     curWnd = ::GetParent(curWnd);       // Parent or owner (if has no parent)
00890   }
00891 
00892   return topWnd;
00893 }
00894 
00895 // Code to dispatch WM_SYSCOLORCHANGE message to all child windows.
00896 // WM_SYSCOLORCHANGE is only sent to top-level windows, but the
00897 // cross platform API requires that NS_SYSCOLORCHANGE message be sent to
00898 // all child windows as well. When running in an embedded application
00899 // we may not receive a WM_SYSCOLORCHANGE message because the top
00900 // level window is owned by the embeddor. Note: this code can be used to
00901 // dispatch other global messages (i.e messages that must be sent to all
00902 // nsIWidget instances.
00903 
00904 // Enumerate all child windows sending aMsg to each of them
00905 
00906 BOOL CALLBACK nsWindow::BroadcastMsgToChildren(HWND aWnd, LPARAM aMsg)
00907 {
00908   WNDPROC winProc = (WNDPROC)nsToolkit::mGetWindowLong(aWnd, GWL_WNDPROC);
00909   if (winProc == &nsWindow::WindowProc) {
00910     // it's one of our windows so go ahead and send a message to it
00911     nsToolkit::mCallWindowProc(winProc, aWnd, aMsg, 0, 0);
00912   }
00913   return TRUE;
00914 }
00915 
00916 // Enumerate all top level windows specifying that the children of each
00917 // top level window should be enumerated. Do *not* send the message to
00918 // each top level window since it is assumed that the toolkit will send
00919 // aMsg to them directly.
00920 
00921 BOOL CALLBACK nsWindow::BroadcastMsg(HWND aTopWindow, LPARAM aMsg)
00922 {
00923   // Iterate each of aTopWindows child windows sending the aMsg
00924   // to each of them.
00925   EnumChildWindows(aTopWindow, nsWindow::BroadcastMsgToChildren, aMsg);
00926   return TRUE;
00927 }
00928 
00929 // This method is called from nsToolkit::WindowProc to forward global
00930 // messages which need to be dispatched to all child windows.
00931 
00932 void nsWindow::GlobalMsgWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
00933 {
00934   switch (msg) {
00935     case WM_SYSCOLORCHANGE:
00936       // System color changes are posted to top-level windows only.
00937       // The NS_SYSCOLORCHANGE must be dispatched to all child
00938       // windows as well.
00939      ::EnumThreadWindows(GetCurrentThreadId(), nsWindow::BroadcastMsg, msg);
00940     break;
00941   }
00942 }
00943 
00944 // End of the methods to dispatch global messages
00945 
00946 //-------------------------------------------------------------------------
00947 //
00948 // nsISupport stuff
00949 //
00950 //-------------------------------------------------------------------------
00951 NS_IMPL_ADDREF(nsWindow)
00952 NS_IMPL_RELEASE(nsWindow)
00953 NS_IMETHODIMP nsWindow::QueryInterface(const nsIID& aIID, void** aInstancePtr)
00954 {
00955   if (NULL == aInstancePtr) {
00956     return NS_ERROR_NULL_POINTER;
00957   }
00958 
00959   if (aIID.Equals(NS_GET_IID(nsIKBStateControl))) {
00960     *aInstancePtr = (void*) ((nsIKBStateControl*)this);
00961     NS_ADDREF((nsBaseWidget*)this);
00962     return NS_OK;
00963   }
00964 
00965   return nsBaseWidget::QueryInterface(aIID,aInstancePtr);
00966 }
00967 //-------------------------------------------------------------------------
00968 //
00969 // nsWindow constructor
00970 //
00971 //-------------------------------------------------------------------------
00972 #ifdef ACCESSIBILITY
00973 nsWindow::nsWindow() : nsBaseWidget()
00974 #else
00975 nsWindow::nsWindow() : nsBaseWidget()
00976 #endif
00977 {
00978   mWnd                = 0;
00979   mPrevWndProc        = NULL;
00980   mBackground         = ::GetSysColor(COLOR_BTNFACE);
00981   mBrush              = ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground));
00982   mForeground         = ::GetSysColor(COLOR_WINDOWTEXT);
00983   mIsShiftDown        = PR_FALSE;
00984   mIsControlDown      = PR_FALSE;
00985   mIsAltDown          = PR_FALSE;
00986   mIsDestroying       = PR_FALSE;
00987   mOnDestroyCalled    = PR_FALSE;
00988   mDeferredPositioner = NULL;
00989   mLastPoint.x        = 0;
00990   mLastPoint.y        = 0;
00991   mPreferredWidth     = 0;
00992   mPreferredHeight    = 0;
00993   mFont               = nsnull;
00994   mIsVisible          = PR_FALSE;
00995   mHas3DBorder        = PR_FALSE;
00996 #ifdef MOZ_XUL
00997   mIsTranslucent      = PR_FALSE;
00998   mIsTopTranslucent   = PR_FALSE;
00999   w2k.mMemoryDC       = NULL;
01000   w2k.mMemoryBitmap   = NULL;
01001   w2k.mMemoryBits     = NULL;
01002   w9x.mPerformingSetWindowRgn = PR_FALSE;
01003   mAlphaMask          = nsnull;
01004 #endif
01005   mWindowType         = eWindowType_child;
01006   mBorderStyle        = eBorderStyle_default;
01007   mBorderlessParent   = 0;
01008   mUnicodeWidget      = PR_TRUE;
01009   mIsInMouseCapture   = PR_FALSE;
01010   mIsInMouseWheelProcessing = PR_FALSE;
01011   mLastSize.width     = 0;
01012   mLastSize.height    = 0;
01013   mOldStyle           = 0;
01014   mOldExStyle         = 0;
01015   mPainting           = 0;
01016 
01017   mLeadByte = '\0';
01018   mBlurEventSuppressionLevel = 0;
01019 
01020   static BOOL gbInitGlobalValue = FALSE;
01021   if (! gbInitGlobalValue) {
01022     gbInitGlobalValue = TRUE;
01023     gKeyboardLayout = GetKeyboardLayout(0);
01024     LangIDToCP((WORD)(0x0FFFFL & (DWORD)gKeyboardLayout), gCurrentKeyboardCP);
01025 
01026     if (nsToolkit::mW2KXP_CP936) {
01027       DWORD imeProp = 0;
01028       NS_IMM_GETPROPERTY(gKeyboardLayout, IGP_PROPERTY, imeProp);
01029       nsToolkit::mUseImeApiW = (imeProp & IME_PROP_UNICODE) ? PR_TRUE : PR_FALSE;
01030     }
01031 
01032     //
01033     // Reconvert message for Windows 95 / NT 4.0
01034     //
01035 
01036     // MS-IME98/2000
01037     nsWindow::uWM_MSIME_RECONVERT = ::RegisterWindowMessage(RWM_RECONVERT);
01038 
01039     // ATOK12/13
01040     nsWindow::uWM_ATOK_RECONVERT  = ::RegisterWindowMessage(MSGNAME_ATOK_RECONVERT);
01041 
01042     // mouse message of MSIME98/2000
01043     nsWindow::uWM_MSIME_MOUSE     = ::RegisterWindowMessage(RWM_MOUSE);
01044 
01045     // Heap dump
01046 #ifndef WINCE
01047     nsWindow::uWM_HEAP_DUMP = ::RegisterWindowMessage(kMozHeapDumpMessageString);
01048 #endif
01049   }
01050 
01051   mNativeDragTarget = nsnull;
01052   mIsTopWidgetWindow = PR_FALSE;
01053   mLastKeyboardLayout = 0;
01054 
01055   sInstanceCount++;
01056 
01057 #if !defined (__MINGW32__) && !defined(WINCE) 
01058   if (!nsWindow::uMSH_MOUSEWHEEL)
01059     nsWindow::uMSH_MOUSEWHEEL = RegisterWindowMessage(MSH_MOUSEWHEEL);
01060 #endif
01061   
01062 #ifdef WINCE
01063   nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
01064   if (prefs) {
01065     nsCOMPtr<nsIPrefBranch> prefBranch;
01066     prefs->GetBranch(0, getter_AddRefs(prefBranch));
01067     if (prefBranch)
01068     {
01069       prefBranch->GetBoolPref("config.wince.overrideHWKeys", &gOverrideHWKeys);
01070       prefBranch->GetIntPref("config.wince.backRepeatDelay", &gBackRepeatDelay);
01071       prefBranch->GetIntPref("config.wince.softKeyContextDelay", &gSoftkeyContextDelay);
01072     }
01073   }
01074 #endif
01075 }
01076 
01077 
01078 HKL nsWindow::gKeyboardLayout = 0;
01079 UINT nsWindow::gCurrentKeyboardCP = 0;
01080 PRBool nsWindow::gSwitchKeyboardLayout = PR_FALSE;
01081 
01082 //-------------------------------------------------------------------------
01083 //
01084 // nsWindow destructor
01085 //
01086 //-------------------------------------------------------------------------
01087 nsWindow::~nsWindow()
01088 {
01089   mIsDestroying = PR_TRUE;
01090   if (gCurrentWindow == this) {
01091     gCurrentWindow = nsnull;
01092   }
01093 
01094   if (MouseTrailer::GetSingleton().GetMouseTrailerWindow() == this) {
01095     MouseTrailer::GetSingleton().DestroyTimer();
01096   }
01097 
01098   // If the widget was released without calling Destroy() then the native
01099   // window still exists, and we need to destroy it
01100   if (NULL != mWnd) {
01101     Destroy();
01102   }
01103 
01104   //XXX Temporary: Should not be caching the font
01105   delete mFont;
01106 
01107   if (mCursor == -1) {
01108     // A sucessfull SetCursor call will destroy the custom cursor, if it's ours
01109     SetCursor(eCursor_standard);
01110   }
01111 
01112   //
01113   // delete any of the IME structures that we allocated
01114   //
01115   sInstanceCount--;
01116   if (sInstanceCount == 0) {
01117     if (sIMECompUnicode) 
01118       delete sIMECompUnicode;
01119     if (sIMEAttributeArray) 
01120       delete [] sIMEAttributeArray;
01121     if (sIMECompClauseArray) 
01122       delete [] sIMECompClauseArray;
01123     if (sIMEReconvertUnicode)
01124       nsMemory::Free(sIMEReconvertUnicode);
01125 
01126     NS_IF_RELEASE(gCursorImgContainer);
01127   }
01128 
01129   NS_IF_RELEASE(mNativeDragTarget);
01130 
01131 }
01132 
01133 
01134 NS_METHOD nsWindow::CaptureMouse(PRBool aCapture)
01135 {
01136   if (aCapture) {
01137     MouseTrailer::GetSingleton().SetCaptureWindow(this);
01138     ::SetCapture(mWnd);
01139   } else {
01140     MouseTrailer::GetSingleton().SetCaptureWindow(NULL);
01141     ::ReleaseCapture();
01142   }
01143   mIsInMouseCapture = aCapture;
01144   return NS_OK;
01145 }
01146 
01147 
01148 //-------------------------------------------------------------------------
01149 //
01150 // Default for height modification is to do nothing
01151 //
01152 //-------------------------------------------------------------------------
01153 
01154 PRInt32 nsWindow::GetHeight(PRInt32 aProposedHeight)
01155 {
01156   return(aProposedHeight);
01157 }
01158 
01159 //-------------------------------------------------------------------------
01160 //
01161 // Deferred Window positioning
01162 //
01163 //-------------------------------------------------------------------------
01164 
01165 NS_METHOD nsWindow::BeginResizingChildren(void)
01166 {
01167   if (NULL == mDeferredPositioner)
01168     mDeferredPositioner = ::BeginDeferWindowPos(1);
01169   return NS_OK;
01170 }
01171 
01172 NS_METHOD nsWindow::EndResizingChildren(void)
01173 {
01174   if (NULL != mDeferredPositioner) {
01175     ::EndDeferWindowPos(mDeferredPositioner);
01176     mDeferredPositioner = NULL;
01177   }
01178   return NS_OK;
01179 }
01180 
01181 NS_METHOD nsWindow::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect)
01182 {
01183   POINT point;
01184   point.x = aOldRect.x;
01185   point.y = aOldRect.y;
01186   ::ClientToScreen(mWnd, &point);
01187   aNewRect.x = point.x;
01188   aNewRect.y = point.y;
01189   aNewRect.width = aOldRect.width;
01190   aNewRect.height = aOldRect.height;
01191   return NS_OK;
01192 }
01193 
01194 NS_METHOD nsWindow::ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect)
01195 {
01196   POINT point;
01197   point.x = aOldRect.x;
01198   point.y = aOldRect.y;
01199   ::ScreenToClient(mWnd, &point);
01200   aNewRect.x = point.x;
01201   aNewRect.y = point.y;
01202   aNewRect.width = aOldRect.width;
01203   aNewRect.height = aOldRect.height;
01204   return NS_OK;
01205 }
01206 
01207 //-------------------------------------------------------------------------
01208 //
01209 // Convert nsEventStatus value to a windows boolean
01210 //
01211 //-------------------------------------------------------------------------
01212 
01213 PRBool nsWindow::ConvertStatus(nsEventStatus aStatus)
01214 {
01215   switch (aStatus) {
01216   case nsEventStatus_eIgnore:
01217     return PR_FALSE;
01218   case nsEventStatus_eConsumeNoDefault:
01219     return PR_TRUE;
01220   case nsEventStatus_eConsumeDoDefault:
01221     return PR_FALSE;
01222   default:
01223     NS_ASSERTION(0, "Illegal nsEventStatus enumeration value");
01224     break;
01225   }
01226   return PR_FALSE;
01227 }
01228 
01229 //-------------------------------------------------------------------------
01230 //
01231 // Initialize an event to dispatch
01232 //
01233 //-------------------------------------------------------------------------
01234 void nsWindow::InitEvent(nsGUIEvent& event, nsPoint* aPoint)
01235 {
01236   NS_ADDREF(event.widget);
01237 
01238   if (nsnull == aPoint) {     // use the point from the event
01239     // get the message position in client coordinates and in twips
01240     DWORD pos = ::GetMessagePos();
01241     POINT cpos;
01242 
01243     cpos.x = GET_X_LPARAM(pos);
01244     cpos.y = GET_Y_LPARAM(pos);
01245 
01246     if (mWnd != NULL) {
01247       ::ScreenToClient(mWnd, &cpos);
01248       event.point.x = cpos.x;
01249       event.point.y = cpos.y;
01250     } else {
01251       event.point.x = 0;
01252       event.point.y = 0;
01253     }
01254   }
01255   else {                      // use the point override if provided
01256     event.point.x = aPoint->x;
01257     event.point.y = aPoint->y;
01258   }
01259 
01260   event.time = ::GetMessageTime();
01261 
01262   mLastPoint.x = event.point.x;
01263   mLastPoint.y = event.point.y;
01264 }
01265 
01266 /* In some circumstances (opening dependent windows) it makes more sense
01267    (and fixes a crash bug) to not blur the parent window. */
01268 void nsWindow::SuppressBlurEvents(PRBool aSuppress)
01269 {
01270   if (aSuppress)
01271     ++mBlurEventSuppressionLevel; // for this widget
01272   else {
01273     NS_ASSERTION(mBlurEventSuppressionLevel > 0, "unbalanced blur event suppression");
01274     if (mBlurEventSuppressionLevel > 0)
01275       --mBlurEventSuppressionLevel;
01276   }
01277 }
01278 
01279 PRBool nsWindow::BlurEventsSuppressed()
01280 {
01281   // are they suppressed in this window?
01282   if (mBlurEventSuppressionLevel > 0)
01283     return PR_TRUE;
01284 
01285   // are they suppressed by any container widget?
01286   HWND parentWnd = ::GetParent(mWnd);
01287   if (parentWnd) {
01288     nsWindow *parent = GetNSWindowPtr(parentWnd);
01289     if (parent)
01290       return parent->BlurEventsSuppressed();
01291   }
01292   return PR_FALSE;
01293 }
01294 
01295 //-------------------------------------------------------------------------
01296 //
01297 // Invokes callback and ProcessEvent method on Event Listener object
01298 //
01299 //-------------------------------------------------------------------------
01300 
01301 NS_IMETHODIMP nsWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus)
01302 {
01303 #ifdef NS_DEBUG
01304   debug_DumpEvent(stdout,
01305                   event->widget,
01306                   event,
01307                   nsCAutoString("something"),
01308                   (PRInt32) mWnd);
01309 #endif // NS_DEBUG
01310 
01311   aStatus = nsEventStatus_eIgnore;
01312 
01313   // skip processing of suppressed blur events
01314   if ((event->message == NS_DEACTIVATE || event->message == NS_LOSTFOCUS) &&
01315       BlurEventsSuppressed())
01316     return NS_OK;
01317 
01318   if (nsnull != mEventCallback) {
01319     aStatus = (*mEventCallback)(event);
01320   }
01321 
01322   // Dispatch to event listener if event was not consumed
01323   if ((aStatus != nsEventStatus_eIgnore) && (nsnull != mEventListener)) {
01324     aStatus = mEventListener->ProcessEvent(*event);
01325   }
01326 
01327   // the window can be destroyed during processing of seemingly innocuous events like, say,
01328   // mousedowns due to the magic of scripting. mousedowns will return nsEventStatus_eIgnore,
01329   // which causes problems with the deleted window. therefore:
01330   if (mOnDestroyCalled)
01331     aStatus = nsEventStatus_eConsumeNoDefault;
01332   return NS_OK;
01333 }
01334 
01335 //-------------------------------------------------------------------------
01336 PRBool nsWindow::DispatchWindowEvent(nsGUIEvent* event)
01337 {
01338   nsEventStatus status;
01339   DispatchEvent(event, status);
01340   return ConvertStatus(status);
01341 }
01342 
01343 PRBool nsWindow::DispatchWindowEvent(nsGUIEvent* event, nsEventStatus &aStatus) {
01344   DispatchEvent(event, aStatus);
01345   return ConvertStatus(aStatus);
01346 }
01347 
01348 //-------------------------------------------------------------------------
01349 //
01350 // Dispatch standard event
01351 //
01352 //-------------------------------------------------------------------------
01353 
01354 PRBool nsWindow::DispatchStandardEvent(PRUint32 aMsg)
01355 {
01356   nsGUIEvent event(PR_TRUE, aMsg, this);
01357   InitEvent(event);
01358 
01359   PRBool result = DispatchWindowEvent(&event);
01360   NS_RELEASE(event.widget);
01361   return result;
01362 }
01363 
01364 //-------------------------------------------------------------------------
01365 //
01366 // Dispatch app command event
01367 //
01368 //-------------------------------------------------------------------------
01369 PRBool nsWindow::DispatchAppCommandEvent(PRUint32 aEventCommand)
01370 {
01371   nsAppCommandEvent event(PR_TRUE, NS_APPCOMMAND_START, this);
01372 
01373   InitEvent(event);
01374   event.appCommand = NS_APPCOMMAND_START + aEventCommand;
01375 
01376   DispatchWindowEvent(&event);
01377   NS_RELEASE(event.widget);
01378 
01379   return NS_OK;
01380 }
01381 
01382 //-------------------------------------------------------------------------
01383 NS_IMETHODIMP nsWindow::CaptureRollupEvents(nsIRollupListener * aListener,
01384                                             PRBool aDoCapture,
01385                                             PRBool aConsumeRollupEvent)
01386 {
01387   if (aDoCapture) {
01388     /* we haven't bothered carrying a weak reference to gRollupWidget because
01389        we believe lifespan is properly scoped. this next assertion helps
01390        assure that remains true. */
01391     NS_ASSERTION(!gRollupWidget, "rollup widget reassigned before release");
01392     gRollupConsumeRollupEvent = aConsumeRollupEvent;
01393     NS_IF_RELEASE(gRollupListener);
01394     NS_IF_RELEASE(gRollupWidget);
01395     gRollupListener = aListener;
01396     NS_ADDREF(aListener);
01397     gRollupWidget = this;
01398     NS_ADDREF(this);
01399 
01400 #ifndef WINCE
01401     if (!gMsgFilterHook && !gCallProcHook && !gCallMouseHook) {
01402       RegisterSpecialDropdownHooks();
01403     }
01404 #endif
01405     gProcessHook = PR_TRUE;
01406 
01407   } else {
01408     NS_IF_RELEASE(gRollupListener);
01409     NS_IF_RELEASE(gRollupWidget);
01410     
01411     gProcessHook = PR_FALSE;
01412 #ifndef WINCE
01413     UnregisterSpecialDropdownHooks();
01414 #endif
01415   }
01416   return NS_OK;
01417 }
01418 
01419 PRBool
01420 nsWindow::EventIsInsideWindow(UINT Msg, nsWindow* aWindow)
01421 {
01422   RECT r;
01423 
01424   if (Msg == WM_ACTIVATE)
01425 #ifndef WINCE
01426     // don't care about activation/deactivation
01427     return PR_FALSE;
01428 #else
01429     // but on Windows CE we do care about
01430     // activation/deactivation because there doesn't exist
01431     // cancelable Mouse Activation events
01432     return TRUE;
01433 #endif
01434 
01435   ::GetWindowRect(aWindow->mWnd, &r);
01436   DWORD pos = ::GetMessagePos();
01437   POINT mp;
01438   mp.x = GET_X_LPARAM(pos);
01439   mp.y = GET_Y_LPARAM(pos);
01440 
01441   // was the event inside this window?
01442   return (PRBool) PtInRect(&r, mp);
01443 }
01444 
01445 static char sPropName[40] = "";
01446 static char* GetNSWindowPropName() {
01447   if (!*sPropName)
01448   {
01449     _snprintf(sPropName, 39, "MozillansIWidgetPtr%p", _getpid());
01450     sPropName[39] = '\0';
01451   }
01452   return sPropName;
01453 }
01454 
01455 nsWindow * nsWindow::GetNSWindowPtr(HWND aWnd) {
01456   return (nsWindow *) ::GetPropA(aWnd, GetNSWindowPropName());
01457 }
01458 
01459 BOOL nsWindow::SetNSWindowPtr(HWND aWnd, nsWindow * ptr) {
01460   if (ptr == NULL) {
01461     ::RemovePropA(aWnd, GetNSWindowPropName());
01462     return TRUE;
01463   } else {
01464     return ::SetPropA(aWnd, GetNSWindowPropName(), (HANDLE)ptr);
01465   }
01466 }
01467 
01468 //-------------------------------------------------------------------------
01469 //
01470 // the nsWindow procedure for all nsWindows in this toolkit
01471 //
01472 //-------------------------------------------------------------------------
01473 LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01474 {
01475   LRESULT popupHandlingResult;
01476   if ( DealWithPopups(hWnd, msg, wParam, lParam, &popupHandlingResult) )
01477     return popupHandlingResult;
01478 
01479   // Get the window which caused the event and ask it to process the message
01480   nsWindow *someWindow = GetNSWindowPtr(hWnd);
01481 
01482   // XXX This fixes 50208 and we are leaving 51174 open to further investigate
01483   // why we are hitting this assert
01484   if (nsnull == someWindow) {
01485     NS_ASSERTION(someWindow, "someWindow is null, cannot call any CallWindowProc");
01486     return nsToolkit::mDefWindowProc(hWnd, msg, wParam, lParam);
01487   }
01488 
01489   // hold on to the window for the life of this method, in case it gets
01490   // deleted during processing. yes, it's a double hack, since someWindow
01491   // is not really an interface.
01492   nsCOMPtr<nsISupports> kungFuDeathGrip;
01493   if (!someWindow->mIsDestroying) // not if we're in the destructor!
01494     kungFuDeathGrip = do_QueryInterface((nsBaseWidget*)someWindow);
01495 
01496   // Re-direct a tab change message destined for its parent window to the
01497   // the actual window which generated the event.
01498   if (msg == WM_NOTIFY) {
01499     LPNMHDR pnmh = (LPNMHDR) lParam;
01500     if (pnmh->code == TCN_SELCHANGE) {
01501       someWindow = GetNSWindowPtr(pnmh->hwndFrom);
01502     }
01503   }
01504 
01505   if (nsnull != someWindow) {
01506     LRESULT retValue;
01507     if (PR_TRUE == someWindow->ProcessMessage(msg, wParam, lParam, &retValue)) {
01508       return retValue;
01509     }
01510   }
01511 
01512 #if defined(STRICT)
01513   return nsToolkit::mCallWindowProc((WNDPROC)someWindow->GetPrevWindowProc(), hWnd,
01514                                     msg, wParam, lParam);
01515 #else
01516   return nsToolkit::mCallWindowProc((FARPROC)someWindow->GetPrevWindowProc(), hWnd,
01517                                     msg, wParam, lParam);
01518 #endif
01519 }
01520 
01521 //
01522 // Default Window procedure for AIMM support.
01523 //
01524 LRESULT CALLBACK nsWindow::DefaultWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01525 {
01526   if (nsToolkit::gAIMMApp)
01527   {
01528     LRESULT lResult;
01529     if (nsToolkit::gAIMMApp->OnDefWindowProc(hWnd, msg, wParam, lParam, &lResult) == S_OK)
01530       return lResult;
01531   }
01532   return nsToolkit::mDefWindowProc(hWnd, msg, wParam, lParam);
01533 }
01534 
01535 static BOOL CALLBACK DummyDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
01536   return FALSE;
01537 }
01538 
01539 //WINOLEAPI oleStatus;
01540 //-------------------------------------------------------------------------
01541 //
01542 // Utility method for implementing both Create(nsIWidget ...) and
01543 // Create(nsNativeWidget...)
01544 //-------------------------------------------------------------------------
01545 
01546 nsresult
01547 nsWindow::StandardWindowCreate(nsIWidget *aParent,
01548                                const nsRect &aRect,
01549                                EVENT_CALLBACK aHandleEventFunction,
01550                                nsIDeviceContext *aContext,
01551                                nsIAppShell *aAppShell,
01552                                nsIToolkit *aToolkit,
01553                                nsWidgetInitData *aInitData,
01554                                nsNativeWidget aNativeParent)
01555 {
01556   nsIWidget *baseParent = aInitData &&
01557                          (aInitData->mWindowType == eWindowType_dialog ||
01558                           aInitData->mWindowType == eWindowType_toplevel ||
01559                           aInitData->mWindowType == eWindowType_invisible) ?
01560                          nsnull : aParent;
01561 
01562   mIsTopWidgetWindow = (nsnull == baseParent);
01563   mBounds.width = aRect.width;
01564   mBounds.height = aRect.height;
01565 
01566   BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
01567              aAppShell, aToolkit, aInitData);
01568 
01569   // Switch to the "main gui thread" if necessary... This method must
01570   // be executed on the "gui thread"...
01571 
01572   nsToolkit* toolkit = (nsToolkit *)mToolkit;
01573   if (toolkit && !toolkit->IsGuiThread()) {
01574     DWORD args[7];
01575     args[0] = (DWORD)aParent;
01576     args[1] = (DWORD)&aRect;
01577     args[2] = (DWORD)aHandleEventFunction;
01578     args[3] = (DWORD)aContext;
01579     args[4] = (DWORD)aAppShell;
01580     args[5] = (DWORD)aToolkit;
01581     args[6] = (DWORD)aInitData;
01582 
01583     if (nsnull != aParent) {
01584       // nsIWidget parent dispatch
01585       MethodInfo info(this, nsWindow::CREATE, 7, args);
01586       toolkit->CallMethod(&info);
01587       return NS_OK;
01588     }
01589     else {
01590       // Native parent dispatch
01591       MethodInfo info(this, nsWindow::CREATE_NATIVE, 5, args);
01592       toolkit->CallMethod(&info);
01593       return NS_OK;
01594     }
01595   }
01596 
01597   HWND parent;
01598   if (nsnull != aParent) { // has a nsIWidget parent
01599     parent = ((aParent) ? (HWND)aParent->GetNativeData(NS_NATIVE_WINDOW) : nsnull);
01600   } else { // has a nsNative parent
01601     parent = (HWND)aNativeParent;
01602   }
01603 
01604   if (nsnull != aInitData) {
01605     SetWindowType(aInitData->mWindowType);
01606     SetBorderStyle(aInitData->mBorderStyle);
01607   }
01608 
01609   mContentType = aInitData ? aInitData->mContentType : eContentTypeInherit;
01610 
01611   DWORD style = WindowStyle();
01612   DWORD extendedStyle = WindowExStyle();
01613 
01614   if (mWindowType == eWindowType_popup) {
01615     NS_ASSERTION(!aParent, "Popups should not be hooked into the nsIWidget hierarchy");
01616     mBorderlessParent = parent;
01617     // Don't set the parent of a popup window.
01618     parent = NULL;
01619   } else if (nsnull != aInitData) {
01620     // See if the caller wants to explictly set clip children and clip siblings
01621     if (aInitData->clipChildren) {
01622       style |= WS_CLIPCHILDREN;
01623     } else {
01624       style &= ~WS_CLIPCHILDREN;
01625     }
01626     if (aInitData->clipSiblings) {
01627       style |= WS_CLIPSIBLINGS;
01628     }
01629   }
01630 
01631   mHas3DBorder = (extendedStyle & WS_EX_CLIENTEDGE) > 0;
01632 
01633   if (mWindowType == eWindowType_dialog) {
01634     struct {
01635       DLGTEMPLATE t;
01636       short noMenu;
01637       short defaultClass;
01638       short title;
01639     } templ;
01640     LONG units = GetDialogBaseUnits();
01641 
01642     templ.t.style = style;
01643     templ.t.dwExtendedStyle = extendedStyle;
01644     templ.t.cdit = 0;
01645     templ.t.x = (aRect.x*4)/LOWORD(units);
01646     templ.t.y = (aRect.y*8)/HIWORD(units);
01647     templ.t.cx = (aRect.width*4 + LOWORD(units) - 1)/LOWORD(units);
01648     templ.t.cy = (GetHeight(aRect.height)*8 + HIWORD(units) - 1)/HIWORD(units);
01649     templ.noMenu = 0;
01650     templ.defaultClass = 0;
01651     templ.title = 0;
01652 
01653     mWnd = ::CreateDialogIndirectParam(nsToolkit::mDllInstance,
01654                                        &templ.t,
01655                                        parent,
01656                                        (DLGPROC)DummyDialogProc,
01657                                        NULL);
01658 
01659   } else {
01660 
01661     mWnd = nsToolkit::mCreateWindowEx(extendedStyle,
01662                                       aInitData && aInitData->mDropShadow ?
01663                                       WindowPopupClassW() : WindowClassW(),
01664                                       L"",
01665                                       style,
01666                                       aRect.x,
01667                                       aRect.y,
01668                                       aRect.width,
01669                                       GetHeight(aRect.height),
01670                                       parent,
01671                                       NULL,
01672                                       nsToolkit::mDllInstance,
01673                                       NULL);
01674   }
01675 
01676   if (!mWnd)
01677     return NS_ERROR_FAILURE;
01678 
01679   /*mNativeDragTarget = new nsNativeDragTarget(this);
01680   if (NULL != mNativeDragTarget) {
01681     mNativeDragTarget->AddRef();
01682     if (S_OK == ::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget,TRUE,FALSE)) {
01683       if (S_OK == ::RegisterDragDrop(mWnd, (LPDROPTARGET)mNativeDragTarget)) {
01684       }
01685     }
01686   }*/
01687 
01688   // call the event callback to notify about creation
01689 
01690   DispatchStandardEvent(NS_CREATE);
01691   SubclassWindow(TRUE);
01692 
01693   if (gTrimOnMinimize == 2 && mWindowType == eWindowType_invisible) {
01694     /* The internal variable set by the config.trim_on_minimize pref
01695        has not yet been initialized, and this is the hidden window
01696        (conveniently created before any visible windows, and after
01697        the profile has been initialized).
01698        
01699        Default config.trim_on_minimize to false, to fix bug 76831
01700        for good.  If anyone complains about this new default, saying
01701        that a Mozilla app hogs too much memory while minimized, they
01702        will have that entire bug tattooed on their backside. */
01703 
01704     gTrimOnMinimize = 0;
01705     nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
01706     if (prefs) {
01707       nsCOMPtr<nsIPrefBranch> prefBranch;
01708       prefs->GetBranch(0, getter_AddRefs(prefBranch));
01709       if (prefBranch) {
01710         PRBool trimOnMinimize;
01711         if (NS_SUCCEEDED(prefBranch->GetBoolPref("config.trim_on_minimize",
01712                                                  &trimOnMinimize))
01713             && trimOnMinimize)
01714           gTrimOnMinimize = 1;
01715 
01716         PRBool switchKeyboardLayout;
01717         if (NS_SUCCEEDED(prefBranch->GetBoolPref("intl.keyboard.per_window_layout",
01718                                                  &switchKeyboardLayout)))
01719           gSwitchKeyboardLayout = switchKeyboardLayout;
01720       }
01721     }
01722   }
01723 #ifdef WINCE
01724   if (mWindowType == eWindowType_dialog || 
01725       mWindowType == eWindowType_toplevel ||
01726       mWindowType == eWindowType_popup )
01727   {  
01728     CreateSoftKeyMenuBar(mWnd);
01729   }
01730 #endif
01731 
01732   return NS_OK;
01733 }
01734 
01735 //-------------------------------------------------------------------------
01736 //
01737 // Create the proper widget
01738 //
01739 //-------------------------------------------------------------------------
01740 NS_METHOD nsWindow::Create(nsIWidget *aParent,
01741                            const nsRect &aRect,
01742                            EVENT_CALLBACK aHandleEventFunction,
01743                            nsIDeviceContext *aContext,
01744                            nsIAppShell *aAppShell,
01745                            nsIToolkit *aToolkit,
01746                            nsWidgetInitData *aInitData)
01747 {
01748   if (aInitData)
01749     mUnicodeWidget = aInitData->mUnicode;
01750   return(StandardWindowCreate(aParent, aRect, aHandleEventFunction,
01751                               aContext, aAppShell, aToolkit, aInitData,
01752                               nsnull));
01753 }
01754 
01755 
01756 //-------------------------------------------------------------------------
01757 //
01758 // create with a native parent
01759 //
01760 //-------------------------------------------------------------------------
01761 
01762 NS_METHOD nsWindow::Create(nsNativeWidget aParent,
01763                            const nsRect &aRect,
01764                            EVENT_CALLBACK aHandleEventFunction,
01765                            nsIDeviceContext *aContext,
01766                            nsIAppShell *aAppShell,
01767                            nsIToolkit *aToolkit,
01768                            nsWidgetInitData *aInitData)
01769 {
01770   if (aInitData)
01771     mUnicodeWidget = aInitData->mUnicode;
01772   return(StandardWindowCreate(nsnull, aRect, aHandleEventFunction,
01773                               aContext, aAppShell, aToolkit, aInitData,
01774                               aParent));
01775 }
01776 
01777 
01778 //-------------------------------------------------------------------------
01779 //
01780 // Close this nsWindow
01781 //
01782 //-------------------------------------------------------------------------
01783 NS_METHOD nsWindow::Destroy()
01784 {
01785   // Switch to the "main gui thread" if necessary... This method must
01786   // be executed on the "gui thread"...
01787   nsToolkit* toolkit = (nsToolkit *)mToolkit;
01788   if (toolkit != nsnull && !toolkit->IsGuiThread()) {
01789     MethodInfo info(this, nsWindow::DESTROY);
01790     toolkit->CallMethod(&info);
01791     return NS_ERROR_FAILURE;
01792   }
01793 
01794   // disconnect from the parent
01795   if (!mIsDestroying) {
01796     nsBaseWidget::Destroy();
01797   }
01798 
01799   // just to be safe. If we're going away and for some reason we're still
01800   // the rollup widget, rollup and turn off capture.
01801   if ( this == gRollupWidget ) {
01802     if ( gRollupListener )
01803       gRollupListener->Rollup();
01804     CaptureRollupEvents(nsnull, PR_FALSE, PR_TRUE);
01805   }
01806 
01807   EnableDragDrop(PR_FALSE);
01808 
01809   // destroy the HWND
01810   if (mWnd) {
01811     // prevent the widget from causing additional events
01812     mEventCallback = nsnull;
01813     if (gAttentionTimerMonitor)
01814       gAttentionTimerMonitor->KillTimer(mWnd);
01815 
01816     HICON icon;
01817     icon = (HICON) nsToolkit::mSendMessage(mWnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM) 0);
01818     if (icon)
01819       ::DestroyIcon(icon);
01820 
01821     icon = (HICON) nsToolkit::mSendMessage(mWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM) 0);
01822     if (icon)
01823       ::DestroyIcon(icon);
01824 
01825 #ifdef MOZ_XUL
01826     if (mIsTranslucent)
01827     {
01828       SetupTranslucentWindowMemoryBitmap(PR_FALSE);
01829 
01830       delete [] mAlphaMask;
01831       mAlphaMask = nsnull;
01832     }
01833 #endif
01834 
01835     VERIFY(::DestroyWindow(mWnd));
01836 
01837     mWnd = NULL;
01838     //our windows can be subclassed by
01839     //others and these nameless, faceless others
01840     //may not let us know about WM_DESTROY. so,
01841     //if OnDestroy() didn't get called, just call
01842     //it now. MMP
01843     if (PR_FALSE == mOnDestroyCalled)
01844       OnDestroy();
01845   }
01846 
01847   return NS_OK;
01848 }
01849 
01850 NS_IMETHODIMP nsWindow::SetParent(nsIWidget *aNewParent)
01851 {
01852   if (aNewParent) {
01853     HWND newParent = (HWND)aNewParent->GetNativeData(NS_NATIVE_WINDOW);
01854     NS_ASSERTION(newParent, "Parent widget has a null native window handle");
01855     ::SetParent(mWnd, newParent);
01856 
01857     return NS_OK;
01858   }
01859   NS_WARNING("Null aNewParent passed to SetParent");
01860   return NS_ERROR_FAILURE;
01861 }
01862 
01863 
01864 //-------------------------------------------------------------------------
01865 //
01866 // Get this nsWindow parent
01867 //
01868 //-------------------------------------------------------------------------
01869 nsIWidget* nsWindow::GetParent(void)
01870 {
01871   return GetParent(PR_TRUE);
01872 }
01873 
01874 nsWindow* nsWindow::GetParent(PRBool aStopOnFirstTopLevel)
01875 {
01876   if (mIsTopWidgetWindow && aStopOnFirstTopLevel) {
01877     // Must use a flag instead of mWindowType to tell if the window is the
01878     // owned by the topmost widget, because a child window can be embedded inside
01879     // a HWND which is not associated with a nsIWidget.
01880     return nsnull;
01881   }
01882   // If this widget has already been destroyed, pretend we have no parent.
01883   // This corresponds to code in Destroy which removes the destroyed
01884   // widget from its parent's child list.
01885   if (mIsDestroying || mOnDestroyCalled)
01886     return nsnull;
01887 
01888   nsWindow* widget = nsnull;
01889   if (mWnd) {
01890     HWND parent = ::GetParent(mWnd);
01891     if (parent) {
01892       widget = GetNSWindowPtr(parent);
01893       if (widget) {
01894         // If the widget is in the process of being destroyed then
01895         // do NOT return it
01896         if (widget->mIsDestroying) {
01897           widget = nsnull;
01898         } else {
01899           NS_ADDREF(widget);
01900         }
01901       }
01902     }
01903   }
01904 
01905   return widget;
01906 }
01907 
01908 
01909 //-------------------------------------------------------------------------
01910 //
01911 // Hide or show this component
01912 //
01913 //-------------------------------------------------------------------------
01914 #ifndef WINCE
01915 PRBool gWindowsVisible;
01916 
01917 static BOOL CALLBACK gEnumWindowsProc(HWND hwnd, LPARAM lParam)
01918 {
01919   DWORD pid;
01920   ::GetWindowThreadProcessId(hwnd, &pid);
01921   if (pid == _getpid() && ::IsWindowVisible(hwnd))
01922   {
01923     gWindowsVisible = PR_TRUE;
01924     return FALSE;
01925   }
01926   return TRUE;
01927 }
01928 #endif
01929 
01930 PRBool nsWindow::CanTakeFocus()
01931 {
01932 #ifndef WINCE
01933   gWindowsVisible = PR_FALSE;
01934   EnumWindows(gEnumWindowsProc, 0);
01935   if (!gWindowsVisible) {
01936     return PR_TRUE;
01937   } else {
01938     HWND fgWnd = ::GetForegroundWindow();
01939     if (!fgWnd) {
01940       return PR_TRUE;
01941     }
01942     DWORD pid;
01943     GetWindowThreadProcessId(fgWnd, &pid);
01944     if (pid == _getpid()) {
01945       return PR_TRUE;
01946     }
01947   }
01948   return PR_FALSE;
01949 #else
01950   return PR_TRUE;
01951 #endif
01952 }
01953 
01954 NS_METHOD nsWindow::Show(PRBool bState)
01955 {
01956   if (mWnd) {
01957     if (bState) {
01958       if (!mIsVisible && mWindowType == eWindowType_toplevel) {
01959         switch (mSizeMode) {
01960           case nsSizeMode_Maximized :
01961             ::ShowWindow(mWnd, SW_SHOWMAXIMIZED);
01962             break;
01963           case nsSizeMode_Minimized :
01964 #ifndef WINCE
01965             ::ShowWindow(mWnd, SW_SHOWMINIMIZED);
01966 #endif
01967             break;
01968           default:
01969             if (CanTakeFocus()) {
01970               ::ShowWindow(mWnd, SW_SHOWNORMAL);
01971             } else {
01972               // Place the window behind the foreground window
01973               // (as long as it is not topmost)
01974               HWND wndAfter = ::GetForegroundWindow();
01975               if (!wndAfter)
01976                 wndAfter = HWND_BOTTOM;
01977               else if (GetWindowLong(wndAfter, GWL_EXSTYLE) & WS_EX_TOPMOST)
01978                 wndAfter = HWND_TOP;
01979               ::SetWindowPos(mWnd, wndAfter, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | 
01980                              SWP_NOMOVE | SWP_NOACTIVATE);
01981               GetAttention(2);
01982             }
01983         }
01984       } else {
01985         DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW;
01986         if (mIsVisible)
01987           flags |= SWP_NOZORDER;
01988 
01989         if (mWindowType == eWindowType_popup) {
01990           // ensure popups are the topmost of the TOPMOST
01991           // layer. Remember not to set the SWP_NOZORDER
01992           // flag as that might allow the taskbar to overlap
01993           // the popup.
01994 #ifndef WINCE
01995           // Make urlbar context menus clickable my ensuring
01996           // that the popup isn't activated.
01997           flags |= SWP_NOACTIVATE;
01998 #endif
01999           ::SetWindowPos(mWnd, HWND_TOPMOST, 0, 0, 0, 0, flags);
02000         } else {
02001           ::SetWindowPos(mWnd, HWND_TOP, 0, 0, 0, 0, flags);
02002         }
02003       }
02004     } else {
02005       if (mWindowType != eWindowType_dialog) {
02006         ::ShowWindow(mWnd, SW_HIDE);
02007       } else {
02008         ::SetWindowPos(mWnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
02009                        SWP_NOZORDER | SWP_NOACTIVATE);
02010       }
02011     }
02012   }
02013   mIsVisible = bState;
02014 
02015   return NS_OK;
02016 }
02017 
02018 //-------------------------------------------------------------------------
02019 //
02020 // Return PR_TRUE if the whether the component is visible, PR_FALSE otherwise
02021 //
02022 //-------------------------------------------------------------------------
02023 NS_METHOD nsWindow::IsVisible(PRBool & bState)
02024 {
02025   bState = mIsVisible;
02026   return NS_OK;
02027 }
02028 
02029 //-------------------------------------------------------------------------
02030 //
02031 // Position the window behind the given window
02032 //
02033 //-------------------------------------------------------------------------
02034 NS_METHOD nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
02035                                 nsIWidget *aWidget, PRBool aActivate)
02036 {
02037   HWND behind = HWND_TOP;
02038   if (aPlacement == eZPlacementBottom)
02039     behind = HWND_BOTTOM;
02040   else if (aPlacement == eZPlacementBelow && aWidget)
02041     behind = (HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW);
02042   UINT flags = SWP_NOMOVE | SWP_NOREPOSITION | SWP_NOSIZE;
02043   if (!aActivate)
02044     flags |= SWP_NOACTIVATE;
02045 
02046   if (!CanTakeFocus() && behind == HWND_TOP)
02047   {
02048     // Can't place the window to top so place it behind the foreground window
02049     // (as long as it is not topmost)
02050     HWND wndAfter = ::GetForegroundWindow();
02051     if (!wndAfter)
02052       behind = HWND_BOTTOM;
02053     else if (!(GetWindowLong(wndAfter, GWL_EXSTYLE) & WS_EX_TOPMOST))
02054       behind = wndAfter;
02055     flags |= SWP_NOACTIVATE;
02056   }
02057 
02058   ::SetWindowPos(mWnd, behind, 0, 0, 0, 0, flags);
02059   return NS_OK;
02060 }
02061 
02062 //-------------------------------------------------------------------------
02063 //
02064 // Maximize, minimize or restore the window.
02065 //
02066 //-------------------------------------------------------------------------
02067 NS_IMETHODIMP nsWindow::SetSizeMode(PRInt32 aMode) {
02068 
02069   nsresult rv;
02070 
02071   // Let's not try and do anything if we're already in that state.
02072   // (This is needed to prevent problems when calling window.minimize(), which
02073   // calls us directly, and then the OS triggers another call to us.)
02074   PRInt32 oldMode;
02075   GetSizeMode(&oldMode);
02076   if (aMode == oldMode)
02077     return NS_OK;
02078 
02079   // save the requested state
02080   rv = nsBaseWidget::SetSizeMode(aMode);
02081   if (NS_SUCCEEDED(rv) && mIsVisible) {
02082     int mode;
02083 
02084     switch (aMode) {
02085       case nsSizeMode_Maximized :
02086         mode = SW_MAXIMIZE;
02087         break;
02088       case nsSizeMode_Minimized :
02089 #ifndef WINCE
02090         mode = gTrimOnMinimize ? SW_MINIMIZE : SW_SHOWMINIMIZED;
02091         if (!gTrimOnMinimize) {
02092           // Find the next window that is visible and not minimized.
02093           HWND hwndBelow = ::GetNextWindow(mWnd, GW_HWNDNEXT);
02094           while (hwndBelow && (!::IsWindowVisible(hwndBelow) ||
02095                                ::IsIconic(hwndBelow))) {
02096             hwndBelow = ::GetNextWindow(hwndBelow, GW_HWNDNEXT);
02097           }
02098 
02099           // Push ourselves to the bottom of the stack, then activate the
02100           // next window.
02101           ::SetWindowPos(mWnd, HWND_BOTTOM, 0, 0, 0, 0,
02102                          SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
02103           if (hwndBelow)
02104             ::SetForegroundWindow(hwndBelow);
02105         }
02106 #endif
02107         break;
02108       default :
02109         mode = SW_RESTORE;
02110     }
02111     ::ShowWindow(mWnd, mode);
02112   }
02113   return rv;
02114 }
02115 
02116 //-------------------------------------------------------------------------
02117 // Return PR_TRUE in aForWindow if the given event should be processed
02118 // assuming this is a modal window.
02119 //-------------------------------------------------------------------------
02120 NS_METHOD nsWindow::ModalEventFilter(PRBool aRealEvent, void *aEvent,
02121                                      PRBool *aForWindow)
02122 {
02123   if (!aRealEvent) {
02124     *aForWindow = PR_FALSE;
02125     return NS_OK;
02126   }
02127 #if 0
02128   // this version actually works, but turns out to be unnecessary
02129   // if we use the OS properly.
02130   MSG *msg = (MSG *) aEvent;
02131 
02132   switch (msg->message) {
02133     case WM_MOUSEMOVE:
02134     case WM_LBUTTONDOWN:
02135     case WM_LBUTTONUP:
02136     case WM_LBUTTONDBLCLK:
02137     case WM_MBUTTONDOWN:
02138     case WM_MBUTTONUP:
02139     case WM_MBUTTONDBLCLK:
02140     case WM_RBUTTONDOWN:
02141     case WM_RBUTTONUP:
02142     case WM_RBUTTONDBLCLK:
02143     {
02144       PRBool acceptEvent;
02145 
02146       // is the event within our window?
02147       HWND rollupWindow = NULL;
02148       HWND msgWindow = GetTopLevelHWND(msg->hwnd);
02149       if (gRollupWidget)
02150         rollupWindow = (HWND)gRollupWidget->GetNativeData(NS_NATIVE_WINDOW);
02151       acceptEvent = msgWindow && (msgWindow == mWnd || msgWindow == rollupWindow) ?
02152                     PR_TRUE : PR_FALSE;
02153 
02154       // if not, accept events for any window that hasn't been disabled.
02155       if (!acceptEvent) {
02156         LONG proc = nsToolkit::mGetWindowLong(msgWindow, GWL_WNDPROC);
02157         if (proc == (LONG)&nsWindow::WindowProc) {
02158           nsWindow *msgWin = GetNSWindowPtr(msgWindow);
02159           msgWin->IsEnabled(&acceptEvent);
02160         }
02161       }
02162     }
02163     break;
02164 
02165     default:
02166       *aForWindow = PR_TRUE;
02167   }
02168 #else
02169   *aForWindow = PR_TRUE;
02170 #endif
02171 
02172   return NS_OK;
02173 }
02174 
02175 //-------------------------------------------------------------------------
02176 //
02177 // Constrain a potential move to fit onscreen
02178 //
02179 //-------------------------------------------------------------------------
02180 NS_METHOD nsWindow::ConstrainPosition(PRBool aAllowSlop,
02181                                       PRInt32 *aX, PRInt32 *aY)
02182 {
02183   if (!mIsTopWidgetWindow) // only a problem for top-level windows
02184     return NS_OK;
02185 
02186   PRBool doConstrain = PR_FALSE; // whether we have enough info to do anything
02187 
02188   /* get our playing field. use the current screen, or failing that
02189     for any reason, use device caps for the default screen. */
02190   RECT screenRect;
02191 
02192   nsCOMPtr<nsIScreenManager> screenmgr = do_GetService(sScreenManagerContractID);
02193   if (screenmgr) {
02194     nsCOMPtr<nsIScreen> screen;
02195     PRInt32 left, top, width, height;
02196 
02197     // zero size rects confuse the screen manager
02198     width = mBounds.width > 0 ? mBounds.width : 1;
02199     height = mBounds.height > 0 ? mBounds.height : 1;
02200     screenmgr->ScreenForRect(*aX, *aY, width, height,
02201                              getter_AddRefs(screen));
02202     if (screen) {
02203       screen->GetAvailRect(&left, &top, &width, &height);
02204       screenRect.left = left;
02205       screenRect.right = left+width;
02206       screenRect.top = top;
02207       screenRect.bottom = top+height;
02208       doConstrain = PR_TRUE;
02209     }
02210   } else {
02211     if (mWnd) {
02212       HDC dc = ::GetDC(mWnd);
02213       if (dc) {
02214         if (::GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
02215           ::SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
02216           doConstrain = PR_TRUE;
02217         }
02218         ::ReleaseDC(mWnd, dc);
02219       }
02220     }
02221   }
02222 
02223   if (aAllowSlop) {
02224     if (*aX < screenRect.left - mBounds.width + kWindowPositionSlop)
02225       *aX = screenRect.left - mBounds.width + kWindowPositionSlop;
02226     else if (*aX >= screenRect.right - kWindowPositionSlop)
02227       *aX = screenRect.right - kWindowPositionSlop;
02228 
02229     if (*aY < screenRect.top - mBounds.height + kWindowPositionSlop)
02230       *aY = screenRect.top - mBounds.height + kWindowPositionSlop;
02231     else if (*aY >= screenRect.bottom - kWindowPositionSlop)
02232       *aY = screenRect.bottom - kWindowPositionSlop;
02233 
02234   } else {
02235 
02236     if (*aX < screenRect.left)
02237       *aX = screenRect.left;
02238     else if (*aX >= screenRect.right - mBounds.width)
02239       *aX = screenRect.right - mBounds.width;
02240 
02241     if (*aY < screenRect.top)
02242       *aY = screenRect.top;
02243     else if (*aY >= screenRect.bottom - mBounds.height)
02244       *aY = screenRect.bottom - mBounds.height;
02245   }
02246 
02247   return NS_OK;
02248 }
02249 
02250 //-------------------------------------------------------------------------
02251 //
02252 // Move this component
02253 //
02254 //-------------------------------------------------------------------------
02255 NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY)
02256 {
02257   // Check to see if window needs to be moved first
02258   // to avoid a costly call to SetWindowPos. This check
02259   // can not be moved to the calling code in nsView, because
02260   // some platforms do not position child windows correctly
02261 
02262   // Only perform this check for non-popup windows, since the positioning can
02263   // in fact change even when the x/y do not.  We always need to perform the
02264   // check. See bug #97805 for details.
02265   if (mWindowType != eWindowType_popup && (mBounds.x == aX) && (mBounds.y == aY))
02266   {
02267     // Nothing to do, since it is already positioned correctly.
02268     return NS_OK;
02269   }
02270 
02271   mBounds.x = aX;
02272   mBounds.y = aY;
02273 
02274   if (mWnd) {
02275 #ifdef DEBUG
02276     // complain if a window is moved offscreen (legal, but potentially worrisome)
02277     if (mIsTopWidgetWindow) { // only a problem for top-level windows
02278       // Make sure this window is actually on the screen before we move it
02279       // XXX: Needs multiple monitor support
02280       HDC dc = ::GetDC(mWnd);
02281       if (dc) {
02282         if (::GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
02283           RECT workArea;
02284           ::SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
02285           // no annoying assertions. just mention the issue.
02286           if (aX < 0 || aX >= workArea.right || aY < 0 || aY >= workArea.bottom)
02287             printf("window moved to offscreen position\n");
02288         }
02289       ::ReleaseDC(mWnd, dc);
02290       }
02291     }
02292 #endif
02293 
02294     nsIWidget *par = GetParent();
02295     HDWP      deferrer = NULL;
02296 
02297     if (nsnull != par) {
02298       deferrer = ((nsWindow *)par)->mDeferredPositioner;
02299     }
02300 
02301     if (NULL != deferrer) {
02302       VERIFY(((nsWindow *)par)->mDeferredPositioner = ::DeferWindowPos(deferrer,
02303                             mWnd, NULL, aX, aY, 0, 0,
02304                             SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE));
02305     }
02306     else {
02307       VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, 0, 0,
02308                             SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE));
02309     }
02310 
02311     NS_IF_RELEASE(par);
02312   }
02313   return NS_OK;
02314 }
02315 
02316 //-------------------------------------------------------------------------
02317 //
02318 // Resize this component
02319 //
02320 //-------------------------------------------------------------------------
02321 NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
02322 {
02323   NS_ASSERTION((aWidth >=0 ) , "Negative width passed to nsWindow::Resize");
02324   NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
02325 
02326 #ifdef MOZ_XUL
02327   if (mIsTranslucent)
02328     ResizeTranslucentWindow(aWidth, aHeight);
02329 #endif
02330 
02331   // Set cached value for lightweight and printing
02332   mBounds.width  = aWidth;
02333   mBounds.height = aHeight;
02334 
02335   if (mWnd) {
02336     nsIWidget *par = GetParent();
02337     HDWP      deferrer = NULL;
02338 
02339     if (nsnull != par) {
02340       deferrer = ((nsWindow *)par)->mDeferredPositioner;
02341     }
02342 
02343     UINT  flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE;
02344 #ifndef WINCE
02345     if (!aRepaint) {
02346       flags |= SWP_NOREDRAW;
02347     }
02348 #endif
02349 
02350     if (NULL != deferrer) {
02351       VERIFY(((nsWindow *)par)->mDeferredPositioner = ::DeferWindowPos(deferrer,
02352                             mWnd, NULL, 0, 0, aWidth, GetHeight(aHeight), flags));
02353     }
02354     else {
02355       VERIFY(::SetWindowPos(mWnd, NULL, 0, 0, aWidth, GetHeight(aHeight), flags));
02356     }
02357 
02358     NS_IF_RELEASE(par);
02359   }
02360 
02361   if (aRepaint)
02362     Invalidate(PR_FALSE);
02363 
02364   return NS_OK;
02365 }
02366 
02367 
02368 //-------------------------------------------------------------------------
02369 //
02370 // Resize this component
02371 //
02372 //-------------------------------------------------------------------------
02373 NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
02374 {
02375   NS_ASSERTION((aWidth >=0 ),  "Negative width passed to nsWindow::Resize");
02376   NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
02377 
02378 #ifdef MOZ_XUL
02379   if (mIsTranslucent)
02380     ResizeTranslucentWindow(aWidth, aHeight);
02381 #endif
02382 
02383   // Set cached value for lightweight and printing
02384   mBounds.x      = aX;
02385   mBounds.y      = aY;
02386   mBounds.width  = aWidth;
02387   mBounds.height = aHeight;
02388 
02389   if (mWnd) {
02390     nsIWidget *par = GetParent();
02391     HDWP      deferrer = NULL;
02392 
02393     if (nsnull != par) {
02394       deferrer = ((nsWindow *)par)->mDeferredPositioner;
02395     }
02396 
02397     UINT  flags = SWP_NOZORDER | SWP_NOACTIVATE;
02398 #ifndef WINCE
02399     if (!aRepaint) {
02400       flags |= SWP_NOREDRAW;
02401     }
02402 #endif
02403     if (NULL != deferrer) {
02404       VERIFY(((nsWindow *)par)->mDeferredPositioner = ::DeferWindowPos(deferrer,
02405                             mWnd, NULL, aX, aY, aWidth, GetHeight(aHeight), flags));
02406     }
02407     else {
02408       VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, aWidth, GetHeight(aHeight), flags));
02409     }
02410 
02411     NS_IF_RELEASE(par);
02412   }
02413 
02414   if (aRepaint)
02415     Invalidate(PR_FALSE);
02416 
02417   return NS_OK;
02418 }
02419 
02420 
02421 //-------------------------------------------------------------------------
02422 //
02423 // Enable/disable this component
02424 //
02425 //-------------------------------------------------------------------------
02426 NS_METHOD nsWindow::Enable(PRBool bState)
02427 {
02428   if (mWnd) {
02429     ::EnableWindow(mWnd, bState);
02430   }
02431   return NS_OK;
02432 }
02433 
02434 
02435 NS_METHOD nsWindow::IsEnabled(PRBool *aState)
02436 {
02437   NS_ENSURE_ARG_POINTER(aState);
02438   *aState = !mWnd || ::IsWindowEnabled(mWnd);
02439   return NS_OK;
02440 }
02441 
02442 
02443 //-------------------------------------------------------------------------
02444 //
02445 // Give the focus to this component
02446 //
02447 //-------------------------------------------------------------------------
02448 NS_METHOD nsWindow::SetFocus(PRBool aRaise)
02449 {
02450   //
02451   // Switch to the "main gui thread" if necessary... This method must
02452   // be executed on the "gui thread"...
02453   //
02454   nsToolkit* toolkit = (nsToolkit *)mToolkit;
02455   NS_ASSERTION(toolkit != nsnull, "This should never be null!"); // Bug 57044
02456   if (toolkit != nsnull && !toolkit->IsGuiThread()) {
02457     MethodInfo info(this, nsWindow::SET_FOCUS);
02458     toolkit->CallMethod(&info);
02459     return NS_ERROR_FAILURE;
02460   }
02461 
02462   if (mWnd) {
02463     // Uniconify, if necessary
02464     HWND toplevelWnd = GetTopLevelHWND(mWnd);
02465     if (::IsIconic(toplevelWnd))
02466       ::ShowWindow(toplevelWnd, SW_RESTORE);
02467     ::SetFocus(mWnd);
02468 
02469   }
02470   return NS_OK;
02471 }
02472 
02473 
02474 //-------------------------------------------------------------------------
02475 //
02476 // Get this component dimension
02477 //
02478 //-------------------------------------------------------------------------
02479 NS_METHOD nsWindow::GetBounds(nsRect &aRect)
02480 {
02481   if (mWnd) {
02482     RECT r;
02483     VERIFY(::GetWindowRect(mWnd, &r));
02484 
02485     // assign size
02486     aRect.width  = r.right - r.left;
02487     aRect.height = r.bottom - r.top;
02488 
02489     // convert coordinates if parent exists
02490     HWND parent = ::GetParent(mWnd);
02491     if (parent) {
02492       RECT pr;
02493       VERIFY(::GetWindowRect(parent, &pr));
02494       r.left -= pr.left;
02495       r.top  -= pr.top;
02496     }
02497     aRect.x = r.left;
02498     aRect.y = r.top;
02499   } else {
02500     aRect = mBounds;
02501   }
02502 
02503   return NS_OK;
02504 }
02505 
02506 //-------------------------------------------------------------------------
02507 //
02508 // Get this component dimension
02509 //
02510 //-------------------------------------------------------------------------
02511 NS_METHOD nsWindow::GetClientBounds(nsRect &aRect)
02512 {
02513   if (mWnd) {
02514     RECT r;
02515     VERIFY(::GetClientRect(mWnd, &r));
02516 
02517     // assign size
02518     aRect.x = 0;
02519     aRect.y = 0;
02520     aRect.width  = r.right - r.left;
02521     aRect.height = r.bottom - r.top;
02522 
02523   } else {
02524     aRect.SetRect(0,0,0,0);
02525   }
02526   return NS_OK;
02527 }
02528 
02529 //get the bounds, but don't take into account the client size
02530 
02531 void nsWindow::GetNonClientBounds(nsRect &aRect)
02532 {
02533   if (mWnd) {
02534     RECT r;
02535     VERIFY(::GetWindowRect(mWnd, &r));
02536 
02537     // assign size
02538     aRect.width = r.right - r.left;
02539     aRect.height = r.bottom - r.top;
02540 
02541     // convert coordinates if parent exists
02542     HWND parent = ::GetParent(mWnd);
02543     if (parent) {
02544       RECT pr;
02545       VERIFY(::GetWindowRect(parent, &pr));
02546       r.left -= pr.left;
02547       r.top -= pr.top;
02548     }
02549     aRect.x = r.left;
02550     aRect.y = r.top;
02551   } else {
02552     aRect.SetRect(0,0,0,0);
02553   }
02554 }
02555 
02556 // like GetBounds, but don't offset by the parent
02557 NS_METHOD nsWindow::GetScreenBounds(nsRect &aRect)
02558 {
02559   if (mWnd) {
02560     RECT r;
02561     VERIFY(::GetWindowRect(mWnd, &r));
02562 
02563     aRect.width  = r.right - r.left;
02564     aRect.height = r.bottom - r.top;
02565     aRect.x = r.left;
02566     aRect.y = r.top;
02567   } else
02568     aRect = mBounds;
02569 
02570   return NS_OK;
02571 }
02572 
02573 //-------------------------------------------------------------------------
02574 //
02575 // Set the background color
02576 //
02577 //-------------------------------------------------------------------------
02578 NS_METHOD nsWindow::SetBackgroundColor(const nscolor &aColor)
02579 {
02580   nsBaseWidget::SetBackgroundColor(aColor);
02581 
02582   if (mBrush)
02583     ::DeleteObject(mBrush);
02584 
02585   mBrush = ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground));
02586   if (mWnd != NULL) {
02587     SetClassLong(mWnd, GCL_HBRBACKGROUND, (LONG)mBrush);
02588   }
02589   return NS_OK;
02590 }
02591 
02592 
02593 //-------------------------------------------------------------------------
02594 //
02595 // Get this component font
02596 //
02597 //-------------------------------------------------------------------------
02598 nsIFontMetrics* nsWindow::GetFont(void)
02599 {
02600   NS_NOTYETIMPLEMENTED("GetFont not yet implemented"); // to be implemented
02601   return NULL;
02602 }
02603 
02604 
02605 //-------------------------------------------------------------------------
02606 //
02607 // Set this component font
02608 //
02609 //-------------------------------------------------------------------------
02610 NS_METHOD nsWindow::SetFont(const nsFont &aFont)
02611 {
02612   // Cache Font for owner draw
02613   if (mFont == nsnull) {
02614     mFont = new nsFont(aFont);
02615   } else {
02616     *mFont  = aFont;
02617   }
02618 
02619   // Bail out if there is no context
02620   if (nsnull == mContext) {
02621     return NS_ERROR_FAILURE;
02622   }
02623 
02624   nsIFontMetrics* metrics;
02625   mContext->GetMetricsFor(aFont, metrics);
02626   nsFontHandle  fontHandle;
02627   metrics->GetFontHandle(fontHandle);
02628   HFONT hfont = (HFONT)fontHandle;
02629 
02630   // Draw in the new font
02631   nsToolkit::mSendMessage(mWnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)0);
02632   NS_RELEASE(metrics);
02633 
02634   return NS_OK;
02635 }
02636 
02637 
02638 //-------------------------------------------------------------------------
02639 //
02640 // Set this component cursor
02641 //
02642 //-------------------------------------------------------------------------
02643 
02644 NS_METHOD nsWindow::SetCursor(nsCursor aCursor)
02645 {
02646   // Only change cursor if it's changing
02647 
02648   //XXX mCursor isn't always right.  Scrollbars and others change it, too.
02649   //XXX If we want this optimization we need a better way to do it.
02650   //if (aCursor != mCursor) {
02651   HCURSOR newCursor = NULL;
02652 
02653   switch (aCursor) {
02654     case eCursor_select:
02655       newCursor = ::LoadCursor(NULL, IDC_IBEAM);
02656       break;
02657 
02658     case eCursor_wait:
02659       newCursor = ::LoadCursor(NULL, IDC_WAIT);
02660       break;
02661 
02662     case eCursor_hyperlink:
02663     {
02664       newCursor = ::LoadCursor(NULL, IDC_HAND);
02665       if (!newCursor) {
02666         newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_SELECTANCHOR));
02667       }
02668       break;
02669     }
02670 
02671     case eCursor_standard:
02672       newCursor = ::LoadCursor(NULL, IDC_ARROW);
02673       break;
02674 
02675     case eCursor_n_resize:
02676     case eCursor_s_resize:
02677       newCursor = ::LoadCursor(NULL, IDC_SIZENS);
02678       break;
02679 
02680     case eCursor_w_resize:
02681     case eCursor_e_resize:
02682       newCursor = ::LoadCursor(NULL, IDC_SIZEWE);
02683       break;
02684 
02685     case eCursor_nw_resize:
02686     case eCursor_se_resize:
02687       newCursor = ::LoadCursor(NULL, IDC_SIZENWSE);
02688       break;
02689 
02690     case eCursor_ne_resize:
02691     case eCursor_sw_resize:
02692       newCursor = ::LoadCursor(NULL, IDC_SIZENESW);
02693       break;
02694 
02695     case eCursor_crosshair:
02696       newCursor = ::LoadCursor(NULL, IDC_CROSS);
02697       break;
02698 
02699     case eCursor_move:
02700       newCursor = ::LoadCursor(NULL, IDC_SIZEALL);
02701       break;
02702 
02703     case eCursor_help:
02704       newCursor = ::LoadCursor(NULL, IDC_HELP);
02705       break;
02706 
02707     case eCursor_copy: // CSS3
02708       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_COPY));
02709       break;
02710 
02711     case eCursor_alias:
02712       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ALIAS));
02713       break;
02714 
02715     case eCursor_cell:
02716       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_CELL));
02717       break;
02718 
02719     case eCursor_grab:
02720       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_GRAB));
02721       break;
02722 
02723     case eCursor_grabbing:
02724       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_GRABBING));
02725       break;
02726 
02727     case eCursor_spinning:
02728       newCursor = ::LoadCursor(NULL, IDC_APPSTARTING);
02729       break;
02730 
02731     case eCursor_context_menu:
02732       // XXX this CSS3 cursor needs to be implemented
02733       break;
02734 
02735     case eCursor_zoom_in:
02736       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ZOOMIN));
02737       break;
02738 
02739     case eCursor_zoom_out:
02740       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ZOOMOUT));
02741       break;
02742 
02743     case eCursor_not_allowed:
02744     case eCursor_no_drop:
02745       newCursor = ::LoadCursor(NULL, IDC_NO);
02746       break;
02747 
02748     case eCursor_col_resize:
02749       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_COLRESIZE));
02750       break;
02751 
02752     case eCursor_row_resize:
02753       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_ROWRESIZE));
02754       break;
02755 
02756     case eCursor_vertical_text:
02757       newCursor = ::LoadCursor(nsToolkit::mDllInstance, MAKEINTRESOURCE(IDC_VERTICALTEXT));
02758       break;
02759 
02760     case eCursor_all_scroll:
02761       // XXX not 100% appropriate perhaps
02762       newCursor = ::LoadCursor(NULL, IDC_SIZEALL);
02763       break;
02764 
02765     case eCursor_nesw_resize:
02766       newCursor = ::LoadCursor(NULL, IDC_SIZENESW);
02767       break;
02768 
02769     case eCursor_nwse_resize:
02770       newCursor = ::LoadCursor(NULL, IDC_SIZENWSE);
02771       break;
02772 
02773     case eCursor_ns_resize:
02774       newCursor = ::LoadCursor(NULL, IDC_SIZENS);
02775       break;
02776 
02777     case eCursor_ew_resize:
02778       newCursor = ::LoadCursor(NULL, IDC_SIZEWE);
02779       break;
02780 
02781     default:
02782       NS_ERROR("Invalid cursor type");
02783       break;
02784   }
02785 
02786   if (NULL != newCursor) {
02787     mCursor = aCursor;
02788     HCURSOR oldCursor = ::SetCursor(newCursor);
02789     
02790     if (gHCursor == oldCursor) {
02791       NS_IF_RELEASE(gCursorImgContainer);
02792       if (gHCursor != NULL)
02793         ::DestroyIcon(gHCursor);
02794       gHCursor = NULL;
02795     }
02796   }
02797   //}
02798   return NS_OK;
02799 }
02800 
02801 // static
02802 PRUint8* nsWindow::Data8BitTo1Bit(PRUint8* aAlphaData,
02803                                   PRUint32 aAlphaBytesPerRow,
02804                                   PRUint32 aWidth, PRUint32 aHeight)
02805 {
02806   // We need (aWidth + 7) / 8 bytes plus zero-padding up to a multiple of
02807   // 4 bytes for each row (HBITMAP requirement). Bug 353553.
02808   PRUint32 outBpr = ((aWidth + 31) / 8) & ~3;
02809   
02810   PRUint8* outData = new PRUint8[outBpr * aHeight];
02811   if (!outData)
02812     return NULL;
02813 
02814   PRUint8 *outRow = outData,
02815           *alphaRow = aAlphaData;
02816 
02817   for (PRUint32 curRow = 0; curRow < aHeight; curRow++) {
02818     PRUint8 *arow = alphaRow;
02819     PRUint8 *nextOutRow = outRow + outBpr;
02820     PRUint8 alphaPixels = 0;
02821     PRUint8 offset = 7;
02822 
02823     for (PRUint32 curCol = 0; curCol < aWidth; curCol++) {
02824       if (*alphaRow++ > 0)
02825         alphaPixels |= (1 << offset);
02826         
02827       if (offset == 0) {
02828         *outRow++ = alphaPixels;
02829         offset = 7;
02830         alphaPixels = 0;
02831       } else {
02832         offset--;
02833       }
02834     }
02835     if (offset != 7)
02836       *outRow++ = alphaPixels;
02837 
02838     alphaRow = arow + aAlphaBytesPerRow;
02839     while (outRow != nextOutRow)
02840       *outRow++ = 0; // padding
02841   }
02842 
02843   return outData;
02844 }
02845 
02846 // static
02847 PRUint8* nsWindow::DataToAData(PRUint8* aImageData, PRUint32 aImageBytesPerRow,
02848                                PRUint8* aAlphaData, PRUint32 aAlphaBytesPerRow,
02849                                PRUint32 aWidth, PRUint32 aHeight)
02850 {
02851   // We will have 32 bpp, so bytes per row will be 4 * w
02852   PRUint32 outBpr = aWidth * 4;
02853 
02854   // Avoid overflows
02855   if (aWidth > 0xfff || aHeight > 0xfff)
02856     return NULL;
02857 
02858   PRUint8* outData = new PRUint8[outBpr * aHeight];
02859   if (!outData)
02860     return NULL;
02861 
02862   PRUint8 *outRow = outData,
02863           *imageRow = aImageData,
02864           *alphaRow = aAlphaData;
02865   for (PRUint32 curRow = 0; curRow < aHeight; curRow++) {
02866     PRUint8 *irow = imageRow, *arow = alphaRow;
02867     for (PRUint32 curCol = 0; curCol < aWidth; curCol++) {
02868       *outRow++ = *imageRow++; // B
02869       *outRow++ = *imageRow++; // G
02870       *outRow++ = *imageRow++; // R
02871       *outRow++ = *alphaRow++; // A
02872     }
02873     imageRow = irow + aImageBytesPerRow;
02874     alphaRow = arow + aAlphaBytesPerRow;
02875   }
02876   return outData;
02877 }
02878 
02879 // static
02880 HBITMAP nsWindow::DataToBitmap(PRUint8* aImageData,
02881                                PRUint32 aWidth,
02882                                PRUint32 aHeight,
02883                                PRUint32 aDepth)
02884 {
02885   if (aDepth == 8 || aDepth == 4) {
02886     NS_WARNING("nsWindow::DataToBitmap can't handle 4 or 8 bit images");
02887     return NULL;
02888   }
02889 
02890   // dc must be a CreateCompatibleDC.
02891   // GetDC, cursors, 1 bit masks, and Win9x do not mix for some reason.
02892   HDC dc = ::CreateCompatibleDC(NULL);
02893   
02894   // force dc into color/bw mode
02895   int planes = ::GetDeviceCaps(dc, PLANES);
02896   int bpp = (aDepth == 1) ? 1 : ::GetDeviceCaps(dc, BITSPIXEL);
02897 
02898   HBITMAP tBitmap = ::CreateBitmap(1, 1, planes, bpp, NULL);
02899   HBITMAP oldbits = (HBITMAP)::SelectObject(dc, tBitmap);
02900 
02901 #ifndef WINCE
02902   if (aDepth == 32 && IsCursorTranslucencySupported()) {
02903     // Alpha channel. We need the new header.
02904     BITMAPV4HEADER head = { 0 };
02905     head.bV4Size = sizeof(head);
02906     head.bV4Width = aWidth;
02907     head.bV4Height = aHeight;
02908     head.bV4Planes = 1;
02909     head.bV4BitCount = aDepth;
02910     head.bV4V4Compression = BI_BITFIELDS;
02911     head.bV4SizeImage = 0; // Uncompressed
02912     head.bV4XPelsPerMeter = 0;
02913     head.bV4YPelsPerMeter = 0;
02914     head.bV4ClrUsed = 0;
02915     head.bV4ClrImportant = 0;
02916 
02917     head.bV4RedMask   = 0x00FF0000;
02918     head.bV4GreenMask = 0x0000FF00;
02919     head.bV4BlueMask  = 0x000000FF;
02920     head.bV4AlphaMask = 0xFF000000;
02921 
02922     HBITMAP bmp = ::CreateDIBitmap(dc,
02923                                    NS_REINTERPRET_CAST(CONST BITMAPINFOHEADER*, &head),
02924                                    CBM_INIT,
02925                                    aImageData,
02926                                    NS_REINTERPRET_CAST(CONST BITMAPINFO*, &head),
02927                                    DIB_RGB_COLORS);
02928 
02929     ::SelectObject(dc, oldbits);
02930     ::DeleteObject(tBitmap);
02931     ::DeleteDC(dc);
02932     return bmp;
02933   }
02934 #endif
02935 
02936   BITMAPINFOHEADER head = { 0 };
02937 
02938   head.biSize = sizeof(BITMAPINFOHEADER);
02939   head.biWidth = aWidth;
02940   head.biHeight = aHeight;
02941   head.biPlanes = 1;
02942   head.biBitCount = (WORD)aDepth;
02943   head.biCompression = BI_RGB;
02944   head.biSizeImage = 0; // Uncompressed
02945   head.biXPelsPerMeter = 0;
02946   head.biYPelsPerMeter = 0;
02947   head.biClrUsed = 0;
02948   head.biClrImportant = 0;
02949   
02950   char reserved_space[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2];
02951   BITMAPINFO& bi = *(BITMAPINFO*)reserved_space;
02952 
02953   bi.bmiHeader = head;
02954 
02955   if (aDepth == 1) {
02956     RGBQUAD black = { 0, 0, 0, 0 };
02957     RGBQUAD white = { 255, 255, 255, 0 };
02958 
02959     bi.bmiColors[0] = white;
02960     bi.bmiColors[1] = black;
02961   }
02962 
02963   HBITMAP bmp = ::CreateDIBitmap(dc, &head, CBM_INIT, aImageData, &bi, DIB_RGB_COLORS);
02964 
02965   ::SelectObject(dc, oldbits);
02966   ::DeleteObject(tBitmap);
02967   ::DeleteDC(dc);
02968   return bmp;
02969 }
02970 
02971 // static
02972 HBITMAP nsWindow::CreateOpaqueAlphaChannel(PRUint32 aWidth, PRUint32 aHeight)
02973 {
02974   // Make up an opaque alpha channel.
02975   // We need (aWidth + 7) / 8 bytes plus zero-padding up to a multiple of
02976   // 4 bytes for each row (HBITMAP requirement). Bug 353553.
02977   PRUint32 nonPaddedBytesPerRow = (aWidth + 7) / 8;
02978   PRUint32 abpr = (nonPaddedBytesPerRow + 3) & ~3;
02979   PRUint32 bufferSize = abpr * aHeight;
02980   PRUint8* opaque = (PRUint8*)malloc(bufferSize);
02981   if (!opaque)
02982     return NULL;
02983 
02984   memset(opaque, 0xff, bufferSize);
02985 
02986   // If we have row padding, set it to zero.
02987   if (nonPaddedBytesPerRow != abpr) {
02988     PRUint8* p = opaque;
02989     PRUint8* end = opaque + bufferSize;
02990     while (p != end) {
02991       PRUint8* nextRow = p + abpr;
02992       p += nonPaddedBytesPerRow;
02993       while (p != nextRow)
02994         *p++ = 0; // padding
02995     }
02996   }
02997 
02998   HBITMAP hAlpha = DataToBitmap(opaque, aWidth, aHeight, 1);
02999   free(opaque);
03000   return hAlpha;
03001 }
03002 
03003 /*
03004   For Win9x/ME, API specs say the image size must be 
03005   SM_CXCURSOR, SM_CYCURSOR (::GetSystemMetrics).  However, ::CreateIconIndirect
03006   returns null when the size is not correct.
03007 */
03008 NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
03009                                   PRUint32 aHotspotX, PRUint32 aHotspotY)
03010 {
03011   if (gCursorImgContainer == aCursor && gHCursor) {
03012     ::SetCursor(gHCursor);
03013     return NS_OK;
03014   }
03015 
03016   // Get the image data
03017   nsCOMPtr<gfxIImageFrame> frame;
03018   aCursor->GetFrameAt(0, getter_AddRefs(frame));
03019   if (!frame)
03020     return NS_ERROR_NOT_AVAILABLE;
03021 
03022   PRInt32 width, height;
03023   frame->GetWidth(&width);
03024   frame->GetHeight(&height);
03025 
03026   // Reject cursors greater than 128 pixels in some direction, to prevent
03027   // spoofing.
03028   // XXX ideally we should rescale. Also, we could modify the API to
03029   // allow trusted content to set larger cursors.
03030   if (width > 128 || height > 128)
03031     return NS_ERROR_NOT_AVAILABLE;
03032 
03033   gfx_format format;
03034   nsresult rv = frame->GetFormat(&format);
03035   if (NS_FAILED(rv))
03036     return rv;
03037 
03038   if (format != gfxIFormats::BGR_A1 && format != gfxIFormats::BGR_A8 &&
03039       format != gfxIFormats::BGR)
03040     return NS_ERROR_UNEXPECTED;
03041 
03042   // On Win2k with nVidia video drivers 71.84 at 32 bit color, cursors that 
03043   // have 8 bit alpha are truncated to 64x64.  Skip cursors larger than that.
03044   if (IsWin2k() && (format == gfxIFormats::BGR_A8) &&
03045       (width > 64 || height > 64))
03046     return NS_ERROR_FAILURE;
03047 
03048   PRUint32 bpr;
03049   rv = frame->GetImageBytesPerRow(&bpr);
03050   if (NS_FAILED(rv))
03051     return rv;
03052 
03053   frame->LockImageData();
03054   PRUint32 dataLen;
03055   PRUint8* data;
03056   rv = frame->GetImageData(&data, &dataLen);
03057   if (NS_FAILED(rv)) {
03058     frame->UnlockImageData();
03059     return rv;
03060   }
03061 
03062   HBITMAP hBMP = NULL;
03063   if (format != gfxIFormats::BGR_A8) {
03064     hBMP = DataToBitmap(data, width, height, 24);
03065     if (hBMP == NULL) {
03066       frame->UnlockImageData();
03067       return NS_ERROR_FAILURE;
03068     }
03069   }
03070 
03071   HBITMAP hAlpha = NULL;
03072   if (format == gfxIFormats::BGR) {
03073     hAlpha = CreateOpaqueAlphaChannel(width, height);
03074   } else {
03075     PRUint32 abpr;
03076     rv = frame->GetAlphaBytesPerRow(&abpr);
03077     if (NS_FAILED(rv)) {
03078       frame->UnlockImageData();
03079       if (hBMP != NULL)
03080         ::DeleteObject(hBMP);
03081       return rv;
03082     }
03083 
03084     PRUint8* adata;
03085     frame->LockAlphaData();
03086     rv = frame->GetAlphaData(&adata, &dataLen);
03087     if (NS_FAILED(rv)) {
03088       if (hBMP != NULL)
03089         ::DeleteObject(hBMP);
03090       frame->UnlockImageData();
03091       frame->UnlockAlphaData();
03092       return rv;
03093     }
03094 
03095     if (format == gfxIFormats::BGR_A8) {
03096       // Convert BGR_A8 to BGRA.  
03097       // Some platforms (or video cards?) on 32bit color mode will ignore
03098       // hAlpha. For them, we could speed up things by creating an opaque alpha
03099       // channel, but since we don't know how to determine whether hAlpha is
03100       // ignored, create a proper 1 bit alpha channel to supplement the RGBA.
03101       // Plus, on non-32bit color and possibly other platforms, the alpha
03102       // of RGBA is ignored.
03103       PRUint8* bgra8data = DataToAData(data, bpr, adata, abpr, width, height);
03104       if (bgra8data) {
03105         hBMP = DataToBitmap(bgra8data, width, height, 32);
03106         if (hBMP != NULL) {
03107           PRUint8* a1data = Data8BitTo1Bit(adata, abpr, width, height);
03108           if (a1data) {
03109             hAlpha = DataToBitmap(a1data, width, height, 1);
03110             delete [] a1data;
03111           }
03112         }
03113         delete [] bgra8data;
03114       }
03115     } else {
03116       hAlpha = DataToBitmap(adata, width, height, 1);
03117     }
03118 
03119     frame->UnlockAlphaData();
03120   }
03121   frame->UnlockImageData();
03122   if (hBMP == NULL) {
03123     return NS_ERROR_FAILURE;
03124   }
03125   if (hAlpha == NULL) {
03126     ::DeleteObject(hBMP);
03127     return NS_ERROR_FAILURE;
03128   }
03129 
03130   ICONINFO info = {0};
03131   info.fIcon = FALSE;
03132   info.xHotspot = aHotspotX;
03133   info.yHotspot = aHotspotY;
03134   info.hbmMask = hAlpha;
03135   info.hbmColor = hBMP;
03136   
03137   HCURSOR cursor = ::CreateIconIndirect(&info);
03138   ::DeleteObject(hBMP);
03139   ::DeleteObject(hAlpha);
03140   if (cursor == NULL) {
03141     return NS_ERROR_FAILURE;
03142   }
03143 
03144   mCursor = nsCursor(-1);
03145   ::SetCursor(cursor);
03146 
03147   NS_IF_RELEASE(gCursorImgContainer);
03148   gCursorImgContainer = aCursor;
03149   NS_ADDREF(gCursorImgContainer);
03150 
03151   if (gHCursor != NULL)
03152     ::DestroyIcon(gHCursor);
03153   gHCursor = cursor;
03154 
03155   return NS_OK;
03156 }
03157 
03158 NS_IMETHODIMP nsWindow::HideWindowChrome(PRBool aShouldHide)
03159 {
03160   HWND hwnd = GetTopLevelHWND(mWnd, PR_TRUE);
03161   if (!GetNSWindowPtr(hwnd))
03162   {
03163     NS_WARNING("Trying to hide window decorations in an embedded context");
03164     return NS_ERROR_FAILURE;
03165   }
03166 
03167   DWORD style, exStyle;
03168   if (aShouldHide) {
03169     DWORD tempStyle = nsToolkit::mGetWindowLong(hwnd, GWL_STYLE);
03170     DWORD tempExStyle = nsToolkit::mGetWindowLong(hwnd, GWL_EXSTYLE);
03171 
03172     style = tempStyle & ~(WS_CAPTION | WS_THICKFRAME);
03173     exStyle = tempExStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE |
03174                               WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
03175 
03176     mOldStyle = tempStyle;
03177     mOldExStyle = tempExStyle;
03178   }
03179   else {
03180     if (!mOldStyle || !mOldExStyle) {
03181       mOldStyle = nsToolkit::mGetWindowLong(hwnd, GWL_STYLE);
03182       mOldExStyle = nsToolkit::mGetWindowLong(hwnd, GWL_EXSTYLE);
03183     }
03184 
03185     style = mOldStyle;
03186     exStyle = mOldExStyle;
03187   }
03188 
03189   nsToolkit::mSetWindowLong(hwnd, GWL_STYLE, style);
03190   nsToolkit::mSetWindowLong(hwnd, GWL_EXSTYLE, exStyle);
03191 
03192   return NS_OK;
03193 }
03194 
03195 // ------------------------------------------------------------------------
03196 //
03197 // Validate a visible area of a widget.
03198 //
03199 // ------------------------------------------------------------------------
03200 
03201 NS_METHOD nsWindow::Validate()
03202 {
03203   if (mWnd)
03204     VERIFY(::ValidateRect(mWnd, NULL));
03205   return NS_OK;
03206 }
03207 
03208 //-------------------------------------------------------------------------
03209 //
03210 // Invalidate this component visible area
03211 //
03212 //-------------------------------------------------------------------------
03213 NS_METHOD nsWindow::Invalidate(PRBool aIsSynchronous)
03214 {
03215   if (mWnd)
03216   {
03217 #ifdef NS_DEBUG
03218     debug_DumpInvalidate(stdout,
03219                          this,
03220                          nsnull,
03221                          aIsSynchronous,
03222                          nsCAutoString("noname"),
03223                          (PRInt32) mWnd);
03224 #endif // NS_DEBUG
03225 
03226 #ifdef MOZ_XUL
03227     if (mIsTranslucent && IsAlphaTranslucencySupported() && !mPainting)
03228       OnPaint(w2k.mMemoryDC);
03229     else
03230 #endif
03231     {
03232       VERIFY(::InvalidateRect(mWnd, NULL, TRUE));
03233       if (aIsSynchronous) {
03234         VERIFY(::UpdateWindow(mWnd));
03235       }
03236     }
03237   }
03238   return NS_OK;
03239 }
03240 
03241 //-------------------------------------------------------------------------
03242 //
03243 // Invalidate this component visible area
03244 //
03245 //-------------------------------------------------------------------------
03246 NS_METHOD nsWindow::Invalidate(const nsRect & aRect, PRBool aIsSynchronous)
03247 {
03248   if (mWnd)
03249   {
03250 #ifdef NS_DEBUG
03251     debug_DumpInvalidate(stdout,
03252                          this,
03253                          &aRect,
03254                          aIsSynchronous,
03255                          nsCAutoString("noname"),
03256                          (PRInt32) mWnd);
03257 #endif // NS_DEBUG
03258 
03259 #ifdef MOZ_XUL
03260     if (mIsTranslucent && IsAlphaTranslucencySupported() && !mPainting)
03261       OnPaint(w2k.mMemoryDC);
03262     else
03263 #endif
03264     {
03265       RECT rect;
03266 
03267       rect.left   = aRect.x;
03268       rect.top    = aRect.y;
03269       rect.right  = aRect.x + aRect.width;
03270       rect.bottom = aRect.y  + aRect.height;
03271 
03272       VERIFY(::InvalidateRect(mWnd, &rect, TRUE));
03273       if (aIsSynchronous) {
03274         VERIFY(::UpdateWindow(mWnd));
03275       }
03276     }
03277   }
03278   return NS_OK;
03279 }
03280 
03281 NS_IMETHODIMP
03282 nsWindow::InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous)
03283 {
03284   nsresult rv = NS_OK;
03285   if (mWnd) {
03286 #ifdef MOZ_XUL
03287     if (mIsTranslucent && IsAlphaTranslucencySupported() && !mPainting)
03288       OnPaint(w2k.mMemoryDC);
03289     else
03290 #endif
03291     {
03292       HRGN nativeRegion;
03293       rv = aRegion->GetNativeRegion((void *&)nativeRegion);
03294       if (nativeRegion) {
03295         if (NS_SUCCEEDED(rv)) {
03296           VERIFY(::InvalidateRgn(mWnd, nativeRegion, TRUE));
03297 
03298           if (aIsSynchronous) {
03299             VERIFY(::UpdateWindow(mWnd));
03300           }
03301         }
03302       } else {
03303         rv = NS_ERROR_FAILURE;
03304       }
03305     }
03306   }
03307   return rv;
03308 }
03309 
03310 //-------------------------------------------------------------------------
03311 //
03312 // Force a synchronous repaint of the window
03313 //
03314 //-------------------------------------------------------------------------
03315 NS_IMETHODIMP nsWindow::Update()
03316 {
03317   nsresult rv = NS_OK;
03318 
03319   // updates can come through for windows no longer holding an mWnd during
03320   // deletes triggered by JavaScript in buttons with mouse feedback
03321   if (mWnd)
03322   {
03323 #ifdef MOZ_XUL
03324     if (mIsTranslucent && IsAlphaTranslucencySupported())
03325     {
03326 //      rv = UpdateTranslucentWindow();
03327     } else
03328 #endif
03329     {
03330       VERIFY(::UpdateWindow(mWnd));
03331     }
03332   }
03333   return rv;
03334 }
03335 
03336 //-------------------------------------------------------------------------
03337 //
03338 // Return some native data according to aDataType
03339 //
03340 //-------------------------------------------------------------------------
03341 void* nsWindow::GetNativeData(PRUint32 aDataType)
03342 {
03343   switch (aDataType) {
03344     case NS_NATIVE_WIDGET:
03345     case NS_NATIVE_WINDOW:
03346     case NS_NATIVE_PLUGIN_PORT:
03347       return (void*)mWnd;
03348     case NS_NATIVE_GRAPHIC:
03349       // XXX:  This is sleezy!!  Remember to Release the DC after using it!
03350 #ifdef MOZ_XUL
03351       return (void*)(mIsTranslucent && IsAlphaTranslucencySupported()) ?
03352         w2k.mMemoryDC : ::GetDC(mWnd);
03353 #else
03354       return (void*)::GetDC(mWnd);
03355 #endif
03356     case NS_NATIVE_COLORMAP:
03357     default:
03358       break;
03359   }
03360 
03361   return NULL;
03362 }
03363 
03364 //~~~
03365 void nsWindow::FreeNativeData(void * data, PRUint32 aDataType)
03366 {
03367   switch (aDataType)
03368   {
03369     case NS_NATIVE_GRAPHIC:
03370 #ifdef MOZ_XUL
03371       if (!(mIsTranslucent && IsAlphaTranslucencySupported()))
03372         ::ReleaseDC(mWnd, (HDC)data);
03373 #else
03374       ::ReleaseDC(mWnd, (HDC)data);
03375 #endif
03376       break;
03377     case NS_NATIVE_WIDGET:
03378     case NS_NATIVE_WINDOW:
03379     case NS_NATIVE_PLUGIN_PORT:
03380     case NS_NATIVE_COLORMAP:
03381       break;
03382     default:
03383       break;
03384   }
03385 }
03386 
03387 //-------------------------------------------------------------------------
03388 //
03389 // Set the colormap of the window
03390 //
03391 //-------------------------------------------------------------------------
03392 NS_METHOD nsWindow::SetColorMap(nsColorMap *aColorMap)
03393 {
03394 #if 0
03395   if (mPalette != NULL) {
03396     ::DeleteObject(mPalette);
03397   }
03398 
03399   PRUint8 *map = aColorMap->Index;
03400   LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +
03401                                                  aColorMap->NumColors * sizeof(PALETTEENTRY)];
03402   pLogPal->palVersion = 0x300;
03403   pLogPal->palNumEntries = aColorMap->NumColors;
03404   for(int i = 0; i < aColorMap->NumColors; i++)
03405   {
03406     pLogPal->palPalEntry[i].peRed = *map++;
03407     pLogPal->palPalEntry[i].peGreen = *map++;
03408     pLogPal->palPalEntry[i].peBlue = *map++;
03409     pLogPal->palPalEntry[i].peFlags = 0;
03410   }
03411   mPalette = ::CreatePalette(pLogPal);
03412   delete pLogPal;
03413 
03414   NS_ASSERTION(mPalette != NULL, "Null palette");
03415   if (mPalette != NULL) {
03416     HDC hDC = ::GetDC(mWnd);
03417     HPALETTE hOldPalette = ::SelectPalette(hDC, mPalette, TRUE);
03418     ::RealizePalette(hDC);
03419     ::SelectPalette(hDC, hOldPalette, TRUE);
03420     ::ReleaseDC(mWnd, hDC);
03421   }
03422 #endif
03423   return NS_OK;
03424 }
03425 
03426 
03427 //-------------------------------------------------------------------------
03428 //
03429 // Scroll the bits of a window
03430 //
03431 //-------------------------------------------------------------------------
03432 //XXX Scroll is obsolete and should go away soon
03433 NS_METHOD nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
03434 {
03435   RECT  trect;
03436 
03437   if (nsnull != aClipRect)
03438   {
03439     trect.left = aClipRect->x;
03440     trect.top = aClipRect->y;
03441     trect.right = aClipRect->XMost();
03442     trect.bottom = aClipRect->YMost();
03443   }
03444 
03445   ::ScrollWindowEx(mWnd, aDx, aDy, (nsnull != aClipRect) ? &trect : NULL, NULL,
03446                    NULL, NULL, SW_INVALIDATE | SW_SCROLLCHILDREN);
03447   ::UpdateWindow(mWnd);
03448   return NS_OK;
03449 }
03450 
03451 NS_IMETHODIMP nsWindow::ScrollWidgets(PRInt32 aDx, PRInt32 aDy)
03452 {
03453   // Scroll the entire contents of the window + change the offset of any child windows
03454   ::ScrollWindowEx(mWnd, aDx, aDy, NULL, NULL, NULL,
03455                    NULL, SW_INVALIDATE | SW_SCROLLCHILDREN);
03456   ::UpdateWindow(mWnd); // Force synchronous generation of NS_PAINT
03457   return NS_OK;
03458 }
03459 
03460 NS_IMETHODIMP nsWindow::ScrollRect(nsRect &aRect, PRInt32 aDx, PRInt32 aDy)
03461 {
03462   RECT  trect;
03463 
03464   trect.left = aRect.x;
03465   trect.top = aRect.y;
03466   trect.right = aRect.XMost();
03467   trect.bottom = aRect.YMost();
03468 
03469   // Scroll the bits in the window defined by trect.
03470   // Child windows are not scrolled.
03471   ::ScrollWindowEx(mWnd, aDx, aDy, &trect, NULL, NULL,
03472                    NULL, SW_INVALIDATE);
03473   ::UpdateWindow(mWnd); // Force synchronous generation of NS_PAINT
03474   return NS_OK;
03475 }
03476 
03477 
03478 //-------------------------------------------------------------------------
03479 //
03480 // Every function that needs a thread switch goes through this function
03481 // by calling SendMessage (..WM_CALLMETHOD..) in nsToolkit::CallMethod.
03482 //
03483 //-------------------------------------------------------------------------
03484 BOOL nsWindow::CallMethod(MethodInfo *info)
03485 {
03486   BOOL bRet = TRUE;
03487 
03488   switch (info->methodId) {
03489     case nsWindow::CREATE:
03490       NS_ASSERTION(info->nArgs == 7, "Wrong number of arguments to CallMethod");
03491       Create((nsIWidget*)(info->args[0]),
03492              (nsRect&)*(nsRect*)(info->args[1]),
03493              (EVENT_CALLBACK)(info->args[2]),
03494              (nsIDeviceContext*)(info->args[3]),
03495              (nsIAppShell *)(info->args[4]),
03496              (nsIToolkit*)(info->args[5]),
03497              (nsWidgetInitData*)(info->args[6]));
03498       break;
03499 
03500     case nsWindow::CREATE_NATIVE:
03501       NS_ASSERTION(info->nArgs == 7, "Wrong number of arguments to CallMethod");
03502       Create((nsNativeWidget)(info->args[0]),
03503              (nsRect&)*(nsRect*)(info->args[1]),
03504              (EVENT_CALLBACK)(info->args[2]),
03505              (nsIDeviceContext*)(info->args[3]),
03506              (nsIAppShell *)(info->args[4]),
03507              (nsIToolkit*)(info->args[5]),
03508              (nsWidgetInitData*)(info->args[6]));
03509       return TRUE;
03510 
03511     case nsWindow::DESTROY:
03512       NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
03513       Destroy();
03514       break;
03515 
03516     case nsWindow::SET_FOCUS:
03517       NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
03518       SetFocus(PR_FALSE);
03519       break;
03520 
03521     default:
03522       bRet = FALSE;
03523       break;
03524   }
03525 
03526   return bRet;
03527 }
03528 
03529 //-------------------------------------------------------------------------
03530 void nsWindow::SetUpForPaint(HDC aHDC)
03531 {
03532   ::SetBkColor (aHDC, NSRGB_2_COLOREF(mBackground));
03533   ::SetTextColor(aHDC, NSRGB_2_COLOREF(mForeground));
03534   ::SetBkMode (aHDC, TRANSPARENT);
03535 }
03536 
03537 //---------------------------------------------------------
03538 NS_METHOD nsWindow::EnableDragDrop(PRBool aEnable)
03539 {
03540   nsresult rv = NS_ERROR_FAILURE;
03541 #ifndef WINCE
03542   if (aEnable) {
03543     if (nsnull == mNativeDragTarget) {
03544        mNativeDragTarget = new nsNativeDragTarget(this);
03545        if (NULL != mNativeDragTarget) {
03546          mNativeDragTarget->AddRef();
03547          if (S_OK == ::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget,TRUE,FALSE)) {
03548            if (S_OK == ::RegisterDragDrop(mWnd, (LPDROPTARGET)mNativeDragTarget)) {
03549              rv = NS_OK;
03550            }
03551          }
03552        }
03553     }
03554   } else {
03555     if (nsnull != mWnd && NULL != mNativeDragTarget) {
03556       ::RevokeDragDrop(mWnd);
03557       if (S_OK == ::CoLockObjectExternal((LPUNKNOWN)mNativeDragTarget, FALSE, TRUE)) {
03558         rv = NS_OK;
03559       }
03560       NS_RELEASE(mNativeDragTarget);
03561     }
03562   }
03563 #endif
03564   return rv;
03565 }
03566 
03567 //-------------------------------------------------------------------------
03568 UINT nsWindow::MapFromNativeToDOM(UINT aNativeKeyCode)
03569 {
03570   switch (aNativeKeyCode) {
03571     case 0xBA: return NS_VK_SEMICOLON;
03572     case 0xBB: return NS_VK_EQUALS;
03573     case 0xBD: return NS_VK_SUBTRACT;
03574   }
03575 
03576   return aNativeKeyCode;
03577 }
03578 
03579 //-------------------------------------------------------------------------
03580 //
03581 // OnKey
03582 //
03583 //-------------------------------------------------------------------------
03584 PRBool nsWindow::DispatchKeyEvent(PRUint32 aEventType, WORD aCharCode, UINT aVirtualCharCode, 
03585                                   LPARAM aKeyData, PRUint32 aFlags)
03586 {
03587   nsKeyEvent event(PR_TRUE, aEventType, this);
03588   nsPoint point(0, 0);
03589 
03590   InitEvent(event, &point); // this add ref's event.widget
03591 
03592   event.flags |= aFlags;
03593   event.charCode = aCharCode;
03594   event.keyCode  = aVirtualCharCode;
03595 
03596 #ifdef KE_DEBUG
03597   static cnt=0;
03598   printf("%d DispatchKE Type: %s charCode %d  keyCode %d ", cnt++,
03599         (NS_KEY_PRESS == aEventType) ? "PRESS" : (aEventType == NS_KEY_UP ? "Up" : "Down"),
03600          event.charCode, event.keyCode);
03601   printf("Shift: %s Control %s Alt: %s \n", 
03602          (mIsShiftDown ? "D" : "U"), (mIsControlDown ? "D" : "U"), (mIsAltDown ? "D" : "U"));
03603   printf("[%c][%c][%c] <==   [%c][%c][%c][ space bar ][%c][%c][%c]\n",
03604          IS_VK_DOWN(NS_VK_SHIFT) ? 'S' : ' ',
03605          IS_VK_DOWN(NS_VK_CONTROL) ? 'C' : ' ',
03606          IS_VK_DOWN(NS_VK_ALT) ? 'A' : ' ',
03607          IS_VK_DOWN(VK_LSHIFT) ? 'S' : ' ',
03608          IS_VK_DOWN(VK_LCONTROL) ? 'C' : ' ',
03609          IS_VK_DOWN(VK_LMENU) ? 'A' : ' ',
03610          IS_VK_DOWN(VK_RMENU) ? 'A' : ' ',
03611          IS_VK_DOWN(VK_RCONTROL) ? 'C' : ' ',
03612          IS_VK_DOWN(VK_RSHIFT) ? 'S' : ' ');
03613 #endif
03614 
03615   event.isShift   = mIsShiftDown;
03616   event.isControl = mIsControlDown;
03617   event.isMeta    = PR_FALSE;
03618   event.isAlt     = mIsAltDown;
03619 
03620   nsPluginEvent pluginEvent;
03621 
03622   switch (aEventType)
03623   {
03624     case NS_KEY_UP:
03625       pluginEvent.event = WM_KEYUP;
03626       break;
03627     case NS_KEY_DOWN:
03628       pluginEvent.event = WM_KEYDOWN;
03629       break;
03630     default:
03631       break;
03632   }
03633 
03634   pluginEvent.wParam = aVirtualCharCode;
03635   pluginEvent.lParam = aKeyData;
03636 
03637   event.nativeMsg = (void *)&pluginEvent;
03638 
03639   PRBool result = DispatchWindowEvent(&event);
03640   NS_RELEASE(event.widget);
03641 
03642   return result;
03643 }
03644 
03645 
03646 
03647 //-------------------------------------------------------------------------
03648 //
03649 //
03650 //-------------------------------------------------------------------------
03651 BOOL nsWindow::OnKeyDown(UINT aVirtualKeyCode, UINT aScanCode, LPARAM aKeyData)
03652 {
03653   UINT virtualKeyCode = sIMEIsComposing ? aVirtualKeyCode : MapFromNativeToDOM(aVirtualKeyCode);
03654 
03655 #ifdef DEBUG
03656   //printf("In OnKeyDown virt: %d  scan: %d\n", virtualKeyCode, aScanCode);
03657 #endif
03658 
03659   BOOL noDefault = DispatchKeyEvent(NS_KEY_DOWN, 0, virtualKeyCode, aKeyData);
03660 
03661   // If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a keypress
03662   // for almost all keys
03663   switch (virtualKeyCode) {
03664     case NS_VK_SHIFT:
03665     case NS_VK_CONTROL:
03666     case NS_VK_ALT:
03667     case NS_VK_CAPS_LOCK:
03668     case NS_VK_NUM_LOCK:
03669     case NS_VK_SCROLL_LOCK: return noDefault;
03670   }
03671 
03672   PRUint32 extraFlags = (noDefault ? NS_EVENT_FLAG_NO_DEFAULT : 0);
03673 
03674   PRBool dispatchAsciiKeyPressEvent = PR_TRUE;
03675   MSG msg;
03676   BOOL gotMsg = nsToolkit::mPeekMessage(&msg, mWnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD);
03677   // Enter and backspace are always handled here to avoid for example the
03678   // confusion between ctrl-enter and ctrl-J.
03679   // Ctrl+[Add, Subtract, Equals] are always handled here to make text zoom shortcuts work
03680   // on different keyboard layouts (Equals is needed because many layouts return it when
03681   // pressing Ctrl++ and that's why it's also accepted as a shortcut for increasing zoom).
03682   if (virtualKeyCode == NS_VK_RETURN || virtualKeyCode == NS_VK_BACK ||
03683       (mIsControlDown && !mIsAltDown && !mIsShiftDown &&
03684        (virtualKeyCode == NS_VK_ADD || virtualKeyCode == NS_VK_SUBTRACT ||
03685         virtualKeyCode == NS_VK_EQUALS)))
03686   {
03687     // Remove a possible WM_CHAR or WM_SYSCHAR from the message queue
03688     if (gotMsg && (msg.message == WM_CHAR || msg.message == WM_SYSCHAR)) {
03689       nsToolkit::mGetMessage(&msg, mWnd, WM_KEYFIRST, WM_KEYLAST);
03690     } else if (virtualKeyCode == NS_VK_BACK) {
03691       MSG imeStartCompositionMsg, imeCompositionMsg;
03692       if (nsToolkit::mPeekMessage(&imeStartCompositionMsg, mWnd, WM_IME_STARTCOMPOSITION, WM_IME_STARTCOMPOSITION, PM_NOREMOVE | PM_NOYIELD)
03693        && nsToolkit::mPeekMessage(&imeCompositionMsg, mWnd, WM_IME_COMPOSITION, WM_IME_COMPOSITION, PM_NOREMOVE | PM_NOYIELD)
03694        && nsToolkit::mPeekMessage(&msg, mWnd, WM_CHAR, WM_CHAR, PM_NOREMOVE | PM_NOYIELD)
03695        && imeStartCompositionMsg.wParam == 0x0 && imeStartCompositionMsg.lParam == 0x0
03696        && imeCompositionMsg.wParam == 0x0 && imeCompositionMsg.lParam == 0x1BF
03697        && msg.wParam == NS_VK_BACK && msg.lParam == 0x1
03698        && imeStartCompositionMsg.time <= imeCompositionMsg.time
03699        && imeCompositionMsg.time <= msg.time) {
03700         // This message pattern is "Kakutei-Undo" on ATOK and WXG.
03701         // (ATOK and WXG are popular IMEs in Japan)
03702         // In this case, the message queue has following messages:
03703         // ------------------------------------------------------------------------------------------
03704         // WM_KEYDOWN              * n (wParam = VK_BACK, lParam = 0x1)
03705         // WM_KEYUP                * 1 (wParam = VK_BACK, lParam = 0xC0000001) #this is ATOK only
03706         // WM_IME_STARTCOMPOSITION * 1 (wParam = 0x0, lParam = 0x0)
03707         // WM_IME_COMPOSITION      * 1 (wParam = 0x0, lParam = 0x1BF)
03708         // WM_CHAR                 * n (wParam = VK_BACK, lParam = 0x1)
03709         // WM_KEYUP                * 1 (wParam = VK_BACK, lParam = 0xC00E0001)
03710         // ------------------------------------------------------------------------------------------
03711         // This message pattern does not match to the above case;
03712         // i.e.,WM_KEYDOWN -> WM_CHAR -> WM_KEYDOWN -> WM_CHAR.
03713         // For more information of this problem:
03714         // http://bugzilla.mozilla.gr.jp/show_bug.cgi?id=2885 (written in Japanese)
03715         // http://bugzilla.mozilla.org/show_bug.cgi?id=194559 (written in English)
03716 
03717         nsToolkit::mGetMessage(&msg, mWnd, WM_CHAR, WM_CHAR);
03718       }
03719     }
03720   }
03721   else if (gotMsg &&
03722            (msg.message == WM_CHAR || msg.message == WM_SYSCHAR || msg.message == WM_DEADCHAR)) {
03723     // If prevent default set for keydown, do same for keypress
03724     nsToolkit::mGetMessage(&msg, mWnd, msg.message, msg.message);
03725     if (msg.message == WM_DEADCHAR)
03726       return PR_FALSE;
03727 #ifdef KE_DEBUG
03728     printf("%s\tchar=%c\twp=%4x\tlp=%8x\n",
03729            (msg.message == WM_SYSCHAR) ? "WM_SYSCHAR" : "WM_CHAR",
03730            msg.wParam, msg.wParam, msg.lParam);
03731 #endif
03732     return OnChar(msg.wParam, msg.lParam, extraFlags);
03733   }
03734   else if (!mIsControlDown && !mIsAltDown) {
03735     // This is not normal key down event if the inputting character
03736     // is ASCII character. If so, we should not send the KeyPress event.
03737     dispatchAsciiKeyPressEvent = PR_FALSE;
03738   }
03739 
03740   WORD asciiKey = 0;
03741 
03742   switch (virtualKeyCode) {
03743     // keys to be sent as characters
03744     case NS_VK_ADD       : asciiKey = '+';  break;
03745     case NS_VK_SUBTRACT  : asciiKey = '-';  break;
03746     case NS_VK_SEMICOLON : asciiKey = ';';  break;
03747     case NS_VK_EQUALS    : asciiKey = '=';  break;
03748     case NS_VK_COMMA     : asciiKey = ',';  break;
03749     case NS_VK_PERIOD    : asciiKey = '.';  break;
03750     case NS_VK_QUOTE     : asciiKey = '\''; break;
03751     case NS_VK_BACK_QUOTE: asciiKey = '`';  break;
03752     case NS_VK_DIVIDE    :
03753     case NS_VK_SLASH     : asciiKey = '/';  break;
03754     case NS_VK_MULTIPLY  : asciiKey = '*';  break;
03755     case NS_VK_NUMPAD0   : asciiKey = '0';  break;
03756     case NS_VK_NUMPAD1   : asciiKey = '1';  break;
03757     case NS_VK_NUMPAD2   : asciiKey = '2';  break;
03758     case NS_VK_NUMPAD3   : asciiKey = '3';  break;
03759     case NS_VK_NUMPAD4   : asciiKey = '4';  break;
03760     case NS_VK_NUMPAD5   : asciiKey = '5';  break;
03761     case NS_VK_NUMPAD6   : asciiKey = '6';  break;
03762     case NS_VK_NUMPAD7   : asciiKey = '7';  break;
03763     case NS_VK_NUMPAD8   : asciiKey = '8';  break;
03764     case NS_VK_NUMPAD9   : asciiKey = '9';  break;
03765     default:
03766       // NS_VK_0 - NS_VK_9 and NS_VK_A - NS_VK_Z match their ascii values
03767       if ((NS_VK_0 <= virtualKeyCode && virtualKeyCode <= NS_VK_9) ||
03768           (NS_VK_A <= virtualKeyCode && virtualKeyCode <= NS_VK_Z)) {
03769         asciiKey = virtualKeyCode;
03770         // Take the Shift state into account
03771         if (!mIsShiftDown 
03772             && NS_VK_A <= virtualKeyCode && virtualKeyCode <= NS_VK_Z) {
03773           asciiKey += 0x20;
03774         }
03775       }
03776   }
03777 
03778   if (asciiKey && !dispatchAsciiKeyPressEvent)
03779     return noDefault;
03780 
03781   if (asciiKey)
03782     DispatchKeyEvent(NS_KEY_PRESS, asciiKey, 0, aKeyData, extraFlags);
03783   else
03784     DispatchKeyEvent(NS_KEY_PRESS, 0, virtualKeyCode, aKeyData, extraFlags);
03785 
03786   return noDefault;
03787 }
03788 
03789 //-------------------------------------------------------------------------
03790 //
03791 //
03792 //-------------------------------------------------------------------------
03793 BOOL nsWindow::OnKeyUp( UINT aVirtualKeyCode, UINT aScanCode, LPARAM aKeyData)
03794 {
03795   aVirtualKeyCode = sIMEIsComposing ? aVirtualKeyCode : MapFromNativeToDOM(aVirtualKeyCode);
03796   BOOL result = DispatchKeyEvent(NS_KEY_UP, 0, aVirtualKeyCode, aKeyData);
03797   return result;
03798 }
03799 
03800 
03801 //-------------------------------------------------------------------------
03802 //
03803 //
03804 //-------------------------------------------------------------------------
03805 BOOL nsWindow::OnChar(UINT charCode, LPARAM keyData, PRUint32 aFlags)
03806 {
03807   // These must be checked here too as a lone WM_CHAR could be received
03808   // if a child window didn't handle it (for example Alt+Space in a content window)
03809   mIsShiftDown   = IS_VK_DOWN(NS_VK_SHIFT);
03810   mIsControlDown = IS_VK_DOWN(NS_VK_CONTROL);
03811   mIsAltDown     = IS_VK_DOWN(NS_VK_ALT);
03812 
03813   // ignore [shift+]alt+space so the OS can handle it
03814   if (mIsAltDown && !mIsControlDown && IS_VK_DOWN(NS_VK_SPACE)) {
03815     return FALSE;
03816   }
03817 
03818   // WM_CHAR with Control and Alt (== AltGr) down really means a normal character
03819   PRBool saveIsAltDown = mIsAltDown;
03820   PRBool saveIsControlDown = mIsControlDown;
03821   if (mIsAltDown && mIsControlDown)
03822     mIsAltDown = mIsControlDown = PR_FALSE;
03823 
03824   wchar_t uniChar;
03825 
03826   if (sIMEIsComposing) {
03827     HandleEndComposition();
03828   }
03829 
03830   if (mIsControlDown && charCode <= 0x1A) { // Ctrl+A Ctrl+Z, see Programming Windows 3.1 page 110 for details
03831     // need to account for shift here.  bug 16486
03832     if (mIsShiftDown)
03833       uniChar = charCode - 1 + 'A';
03834     else
03835       uniChar = charCode - 1 + 'a';
03836     charCode = 0;
03837   }
03838   else if (mIsControlDown && charCode <= 0x1F) {
03839     // Fix for 50255 - <ctrl><[> and <ctrl><]> are not being processed.
03840     // also fixes ctrl+\ (x1c), ctrl+^ (x1e) and ctrl+_ (x1f)
03841     // for some reason the keypress handler need to have the uniChar code set
03842     // with the addition of a upper case A not the lower case.
03843     uniChar = charCode - 1 + 'A';
03844     charCode = 0;
03845   } else { // 0x20 - SPACE, 0x3D - EQUALS
03846     if (charCode < 0x20 || (charCode == 0x3D && mIsControlDown)) {
03847       uniChar = 0;
03848     } else {
03849       if (nsToolkit::mIsNT) {
03850         uniChar = charCode;
03851       } else {
03852         char    charToConvert[3];
03853         size_t  length;
03854 
03855         if (charCode <= 0xFF) { // not a multibyte character
03856           if (mLeadByte) {      // mLeadByte is used for keeping the lead-byte of CJK char
03857             charToConvert[0] = mLeadByte;
03858             charToConvert[1] = LOBYTE(charCode);
03859             mLeadByte = '\0';
03860             length = 2;
03861           } else {
03862             charToConvert[0] = LOBYTE(charCode);
03863             if (::IsDBCSLeadByteEx(gCurrentKeyboardCP, charToConvert[0])) {
03864               mLeadByte = charToConvert[0];
03865               mIsAltDown = saveIsAltDown;
03866               mIsControlDown = saveIsControlDown;
03867               return TRUE;
03868             }
03869             length = 1;
03870           }
03871         } else {
03872           // SC double-byte punctuation mark in Windows-English is 0x0000aca3
03873           uniChar = LOWORD(charCode);
03874           charToConvert[0] = LOBYTE(uniChar);
03875           charToConvert[1] = HIBYTE(uniChar);
03876           mLeadByte = '\0';
03877           length=2;
03878         }
03879         ::MultiByteToWideChar(gCurrentKeyboardCP, MB_PRECOMPOSED, charToConvert, length,
03880                               &uniChar, 1);
03881       }
03882       charCode = 0;
03883     }
03884   }
03885 
03886   // Keep the characters unshifted for shortcuts and accesskeys and make sure
03887   // that numbers are always passed as such (among others: bugs 50255 and 351310)
03888   if (uniChar && (mIsControlDown || mIsAltDown)) {
03889     UINT virtualKeyCode = ::MapVirtualKey(HIWORD(keyData) & 0xFF, MAPVK_VSC_TO_VK);
03890     UINT unshiftedCharCode =
03891       virtualKeyCode >= '0' && virtualKeyCode <= '9' ? virtualKeyCode :
03892       mIsShiftDown ? ::MapVirtualKey(virtualKeyCode, MAPVK_VK_TO_CHAR) : 0;
03893     // ignore diacritics (top bit set) and key mapping errors (char code 0)
03894     if ((INT)unshiftedCharCode > 0)
03895       uniChar = unshiftedCharCode;
03896   }
03897 
03898   // Fix for bug 285161 (and 295095) which was caused by the initial fix for bug 178110.
03899   // When pressing (alt|ctrl)+char, the char must be lowercase unless shift is 
03900   // pressed too.
03901   if (!mIsShiftDown && (saveIsAltDown || saveIsControlDown)) {
03902     uniChar = towlower(uniChar);
03903   }
03904 
03905   PRBool result = DispatchKeyEvent(NS_KEY_PRESS, uniChar, charCode, 0, aFlags);
03906   mIsAltDown = saveIsAltDown;
03907   mIsControlDown = saveIsControlDown;
03908   return result;
03909 }
03910 
03911 
03912 void nsWindow::ConstrainZLevel(HWND *aAfter)
03913 {
03914   nsZLevelEvent  event(PR_TRUE, NS_SETZLEVEL, this);
03915   nsWindow      *aboveWindow = 0;
03916 
03917   InitEvent(event);
03918 
03919   if (*aAfter == HWND_BOTTOM)
03920     event.mPlacement = nsWindowZBottom;
03921   else if (*aAfter == HWND_TOP || *aAfter == HWND_TOPMOST || *aAfter == HWND_NOTOPMOST)
03922     event.mPlacement = nsWindowZTop;
03923   else {
03924     event.mPlacement = nsWindowZRelative;
03925     aboveWindow = GetNSWindowPtr(*aAfter);
03926   }
03927   event.mReqBelow = aboveWindow;
03928   event.mActualBelow = nsnull;
03929 
03930   event.mImmediate = PR_FALSE;
03931   event.mAdjusted = PR_FALSE;
03932   DispatchWindowEvent(&event);
03933 
03934   if (event.mAdjusted) {
03935     if (event.mPlacement == nsWindowZBottom)
03936       *aAfter = HWND_BOTTOM;
03937     else if (event.mPlacement == nsWindowZTop)
03938       *aAfter = HWND_TOP;
03939     else {
03940       *aAfter = (HWND)event.mActualBelow->GetNativeData(NS_NATIVE_WINDOW);
03941     }
03942   }
03943   NS_IF_RELEASE(event.mActualBelow);
03944   NS_RELEASE(event.widget);
03945 }
03946 
03947 //-------------------------------------------------------------------------
03948 //
03949 // Process all nsWindows messages
03950 //
03951 //-------------------------------------------------------------------------
03952 static PRBool gJustGotDeactivate = PR_FALSE;
03953 static PRBool gJustGotActivate = PR_FALSE;
03954 
03955 #ifdef NS_DEBUG
03956 
03957 typedef struct {
03958   char * mStr;
03959   long   mId;
03960 } EventMsgInfo;
03961 
03962 EventMsgInfo gAllEvents[] = {
03963   {"WM_NULL",                   0x0000},
03964   {"WM_CREATE",                 0x0001},
03965   {"WM_DESTROY",                0x0002},
03966   {"WM_MOVE",                   0x0003},
03967   {"WM_SIZE",                   0x0005},
03968   {"WM_ACTIVATE",               0x0006},
03969   {"WM_SETFOCUS",               0x0007},
03970   {"WM_KILLFOCUS",              0x0008},
03971   {"WM_ENABLE",                 0x000A},
03972   {"WM_SETREDRAW",              0x000B},
03973   {"WM_SETTEXT",                0x000C},
03974   {"WM_GETTEXT",                0x000D},
03975   {"WM_GETTEXTLENGTH",          0x000E},
03976   {"WM_PAINT",                  0x000F},
03977   {"WM_CLOSE",                  0x0010},
03978   {"WM_QUERYENDSESSION",        0x0011},
03979   {"WM_QUIT",                   0x0012},
03980   {"WM_QUERYOPEN",              0x0013},
03981   {"WM_ERASEBKGND",             0x0014},
03982   {"WM_SYSCOLORCHANGE",         0x0015},
03983   {"WM_ENDSESSION",             0x0016},
03984   {"WM_SHOWWINDOW",             0x0018},
03985   {"WM_SETTINGCHANGE",          0x001A},
03986   {"WM_DEVMODECHANGE",          0x001B},
03987   {"WM_ACTIVATEAPP",            0x001C},
03988   {"WM_FONTCHANGE",             0x001D},
03989   {"WM_TIMECHANGE",             0x001E},
03990   {"WM_CANCELMODE",             0x001F},
03991   {"WM_SETCURSOR",              0x0020},
03992   {"WM_MOUSEACTIVATE",          0x0021},
03993   {"WM_CHILDACTIVATE",          0x0022},
03994   {"WM_QUEUESYNC",              0x0023},
03995   {"WM_GETMINMAXINFO",          0x0024},
03996   {"WM_PAINTICON",              0x0026},
03997   {"WM_ICONERASEBKGND",         0x0027},
03998   {"WM_NEXTDLGCTL",             0x0028},
03999   {"WM_SPOOLERSTATUS",          0x002A},
04000   {"WM_DRAWITEM",               0x002B},
04001   {"WM_MEASUREITEM",            0x002C},
04002   {"WM_DELETEITEM",             0x002D},
04003   {"WM_VKEYTOITEM",             0x002E},
04004   {"WM_CHARTOITEM",             0x002F},
04005   {"WM_SETFONT",                0x0030},
04006   {"WM_GETFONT",                0x0031},
04007   {"WM_SETHOTKEY",              0x0032},
04008   {"WM_GETHOTKEY",              0x0033},
04009   {"WM_QUERYDRAGICON",          0x0037},
04010   {"WM_COMPAREITEM",            0x0039},
04011   {"WM_GETOBJECT",              0x003D},
04012   {"WM_COMPACTING",             0x0041},
04013   {"WM_COMMNOTIFY",             0x0044},
04014   {"WM_WINDOWPOSCHANGING",      0x0046},
04015   {"WM_WINDOWPOSCHANGED",       0x0047},
04016   {"WM_POWER",                  0x0048},
04017   {"WM_COPYDATA",               0x004A},
04018   {"WM_CANCELJOURNAL",          0x004B},
04019   {"WM_NOTIFY",                 0x004E},
04020   {"WM_INPUTLANGCHANGEREQUEST", 0x0050},
04021   {"WM_INPUTLANGCHANGE",        0x0051},
04022   {"WM_TCARD",                  0x0052},
04023   {"WM_HELP",                   0x0053},
04024   {"WM_USERCHANGED",            0x0054},
04025   {"WM_NOTIFYFORMAT",           0x0055},
04026   {"WM_CONTEXTMENU",            0x007B},
04027   {"WM_STYLECHANGING",          0x007C},
04028   {"WM_STYLECHANGED",           0x007D},
04029   {"WM_DISPLAYCHANGE",          0x007E},
04030   {"WM_GETICON",                0x007F},
04031   {"WM_SETICON",                0x0080},
04032   {"WM_NCCREATE",               0x0081},
04033   {"WM_NCDESTROY",              0x0082},
04034   {"WM_NCCALCSIZE",             0x0083},
04035   {"WM_NCHITTEST",              0x0084},
04036   {"WM_NCPAINT",                0x0085},
04037   {"WM_NCACTIVATE",             0x0086},
04038   {"WM_GETDLGCODE",             0x0087},
04039   {"WM_SYNCPAINT",              0x0088},
04040   {"WM_NCMOUSEMOVE",            0x00A0},
04041   {"WM_NCLBUTTONDOWN",          0x00A1},
04042   {"WM_NCLBUTTONUP",            0x00A2},
04043   {"WM_NCLBUTTONDBLCLK",        0x00A3},
04044   {"WM_NCRBUTTONDOWN",          0x00A4},
04045   {"WM_NCRBUTTONUP",            0x00A5},
04046   {"WM_NCRBUTTONDBLCLK",        0x00A6},
04047   {"WM_NCMBUTTONDOWN",          0x00A7},
04048   {"WM_NCMBUTTONUP",            0x00A8},
04049   {"WM_NCMBUTTONDBLCLK",        0x00A9},
04050   {"EM_GETSEL",                 0x00B0},
04051   {"EM_SETSEL",                 0x00B1},
04052   {"EM_GETRECT",                0x00B2},
04053   {"EM_SETRECT",                0x00B3},
04054   {"EM_SETRECTNP",              0x00B4},
04055   {"EM_SCROLL",                 0x00B5},
04056   {"EM_LINESCROLL",             0x00B6},
04057   {"EM_SCROLLCARET",            0x00B7},
04058   {"EM_GETMODIFY",              0x00B8},
04059   {"EM_SETMODIFY",              0x00B9},
04060   {"EM_GETLINECOUNT",           0x00BA},
04061   {"EM_LINEINDEX",              0x00BB},
04062   {"EM_SETHANDLE",              0x00BC},
04063   {"EM_GETHANDLE",              0x00BD},
04064   {"EM_GETTHUMB",               0x00BE},
04065   {"EM_LINELENGTH",             0x00C1},
04066   {"EM_REPLACESEL",             0x00C2},
04067   {"EM_GETLINE",                0x00C4},
04068   {"EM_LIMITTEXT",              0x00C5},
04069   {"EM_CANUNDO",                0x00C6},
04070   {"EM_UNDO",                   0x00C7},
04071   {"EM_FMTLINES",               0x00C8},
04072   {"EM_LINEFROMCHAR",           0x00C9},
04073   {"EM_SETTABSTOPS",            0x00CB},
04074   {"EM_SETPASSWORDCHAR",        0x00CC},
04075   {"EM_EMPTYUNDOBUFFER",        0x00CD},
04076   {"EM_GETFIRSTVISIBLELINE",    0x00CE},
04077   {"EM_SETREADONLY",            0x00CF},
04078   {"EM_SETWORDBREAKPROC",       0x00D0},
04079   {"EM_GETWORDBREAKPROC",       0x00D1},
04080   {"EM_GETPASSWORDCHAR",        0x00D2},
04081   {"EM_SETMARGINS",             0x00D3},
04082   {"EM_GETMARGINS",             0x00D4},
04083   {"EM_GETLIMITTEXT",           0x00D5},
04084   {"EM_POSFROMCHAR",            0x00D6},
04085   {"EM_CHARFROMPOS",            0x00D7},
04086   {"EM_SETIMESTATUS",           0x00D8},
04087   {"EM_GETIMESTATUS",           0x00D9},
04088   {"SBM_SETPOS",                0x00E0},
04089   {"SBM_GETPOS",                0x00E1},
04090   {"SBM_SETRANGE",              0x00E2},
04091   {"SBM_SETRANGEREDRAW",        0x00E6},
04092   {"SBM_GETRANGE",              0x00E3},
04093   {"SBM_ENABLE_ARROWS",         0x00E4},
04094   {"SBM_SETSCROLLINFO",         0x00E9},
04095   {"SBM_GETSCROLLINFO",         0x00EA},
04096   {"WM_KEYDOWN",                0x0100},
04097   {"WM_KEYUP",                  0x0101},
04098   {"WM_CHAR",                   0x0102},
04099   {"WM_DEADCHAR",               0x0103},
04100   {"WM_SYSKEYDOWN",             0x0104},
04101   {"WM_SYSKEYUP",               0x0105},
04102   {"WM_SYSCHAR",                0x0106},
04103   {"WM_SYSDEADCHAR",            0x0107},
04104   {"WM_KEYLAST",                0x0108},
04105   {"WM_IME_STARTCOMPOSITION",   0x010D},
04106   {"WM_IME_ENDCOMPOSITION",     0x010E},
04107   {"WM_IME_COMPOSITION",        0x010F},
04108   {"WM_INITDIALOG",             0x0110},
04109   {"WM_COMMAND",                0x0111},
04110   {"WM_SYSCOMMAND",             0x0112},
04111   {"WM_TIMER",                  0x0113},
04112   {"WM_HSCROLL",                0x0114},
04113   {"WM_VSCROLL",                0x0115},
04114   {"WM_INITMENU",               0x0116},
04115   {"WM_INITMENUPOPUP",          0x0117},
04116   {"WM_MENUSELECT",             0x011F},
04117   {"WM_MENUCHAR",               0x0120},
04118   {"WM_ENTERIDLE",              0x0121},
04119   {"WM_MENURBUTTONUP",          0x0122},
04120   {"WM_MENUDRAG",               0x0123},
04121   {"WM_MENUGETOBJECT",          0x0124},
04122   {"WM_UNINITMENUPOPUP",        0x0125},
04123   {"WM_MENUCOMMAND",            0x0126},
04124   {"WM_CTLCOLORMSGBOX",         0x0132},
04125   {"WM_CTLCOLOREDIT",           0x0133},
04126   {"WM_CTLCOLORLISTBOX",        0x0134},
04127   {"WM_CTLCOLORBTN",            0x0135},
04128   {"WM_CTLCOLORDLG",            0x0136},
04129   {"WM_CTLCOLORSCROLLBAR",      0x0137},
04130   {"WM_CTLCOLORSTATIC",         0x0138},
04131   {"CB_GETEDITSEL",             0x0140},
04132   {"CB_LIMITTEXT",              0x0141},
04133   {"CB_SETEDITSEL",             0x0142},
04134   {"CB_ADDSTRING",              0x0143},
04135   {"CB_DELETESTRING",           0x0144},
04136   {"CB_DIR",                    0x0145},
04137   {"CB_GETCOUNT",               0x0146},
04138   {"CB_GETCURSEL",              0x0147},
04139   {"CB_GETLBTEXT",              0x0148},
04140   {"CB_GETLBTEXTLEN",           0x0149},
04141   {"CB_INSERTSTRING",           0x014A},
04142   {"CB_RESETCONTENT",           0x014B},
04143   {"CB_FINDSTRING",             0x014C},
04144   {"CB_SELECTSTRING",           0x014D},
04145   {"CB_SETCURSEL",              0x014E},
04146   {"CB_SHOWDROPDOWN",           0x014F},
04147   {"CB_GETITEMDATA",            0x0150},
04148   {"CB_SETITEMDATA",            0x0151},
04149   {"CB_GETDROPPEDCONTROLRECT",  0x0152},
04150   {"CB_SETITEMHEIGHT",          0x0153},
04151   {"CB_GETITEMHEIGHT",          0x0154},
04152   {"CB_SETEXTENDEDUI",          0x0155},
04153   {"CB_GETEXTENDEDUI",          0x0156},
04154   {"CB_GETDROPPEDSTATE",        0x0157},
04155   {"CB_FINDSTRINGEXACT",        0x0158},
04156   {"CB_SETLOCALE",              0x0159},
04157   {"CB_GETLOCALE",              0x015A},
04158   {"CB_GETTOPINDEX",            0x015b},
04159   {"CB_SETTOPINDEX",            0x015c},
04160   {"CB_GETHORIZONTALEXTENT",    0x015d},
04161   {"CB_SETHORIZONTALEXTENT",    0x015e},
04162   {"CB_GETDROPPEDWIDTH",        0x015f},
04163   {"CB_SETDROPPEDWIDTH",        0x0160},
04164   {"CB_INITSTORAGE",            0x0161},
04165   {"CB_MSGMAX",                 0x0162},
04166   {"LB_ADDSTRING",              0x0180},
04167   {"LB_INSERTSTRING",           0x0181},
04168   {"LB_DELETESTRING",           0x0182},
04169   {"LB_SELITEMRANGEEX",         0x0183},
04170   {"LB_RESETCONTENT",           0x0184},
04171   {"LB_SETSEL",                 0x0185},
04172   {"LB_SETCURSEL",              0x0186},
04173   {"LB_GETSEL",                 0x0187},
04174   {"LB_GETCURSEL",              0x0188},
04175   {"LB_GETTEXT",                0x0189},
04176   {"LB_GETTEXTLEN",             0x018A},
04177   {"LB_GETCOUNT",               0x018B},
04178   {"LB_SELECTSTRING",           0x018C},
04179   {"LB_DIR",                    0x018D},
04180   {"LB_GETTOPINDEX",            0x018E},
04181   {"LB_FINDSTRING",             0x018F},
04182   {"LB_GETSELCOUNT",            0x0190},
04183   {"LB_GETSELITEMS",            0x0191},
04184   {"LB_SETTABSTOPS",            0x0192},
04185   {"LB_GETHORIZONTALEXTENT",    0x0193},
04186   {"LB_SETHORIZONTALEXTENT",    0x0194},
04187   {"LB_SETCOLUMNWIDTH",         0x0195},
04188   {"LB_ADDFILE",                0x0196},
04189   {"LB_SETTOPINDEX",            0x0197},
04190   {"LB_GETITEMRECT",            0x0198},
04191   {"LB_GETITEMDATA",            0x0199},
04192   {"LB_SETITEMDATA",            0x019A},
04193   {"LB_SELITEMRANGE",           0x019B},
04194   {"LB_SETANCHORINDEX",         0x019C},
04195   {"LB_GETANCHORINDEX",         0x019D},
04196   {"LB_SETCARETINDEX",          0x019E},
04197   {"LB_GETCARETINDEX",          0x019F},
04198   {"LB_SETITEMHEIGHT",          0x01A0},
04199   {"LB_GETITEMHEIGHT",          0x01A1},
04200   {"LB_FINDSTRINGEXACT",        0x01A2},
04201   {"LB_SETLOCALE",              0x01A5},
04202   {"LB_GETLOCALE",              0x01A6},
04203   {"LB_SETCOUNT",               0x01A7},
04204   {"LB_INITSTORAGE",            0x01A8},
04205   {"LB_ITEMFROMPOINT",          0x01A9},
04206   {"LB_MSGMAX",                 0x01B0},
04207   {"WM_MOUSEFIRST",             0x0200},
04208   {"WM_MOUSEMOVE",              0x0200},
04209   {"WM_LBUTTONDOWN",            0x0201},
04210   {"WM_LBUTTONUP",              0x0202},
04211   {"WM_LBUTTONDBLCLK",          0x0203},
04212   {"WM_RBUTTONDOWN",            0x0204},
04213   {"WM_RBUTTONUP",              0x0205},
04214   {"WM_RBUTTONDBLCLK",          0x0206},
04215   {"WM_MBUTTONDOWN",            0x0207},
04216   {"WM_MBUTTONUP",              0x0208},
04217   {"WM_MBUTTONDBLCLK",          0x0209},
04218   {"WM_MOUSEWHEEL",             0x020A},
04219   {"WM_MOUSEHWHEEL",            0x020E},
04220   {"WM_MOUSELAST",              0x020A},
04221   {"WM_MOUSELAST",              0x0209},
04222   {"WM_PARENTNOTIFY",           0x0210},
04223   {"WM_ENTERMENULOOP",          0x0211},
04224   {"WM_EXITMENULOOP",           0x0212},
04225   {"WM_NEXTMENU",               0x0213},
04226   {"WM_SIZING",                 0x0214},
04227   {"WM_CAPTURECHANGED",         0x0215},
04228   {"WM_MOVING",                 0x0216},
04229   {"WM_POWERBROADCAST",         0x0218},
04230   {"WM_DEVICECHANGE",           0x0219},
04231   {"WM_MDICREATE",              0x0220},
04232   {"WM_MDIDESTROY",             0x0221},
04233   {"WM_MDIACTIVATE",            0x0222},
04234   {"WM_MDIRESTORE",             0x0223},
04235   {"WM_MDINEXT",                0x0224},
04236   {"WM_MDIMAXIMIZE",            0x0225},
04237   {"WM_MDITILE",                0x0226},
04238   {"WM_MDICASCADE",             0x0227},
04239   {"WM_MDIICONARRANGE",         0x0228},
04240   {"WM_MDIGETACTIVE",           0x0229},
04241   {"WM_MDISETMENU",             0x0230},
04242   {"WM_ENTERSIZEMOVE",          0x0231},
04243   {"WM_EXITSIZEMOVE",           0x0232},
04244   {"WM_DROPFILES",              0x0233},
04245   {"WM_MDIREFRESHMENU",         0x0234},
04246   {"WM_IME_SETCONTEXT",         0x0281},
04247   {"WM_IME_NOTIFY",             0x0282},
04248   {"WM_IME_CONTROL",            0x0283},
04249   {"WM_IME_COMPOSITIONFULL",    0x0284},
04250   {"WM_IME_SELECT",             0x0285},
04251   {"WM_IME_CHAR",               0x0286},
04252   {"WM_IME_REQUEST",            0x0288},
04253   {"WM_IME_KEYDOWN",            0x0290},
04254   {"WM_IME_KEYUP",              0x0291},
04255   {"WM_MOUSEHOVER",             0x02A1},
04256   {"WM_MOUSELEAVE",             0x02A3},
04257   {"WM_CUT",                    0x0300},
04258   {"WM_COPY",                   0x0301},
04259   {"WM_PASTE",                  0x0302},
04260   {"WM_CLEAR",                  0x0303},
04261   {"WM_UNDO",                   0x0304},
04262   {"WM_RENDERFORMAT",           0x0305},
04263   {"WM_RENDERALLFORMATS",       0x0306},
04264   {"WM_DESTROYCLIPBOARD",       0x0307},
04265   {"WM_DRAWCLIPBOARD",          0x0308},
04266   {"WM_PAINTCLIPBOARD",         0x0309},
04267   {"WM_VSCROLLCLIPBOARD",       0x030A},
04268   {"WM_SIZECLIPBOARD",          0x030B},
04269   {"WM_ASKCBFORMATNAME",        0x030C},
04270   {"WM_CHANGECBCHAIN",          0x030D},
04271   {"WM_HSCROLLCLIPBOARD",       0x030E},
04272   {"WM_QUERYNEWPALETTE",        0x030F},
04273   {"WM_PALETTEISCHANGING",      0x0310},
04274   {"WM_PALETTECHANGED",         0x0311},
04275   {"WM_HOTKEY",                 0x0312},
04276   {"WM_PRINT",                  0x0317},
04277   {"WM_PRINTCLIENT",            0x0318},
04278   {"WM_THEMECHANGED",           0x031A},
04279   {"WM_HANDHELDFIRST",          0x0358},
04280   {"WM_HANDHELDLAST",           0x035F},
04281   {"WM_AFXFIRST",               0x0360},
04282   {"WM_AFXLAST",                0x037F},
04283   {"WM_PENWINFIRST",            0x0380},
04284   {"WM_PENWINLAST",             0x038F},
04285   {"WM_APP",                    0x8000},
04286   {NULL, 0x0}
04287 };
04288 
04289 
04290 static long gEventCounter = 0;
04291 static long gLastEventMsg = 0;
04292 
04293 void PrintEvent(UINT msg, PRBool aShowAllEvents, PRBool aShowMouseMoves)
04294 {
04295   int inx = 0;
04296   while (gAllEvents[inx].mId != (long)msg && gAllEvents[inx].mStr != NULL) {
04297     inx++;
04298   }
04299   if (aShowAllEvents || (!aShowAllEvents && gLastEventMsg != (long)msg)) {
04300     if (aShowMouseMoves || (!aShowMouseMoves && msg != 0x0020 && msg != 0x0200 && msg != 0x0084)) {
04301       printf("%6d - 0x%04X %s\n", gEventCounter++, msg, gAllEvents[inx].mStr ? gAllEvents[inx].mStr : "Unknown");
04302       gLastEventMsg = msg;
04303     }
04304   }
04305 }
04306 
04307 #endif
04308 
04309 #define WM_XP_THEMECHANGED                 0x031A
04310 
04311 // Static helper functions for heap dumping
04312 static nsresult HeapDump(const char *filename, const char *heading)
04313 {
04314 #ifdef WINCE
04315   return NS_ERROR_NOT_IMPLEMENTED;
04316 #else
04317   // Make sure heapwalk() is available
04318   typedef BOOL WINAPI HeapWalkProc(HANDLE hHeap, LPPROCESS_HEAP_ENTRY lpEntry);
04319   typedef DWORD WINAPI GetProcessHeapsProc(DWORD NumberOfHeaps, PHANDLE ProcessHeaps);
04320 
04321   static PRBool firstTime = PR_TRUE;
04322   static HeapWalkProc *heapWalkP = NULL;
04323   static GetProcessHeapsProc *getProcessHeapsP = NULL;
04324 
04325   if (firstTime) {
04326     firstTime = PR_FALSE;
04327     HMODULE kernel = GetModuleHandle("kernel32.dll");
04328     if (kernel) {
04329       heapWalkP = (HeapWalkProc*)GetProcAddress(kernel, "HeapWalk");
04330       getProcessHeapsP = (GetProcessHeapsProc*)GetProcAddress(kernel, "GetProcessHeaps");
04331     }
04332   }
04333 
04334   if (!heapWalkP)
04335     return NS_ERROR_NOT_AVAILABLE;
04336 
04337   PRFileDesc *prfd = PR_Open(filename, PR_CREATE_FILE | PR_APPEND | PR_WRONLY, 0777);
04338   if (!prfd)
04339     return NS_ERROR_FAILURE;
04340 
04341   char buf[1024];
04342   PRUint32 n;
04343   PRUint32 written = 0;
04344   HANDLE heapHandle[64];
04345   DWORD nheap = (*getProcessHeapsP)(64, heapHandle);
04346   if (nheap == 0 || nheap > 64) {
04347     return NS_ERROR_FAILURE;
04348   }
04349 
04350   n = PR_snprintf(buf, sizeof buf, "BEGIN HEAPDUMP : %s\n", heading);
04351   PR_Write(prfd, buf, n);
04352   for (DWORD i = 0; i < nheap; i++) {
04353     // Dump each heap
04354     PROCESS_HEAP_ENTRY ent = {0};
04355     n = PR_snprintf(buf, sizeof buf, "BEGIN heap %d : 0x%p\n", i+1, heapHandle[i]);
04356     PR_Write(prfd, buf, n);
04357     ent.lpData = NULL;
04358     while ((*heapWalkP)(heapHandle[i], &ent)) {
04359       if (ent.wFlags & PROCESS_HEAP_REGION)
04360         n = PR_snprintf(buf, sizeof buf, "REGION %08p : overhead %d committed %d uncommitted %d firstblock %08p lastblock %08p\n",
04361                         ent.lpData, ent.cbOverhead,
04362                         ent.Region.dwCommittedSize, ent.Region.dwUnCommittedSize,
04363                         ent.Region.lpFirstBlock, ent.Region.lpLastBlock);
04364       else
04365         n = PR_snprintf(buf, sizeof buf, "%s %08p : %6d overhead %2d\n",
04366                         (ent.wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) ? "----" : ((ent.wFlags & PROCESS_HEAP_ENTRY_BUSY) ? "USED" : "FREE"),
04367                         ent.lpData, ent.cbData, ent.cbOverhead);
04368       PR_Write(prfd, buf, n);
04369     }
04370     n = PR_snprintf(buf, sizeof buf, "END heap %d : 0x%p\n", i+1, heapHandle[i]);
04371     PR_Write(prfd, buf, n);
04372   }
04373   n = PR_snprintf(buf, sizeof buf, "END HEAPDUMP : %s\n", heading);
04374   PR_Write(prfd, buf, n);
04375 
04376   PR_Close(prfd);
04377   return NS_OK;
04378 #endif // WINCE
04379 }
04380 
04381 // Recursively dispatch synchronous paints for nsIWidget
04382 // descendants with invalidated rectangles.
04383 
04384 BOOL CALLBACK nsWindow::DispatchStarvedPaints(HWND aWnd, LPARAM aMsg)
04385 {
04386   LONG proc = nsToolkit::mGetWindowLong(aWnd, GWL_WNDPROC);
04387   if (proc == (LONG)&nsWindow::WindowProc) {
04388     // its one of our windows so check to see if it has a
04389     // invalidated rect. If it does. Dispatch a synchronous
04390     // paint.
04391     if (GetUpdateRect(aWnd, NULL, FALSE)) {
04392       VERIFY(::UpdateWindow(aWnd));
04393     }
04394   }
04395   return TRUE;
04396 }
04397 
04398 // Check for pending paints and dispatch any pending paint
04399 // messages for any nsIWidget which is a descendant of the
04400 // top-level window that *this* window is embedded within.
04401 // Also dispatch pending PL_Events to avoid PL_EventQueue starvation.
04402 // Note: We do not dispatch pending paint messages for non
04403 // nsIWidget managed windows.
04404 
04405 void nsWindow::DispatchPendingEvents()
04406 {
04407   gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
04408 
04409   // Need to flush all pending PL_Events before
04410   // painting to prevent reflow events from being starved.
04411   // Note: Unfortunately, The flushing of PL_Events can not be done by
04412   // dispatching the native WM_TIMER event that is used for PL_Event
04413   // notification because the timer message will not appear in the
04414   // native msg queue until 10ms after the event is posted. Which is too late.
04415   nsCOMPtr<nsIEventQueue> eventQueue;
04416   nsToolkit *toolkit = NS_STATIC_CAST(nsToolkit *, mToolkit);
04417   eventQueue = toolkit->GetEventQueue();
04418   if (eventQueue) {
04419     eventQueue->ProcessPendingEvents();
04420   }
04421 
04422   // Quickly check to see if there are any
04423   // paint events pending.
04424   if (::GetQueueStatus(QS_PAINT)) {
04425     // Find the top level window.
04426     HWND topWnd = GetTopLevelHWND(mWnd);
04427 
04428     // Dispatch pending paints for all topWnd's descendant windows.
04429     // Note: EnumChildWindows enumerates all descendant windows not just
04430     // it's children.
04431     ::EnumChildWindows(topWnd, nsWindow::DispatchStarvedPaints, NULL);
04432   }
04433 }
04434 
04435 #ifndef WINCE
04436 void nsWindow::PostSleepWakeNotification(const char* aNotification)
04437 {
04438   nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
04439   if (observerService)
04440   {
04441     observerService->NotifyObservers(nsnull, aNotification, nsnull);
04442   }
04443 }
04444 #endif
04445 
04446 PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *aRetValue)
04447 {
04448   static UINT vkKeyCached = 0;              // caches VK code fon WM_KEYDOWN
04449   PRBool result = PR_FALSE;                 // call the default nsWindow proc
04450   static PRBool getWheelInfo = PR_TRUE;
04451   *aRetValue = 0;
04452   PRBool isMozWindowTakingFocus = PR_TRUE;
04453   nsPaletteInfo palInfo;
04454 
04455   // Uncomment this to see all windows messages
04456   // first param shows all events
04457   // second param indicates whether to show mouse move events
04458   //PrintEvent(msg, PR_FALSE, PR_FALSE);
04459 
04460   switch (msg) {
04461     case WM_COMMAND:
04462     {
04463       WORD wNotifyCode = HIWORD(wParam); // notification code
04464       if ((CBN_SELENDOK == wNotifyCode) || (CBN_SELENDCANCEL == wNotifyCode)) { // Combo box change
04465         nsGUIEvent event(PR_TRUE, NS_CONTROL_CHANGE, this);
04466         nsPoint point(0,0);
04467         InitEvent(event, &point); // this add ref's event.widget
04468         result = DispatchWindowEvent(&event);
04469         NS_RELEASE(event.widget);
04470       } else if (wNotifyCode == 0) { // Menu selection
04471         nsMenuEvent event(PR_TRUE, NS_MENU_SELECTED, this);
04472         event.mCommand = LOWORD(wParam);
04473         InitEvent(event);
04474         result = DispatchWindowEvent(&event);
04475         NS_RELEASE(event.widget);
04476       }
04477     }
04478     break;
04479 
04480 #ifndef WINCE
04481     case WM_DISPLAYCHANGE:
04482       DispatchStandardEvent(NS_DISPLAYCHANGED);
04483       break;
04484 #endif
04485 
04486     case WM_SYSCOLORCHANGE:
04487       // Note: This is sent for child windows as well as top-level windows.
04488       // The Win32 toolkit normally only sends these events to top-level windows.
04489       // But we cycle through all of the childwindows and send it to them as well
04490       // so all presentations get notified properly.
04491       // See nsWindow::GlobalMsgWindowProc.
04492       DispatchStandardEvent(NS_SYSCOLORCHANGED);
04493       break;
04494 
04495     case WM_NOTIFY:
04496       // TAB change
04497     {
04498       LPNMHDR pnmh = (LPNMHDR) lParam;
04499 
04500         switch (pnmh->code) {
04501           case TCN_SELCHANGE:
04502           {
04503             DispatchStandardEvent(NS_TABCHANGE);
04504             result = PR_TRUE;
04505           }
04506           break;
04507         }
04508     }
04509     break;
04510 
04511     case WM_XP_THEMECHANGED:
04512     {
04513       DispatchStandardEvent(NS_THEMECHANGED);
04514 
04515       // Invalidate the window so that the repaint will
04516       // pick up the new theme.
04517       Invalidate(PR_FALSE);
04518     }
04519     break;
04520 
04521     case WM_FONTCHANGE:
04522     {
04523       nsresult rv;
04524       PRBool didChange = PR_FALSE;
04525 
04526       // update the global font list
04527       nsCOMPtr<nsIFontEnumerator> fontEnum = do_GetService("@mozilla.org/gfx/fontenumerator;1", &rv);
04528       if (NS_SUCCEEDED(rv)) {
04529         fontEnum->UpdateFontList(&didChange);
04530         //didChange is TRUE only if new font langGroup is added to the list.
04531         if (didChange)  {
04532           nsCOMPtr<nsIFontPackageService> proxy = do_GetService("@mozilla.org/intl/fontpackageservice;1", &rv);
04533           if (proxy) {
04534             // font in the system is changed.  Notify the font download service.
04535             proxy->FontPackageHandled(PR_FALSE, PR_FALSE, "");
04536 
04537             // update device context font cache
04538             // Dirty but easiest way:
04539             // Changing nsIPref entry which triggers callbacks
04540             // and flows into calling mDeviceContext->FlushFontCache()
04541             // to update the font cache in all the instance of Browsers
04542             nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
04543             if (prefs) {
04544               nsCOMPtr<nsIPrefBranch> fiPrefs;
04545               prefs->GetBranch("font.internaluseonly.", getter_AddRefs(fiPrefs));
04546               if (fiPrefs) {
04547                 PRBool fontInternalChange = PR_FALSE;
04548                 fiPrefs->GetBoolPref("changed", &fontInternalChange);
04549                 fiPrefs->SetBoolPref("changed", !fontInternalChange);
04550               }
04551             }
04552           }
04553         }
04554       } //if (NS_SUCCEEDED(rv))
04555     }
04556     break;
04557 
04558 #ifndef WINCE
04559     case WM_POWERBROADCAST:
04560       // only hidden window handle this
04561       // to prevent duplicate notification
04562       if (mWindowType == eWindowType_invisible) {
04563         switch (wParam)
04564         {
04565           case PBT_APMSUSPEND:
04566             PostSleepWakeNotification("sleep_notification");
04567             break;
04568           case PBT_APMRESUMEAUTOMATIC:
04569           case PBT_APMRESUMECRITICAL:
04570           case PBT_APMRESUMESUSPEND:
04571             PostSleepWakeNotification("wake_notification");
04572             break;
04573         }
04574       }
04575       break;
04576 #endif
04577 
04578     case WM_MOVE: // Window moved
04579     {
04580       PRInt32 x = GET_X_LPARAM(lParam); // horizontal position in screen coordinates
04581       PRInt32 y = GET_Y_LPARAM(lParam); // vertical position in screen coordinates
04582       result = OnMove(x, y);
04583     }
04584     break;
04585 
04586     case WM_CLOSE: // close request
04587       DispatchStandardEvent(NS_XUL_CLOSE);
04588       result = PR_TRUE; // abort window closure
04589       break;
04590 
04591     case WM_DESTROY:
04592       // clean up.
04593       OnDestroy();
04594       result = PR_TRUE;
04595       break;
04596 
04597     case WM_PAINT:
04598       result = OnPaint();
04599       break;
04600 
04601 #ifndef WINCE
04602     case WM_PRINTCLIENT:
04603       result = OnPaint((HDC) wParam);
04604       break;
04605 #endif
04606                      
04607 #ifdef WINCE
04608       // This needs to move into nsIDOMKeyEvent.idl && nsGUIEvent.h
04609     case WM_HOTKEY:
04610     {
04611       // SmartPhones has a one or two menu buttons at the
04612       // bottom of the screen.  They are dispatched via a
04613       // menu resource, rather then a hotkey.  To make
04614       // this look consistent, we have mapped this menu to
04615       // fire hotkey events.  See
04616       // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/win_ce/html/pwc_TheBackButtonandOtherInterestingButtons.asp
04617       
04618       if (VK_TSOFT1 == HIWORD(lParam))
04619       {
04620         if (MOD_KEYUP & LOWORD(lParam))
04621         {
04622           KillTimer(NULL, gSoftkeyTimerId);
04623           gSoftkeyTimerId = 0;
04624 
04625           if (gSoftkeyTimerHit == 0)
04626           {
04627             nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
04628             if (observerService)
04629               observerService->NotifyObservers(nsnull, "softkey", NS_LITERAL_STRING("left").get());
04630           } 
04631 
04632         }
04633         else
04634         {
04635           if (!gSoftkeyTimerId)
04636           {
04637             gSoftkeyTimerHit = 0;
04638             gSoftkeyTimerId = SetTimer(NULL, 0, gSoftkeyContextDelay, LeftSoftkeyTimer);
04639           }
04640         }
04641         result = 0;
04642         break;
04643       }
04644       
04645       if (VK_TSOFT2 == HIWORD(lParam))
04646       {
04647         if (MOD_KEYUP & LOWORD(lParam))
04648         {
04649           KillTimer(NULL, gSoftkeyTimerId);
04650           gSoftkeyTimerId = 0;
04651 
04652           if (gSoftkeyTimerHit == 0)
04653           {
04654             nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
04655             if (observerService)
04656               observerService->NotifyObservers(nsnull, "softkey", NS_LITERAL_STRING("right").get());
04657           }
04658         }
04659         else
04660         {
04661           if (!gSoftkeyTimerId)
04662           {
04663             gSoftkeyTimerHit = 0;
04664             gSoftkeyTimerId = SetTimer(NULL, 0, gSoftkeyContextDelay, RightSoftkeyTimer);
04665           }
04666         }
04667         result = 0;
04668         break;
04669       }
04670       
04671       if (VK_TBACK == HIWORD(lParam))
04672       {
04673         if (MOD_KEYUP & LOWORD(lParam))
04674         {
04675           KillTimer(NULL, gSoftkeyTimerId);
04676           gSoftkeyTimerId = 0;
04677         }
04678         else
04679         {
04680           keybd_event(VK_BACK, 0, 0, 0);
04681           keybd_event(VK_BACK, 0, KEYEVENTF_KEYUP, 0);
04682 
04683           if (!gSoftkeyTimerId)
04684             gSoftkeyTimerId = SetTimer(NULL, 0, gBackRepeatDelay, BackSoftkeyTimer);
04685         }
04686         result = 0;
04687         break;
04688       }
04689     }
04690     break;
04691 #endif
04692 
04693     case WM_SYSCHAR:
04694     case WM_CHAR:
04695     {
04696 #ifdef KE_DEBUG
04697       printf("%s\tchar=%c\twp=%4x\tlp=%8x\n", (msg == WM_SYSCHAR) ? "WM_SYSCHAR" : "WM_CHAR", wParam, wParam, lParam);
04698 #endif
04699       result = OnChar(wParam, lParam);
04700     }
04701     break;
04702 
04703     case WM_SYSKEYUP:
04704     case WM_KEYUP:
04705 
04706 #ifdef KE_DEBUG
04707       printf("%s\t\twp=%x\tlp=%x\n", (WM_KEYUP==msg) ? "WM_KEYUP" : "WM_SYSKEYUP", wParam, lParam);
04708 #endif
04709       mIsShiftDown   = IS_VK_DOWN(NS_VK_SHIFT);
04710       mIsControlDown = IS_VK_DOWN(NS_VK_CONTROL);
04711       mIsAltDown     = IS_VK_DOWN(NS_VK_ALT);
04712 
04713       // Note: the original code passed (HIWORD(lParam)) to OnKeyUp as
04714       // scan code. However, this breaks Alt+Num pad input.
04715       // http://msdn.microsoft.com/library/psdk/winui/keybinpt_8qp5.htm
04716       // states the following:
04717       //  Typically, ToAscii performs the translation based on the
04718       //  virtual-key code. In some cases, however, bit 15 of the
04719       //  uScanCode parameter may be used to distinguish between a key
04720       //  press and a key release. The scan code is used for
04721       //  translating ALT+number key combinations.
04722 
04723       // ignore [shift+]alt+space so the OS can handle it
04724       if (mIsAltDown && !mIsControlDown && IS_VK_DOWN(NS_VK_SPACE)) {
04725         result = PR_FALSE;
04726         DispatchPendingEvents();
04727         break;
04728       }
04729 
04730       if (!sIMEIsComposing && (msg != WM_KEYUP || wParam != VK_MENU)) {
04731         // Ignore VK_MENU if it's not a system key release, so that the menu bar does not trigger
04732         // This helps avoid triggering the menu bar for ALT key accelerators used in
04733         // assistive technologies such as Window-Eyes and ZoomText, and when using Alt+Tab
04734         // to switch back to Mozilla in Windows 95 and Windows 98
04735         result = OnKeyUp(wParam, (HIWORD(lParam)), lParam);
04736       }
04737       else {
04738         result = PR_FALSE;
04739       }
04740 
04741       DispatchPendingEvents();
04742       break;
04743 
04744     // Let the fall through if it isn't a key pad
04745     case WM_SYSKEYDOWN:
04746     case WM_KEYDOWN:
04747 #ifdef KE_DEBUG
04748       printf("%s\t\twp=%4x\tlp=%8x\n", (WM_KEYDOWN==msg) ? "WM_KEYDOWN" : "WM_SYSKEYDOWN", wParam, lParam);
04749 #endif
04750 
04751       mIsShiftDown   = IS_VK_DOWN(NS_VK_SHIFT);
04752       mIsControlDown = IS_VK_DOWN(NS_VK_CONTROL);
04753       mIsAltDown     = IS_VK_DOWN(NS_VK_ALT);
04754 
04755       // Note: the original code passed (HIWORD(lParam)) to OnKeyDown as
04756       // scan code. However, this breaks Alt+Num pad input.
04757       // http://msdn.microsoft.com/library/psdk/winui/keybinpt_8qp5.htm
04758       // states the following:
04759       //  Typically, ToAscii performs the translation based on the
04760       //  virtual-key code. In some cases, however, bit 15 of the
04761       //  uScanCode parameter may be used to distinguish between a key
04762       //  press and a key release. The scan code is used for
04763       //  translating ALT+number key combinations.
04764 
04765       // ignore [shift+]alt+space so the OS can handle it
04766       if (mIsAltDown && !mIsControlDown && IS_VK_DOWN(NS_VK_SPACE)) {
04767         result = PR_FALSE;
04768         DispatchPendingEvents();
04769         break;
04770       }
04771 
04772       if (mIsAltDown && sIMEIsStatusChanged) {
04773         sIMEIsStatusChanged = FALSE;
04774         result = PR_FALSE;
04775       }
04776       else if (!sIMEIsComposing) {
04777         result = OnKeyDown(wParam, (HIWORD(lParam)), lParam);
04778       }
04779       else
04780         result = PR_FALSE;
04781 #ifndef WINCE
04782       if (wParam == VK_MENU || (wParam == VK_F10 && !mIsShiftDown)) {
04783         // We need to let Windows handle this keypress,
04784         // by returning PR_FALSE, if there's a native menu
04785         // bar somewhere in our containing window hierarchy.
04786         // Otherwise we handle the keypress and don't pass
04787         // it on to Windows, by returning PR_TRUE.
04788         PRBool hasNativeMenu = PR_FALSE;
04789         HWND hWnd = mWnd;
04790         while (hWnd) {
04791           if (::GetMenu(hWnd)) {
04792             hasNativeMenu = PR_TRUE;
04793             break;
04794           }
04795           hWnd = ::GetParent(hWnd);
04796         }
04797         result = !hasNativeMenu;
04798       }
04799 #endif
04800       DispatchPendingEvents();
04801       break;
04802 
04803     // say we've dealt with erase background if widget does
04804     // not need auto-erasing
04805     case WM_ERASEBKGND:
04806       if (! AutoErase()) {
04807         *aRetValue = 1;
04808         result = PR_TRUE;
04809       }
04810       break;
04811 
04812     case WM_GETDLGCODE:
04813       *aRetValue = DLGC_WANTALLKEYS;
04814       result = PR_TRUE;
04815       break;
04816 
04817     case WM_MOUSEMOVE:
04818       //RelayMouseEvent(msg,wParam, lParam);
04819 
04820       // Suppress dispatch of pending events
04821       // when mouse moves are generated by widget
04822       // creation instead of user input.
04823     {
04824       POINT mp;
04825       DWORD pos = ::GetMessagePos();
04826       mp.x      = GET_X_LPARAM(pos);
04827       mp.y      = GET_Y_LPARAM(pos);
04828       PRBool userMovedMouse = PR_FALSE;
04829       if ((gLastMouseMovePoint.x != mp.x) || (gLastMouseMovePoint.y != mp.y)) {
04830         userMovedMouse = PR_TRUE;
04831       }
04832 
04833       result = DispatchMouseEvent(NS_MOUSE_MOVE, wParam);
04834       if (userMovedMouse) {
04835         DispatchPendingEvents();
04836       }
04837     }
04838     break;
04839 
04840     case WM_LBUTTONDOWN:
04841       //SetFocus(); // this is bad
04842       //RelayMouseEvent(msg,wParam, lParam);
04843     {
04844 #ifdef WINCE
04845       if (!gRollupListener && !gRollupWidget) 
04846       {
04847         SHRGINFO  shrg;
04848         shrg.cbSize = sizeof(shrg);
04849         shrg.hwndClient = mWnd;
04850         shrg.ptDown.x = LOWORD(lParam);
04851         shrg.ptDown.y = HIWORD(lParam);
04852         shrg.dwFlags = SHRG_RETURNCMD;
04853         if (SHRecognizeGesture(&shrg)  == GN_CONTEXTMENU)
04854         {
04855           DispatchMouseEvent(NS_MOUSE_RIGHT_BUTTON_DOWN, wParam);
04856           DispatchMouseEvent(NS_MOUSE_RIGHT_BUTTON_UP, wParam);
04857           result = 0;
04858           break;
04859         }
04860       }
04861 #endif 
04862       // check whether IME window do mouse operation
04863       if (IMEMouseHandling(NS_MOUSE_LEFT_BUTTON_DOWN, IMEMOUSE_LDOWN, lParam))
04864         break;
04865       result = DispatchMouseEvent(NS_MOUSE_LEFT_BUTTON_DOWN, wParam);
04866       DispatchPendingEvents();
04867     }
04868     break;
04869 
04870     case WM_LBUTTONUP:
04871       //RelayMouseEvent(msg,wParam, lParam);
04872       result = DispatchMouseEvent(NS_MOUSE_LEFT_BUTTON_UP, wParam);
04873       DispatchPendingEvents();
04874       break;
04875 
04876     case WM_CONTEXTMENU:
04877     {
04878       // if the context menu is brought up from the keyboard, |lParam|
04879       // will be maxlong. Send a different event msg instead.
04880       PRUint32 msg = (lParam == 0xFFFFFFFF) ? NS_CONTEXTMENU_KEY : NS_CONTEXTMENU;
04881       result = DispatchMouseEvent(msg, wParam);
04882     }
04883     break;
04884 
04885     case WM_LBUTTONDBLCLK:
04886       result = DispatchMouseEvent(NS_MOUSE_LEFT_DOUBLECLICK, wParam);
04887       break;
04888 
04889     case WM_MBUTTONDOWN:
04890     {
04891       // check whether IME window do mouse operation
04892       if (IMEMouseHandling(NS_MOUSE_MIDDLE_BUTTON_DOWN, IMEMOUSE_MDOWN, lParam))
04893         break;
04894       result = DispatchMouseEvent(NS_MOUSE_MIDDLE_BUTTON_DOWN, wParam);
04895       DispatchPendingEvents();
04896     }
04897     break;
04898 
04899     case WM_MBUTTONUP:
04900       result = DispatchMouseEvent(NS_MOUSE_MIDDLE_BUTTON_UP, wParam);
04901       DispatchPendingEvents();
04902       break;
04903 
04904     case WM_MBUTTONDBLCLK:
04905       result = DispatchMouseEvent(NS_MOUSE_MIDDLE_BUTTON_DOWN, wParam);
04906       break;
04907 
04908     case WM_RBUTTONDOWN:
04909     {
04910       // check whether IME window do mouse operation
04911       if (IMEMouseHandling(NS_MOUSE_RIGHT_BUTTON_DOWN, IMEMOUSE_RDOWN, lParam))
04912         break;
04913       result = DispatchMouseEvent(NS_MOUSE_RIGHT_BUTTON_DOWN, wParam);
04914       DispatchPendingEvents();
04915     }
04916     break;
04917 
04918     case WM_RBUTTONUP:
04919       result = DispatchMouseEvent(NS_MOUSE_RIGHT_BUTTON_UP, wParam);
04920       DispatchPendingEvents();
04921       break;
04922 
04923     case WM_RBUTTONDBLCLK:
04924       result = DispatchMouseEvent(NS_MOUSE_RIGHT_DOUBLECLICK, wParam);
04925       break;
04926 
04927     case WM_APPCOMMAND:
04928     {
04929       PRUint32 appCommand = GET_APPCOMMAND_LPARAM(lParam);
04930 
04931       switch (appCommand)
04932       {
04933         case APPCOMMAND_BROWSER_BACKWARD:
04934         case APPCOMMAND_BROWSER_FORWARD:
04935         case APPCOMMAND_BROWSER_REFRESH:
04936         case APPCOMMAND_BROWSER_STOP:
04937           DispatchAppCommandEvent(appCommand);
04938           // tell the driver that we handled the event
04939           *aRetValue = 1;
04940           result = PR_TRUE;
04941           break;
04942       }
04943       // default = PR_FALSE - tell the driver that the event was not handled
04944     }
04945     break;
04946 
04947     case WM_HSCROLL:
04948     case WM_VSCROLL:
04949       // check for the incoming nsWindow handle to be null in which case
04950       // we assume the message is coming from a horizontal scrollbar inside
04951       // a listbox and we don't bother processing it (well, we don't have to)
04952       if (lParam) {
04953         nsWindow* scrollbar = GetNSWindowPtr((HWND)lParam);
04954 
04955         if (scrollbar) {
04956           result = scrollbar->OnScroll(LOWORD(wParam), (short)HIWORD(wParam));
04957         }
04958       }
04959       break;
04960 
04961     case WM_CTLCOLORLISTBOX:
04962     case WM_CTLCOLOREDIT:
04963     case WM_CTLCOLORBTN:
04964     //case WM_CTLCOLORSCROLLBAR: //XXX causes the scrollbar to be drawn incorrectly
04965     case WM_CTLCOLORSTATIC:
04966       if (lParam) {
04967         nsWindow* control = GetNSWindowPtr((HWND)lParam);
04968           if (control) {
04969             control->SetUpForPaint((HDC)wParam);
04970             *aRetValue = (LPARAM)control->OnControlColor();
04971           }
04972       }
04973 
04974       result = PR_TRUE;
04975       break;
04976 
04977     case WM_ACTIVATE:
04978       if (mEventCallback) {
04979         PRInt32 fActive = LOWORD(wParam);
04980 
04981         if (WA_INACTIVE == fActive) {
04982           gJustGotDeactivate = PR_TRUE;
04983           if (mIsTopWidgetWindow)
04984             mLastKeyboardLayout = gKeyboardLayout;
04985         } else {
04986           gJustGotActivate = PR_TRUE;
04987           nsMouseEvent event(PR_TRUE, NS_MOUSE_ACTIVATE, this,
04988                              nsMouseEvent::eReal);
04989           InitEvent(event);
04990 
04991           event.acceptActivation = PR_TRUE;
04992 
04993           PRBool result = DispatchWindowEvent(&event);
04994           NS_RELEASE(event.widget);
04995 
04996           if (event.acceptActivation)
04997             *aRetValue = MA_ACTIVATE;
04998           else
04999             *aRetValue = MA_NOACTIVATE;
05000 
05001           if (gSwitchKeyboardLayout && mLastKeyboardLayout)
05002             ActivateKeyboardLayout(mLastKeyboardLayout, 0);
05003         }
05004       }
05005       break;
05006 
05007 #ifndef WINCE
05008     case WM_WINDOWPOSCHANGING:
05009     {
05010       LPWINDOWPOS info = (LPWINDOWPOS) lParam;
05011       // enforce local z-order rules
05012       if (!(info->flags & SWP_NOZORDER))
05013         ConstrainZLevel(&info->hwndInsertAfter);
05014       // prevent rude external programs from making hidden window visible
05015       if (mWindowType == eWindowType_invisible)
05016         info->flags &= ~SWP_SHOWWINDOW;
05017     }
05018     break;
05019 #endif
05020 
05021     case WM_SETFOCUS:
05022 #ifdef WINCE
05023       {
05024         // Get current input context
05025         HIMC hC = ImmGetContext(mWnd);           
05026         // Open the IME 
05027         ImmSetOpenStatus(hC, TRUE);
05028         // Set "multi-press" input mode
05029         ImmEscapeW(NULL, hC, IME_ESC_SET_MODE, (LPVOID)IM_SPELL);
05030       }
05031 #endif
05032 
05033       result = DispatchFocus(NS_GOTFOCUS, isMozWindowTakingFocus);
05034       if (gJustGotActivate) {
05035         gJustGotActivate = PR_FALSE;
05036         gJustGotDeactivate = PR_FALSE;
05037         result = DispatchFocus(NS_ACTIVATE, isMozWindowTakingFocus);
05038       }
05039 #ifdef ACCESSIBILITY
05040       if (nsWindow::gIsAccessibilityOn) {
05041         // Create it for the first time so that it can start firing events
05042         nsCOMPtr<nsIAccessible> rootAccessible = GetRootAccessible();
05043       }
05044 #endif
05045 
05046 #ifdef WINCE
05047       // On Windows CE, we have a window that overlaps
05048       // the ISP button.  In this case, we should always
05049       // try to hide it when we are activated
05050       if (mWindowType == eWindowType_dialog || mWindowType == eWindowType_toplevel) {
05051         
05052         // This should work on all platforms, but it doesn't...
05053         SHFullScreen(mWnd, SHFS_HIDESIPBUTTON);
05054         
05055         // So do it the hard way....
05056         HWND hWndSIP = FindWindow( _T( "MS_SIPBUTTON" ), NULL );
05057         if (hWndSIP) 
05058         {
05059           ShowWindow( hWndSIP, SW_HIDE );
05060           SetWindowPos(hWndSIP, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
05061         }
05062       }
05063 #endif
05064       break;
05065 
05066     case WM_KILLFOCUS:
05067 #ifdef WINCE
05068       {
05069       // Get current input context
05070       HIMC hC = ImmGetContext(mWnd);
05071       // Close the IME 
05072       if (hC)
05073         ImmSetOpenStatus(hC, FALSE);
05074       }
05075 #endif
05076       WCHAR className[kMaxClassNameLength];
05077       nsToolkit::mGetClassName((HWND)wParam, className, kMaxClassNameLength);
05078       if (wcscmp(className, kWClassNameUI) &&
05079           wcscmp(className, kWClassNameContent) &&
05080           wcscmp(className, kWClassNameContentFrame) &&
05081           wcscmp(className, kWClassNameGeneral)) {
05082         isMozWindowTakingFocus = PR_FALSE;
05083       }
05084       if (gJustGotDeactivate) {
05085         gJustGotDeactivate = PR_FALSE;
05086         result = DispatchFocus(NS_DEACTIVATE, isMozWindowTakingFocus);
05087       }
05088       result = DispatchFocus(NS_LOSTFOCUS, isMozWindowTakingFocus);
05089       break;
05090 
05091     case WM_WINDOWPOSCHANGED:
05092     {
05093 #ifdef MOZ_XUL
05094       if (mIsTopTranslucent && !IsAlphaTranslucencySupported() && w9x.mPerformingSetWindowRgn)
05095       {
05096         result = PR_FALSE;    // Ignore events generated by SetWindowRgn
05097         break;
05098       }
05099 #endif
05100 
05101       WINDOWPOS *wp = (LPWINDOWPOS)lParam;
05102 
05103       // We only care about a resize, so filter out things like z-order
05104       // changes. Note: there's a WM_MOVE handler above which is why we're
05105       // not handling them here...
05106       if (0 == (wp->flags & SWP_NOSIZE)) {
05107         // XXX Why are we using the client size area? If the size notification
05108         // is for the client area then the origin should be (0,0) and not
05109         // the window origin in screen coordinates...
05110         RECT r;
05111         ::GetWindowRect(mWnd, &r);
05112         PRInt32 newWidth, newHeight;
05113         newWidth = PRInt32(r.right - r.left);
05114         newHeight = PRInt32(r.bottom - r.top);
05115         nsRect rect(wp->x, wp->y, newWidth, newHeight);
05116         if (newWidth > mLastSize.width)
05117         {
05118           RECT drect;
05119 
05120           //getting wider
05121           drect.left = wp->x + mLastSize.width;
05122           drect.top = wp->y;
05123           drect.right = drect.left + (newWidth - mLastSize.width);
05124           drect.bottom = drect.top + newHeight;
05125 
05126           ::RedrawWindow(mWnd, &drect, NULL,
05127                          RDW_INVALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ERASENOW | RDW_ALLCHILDREN);
05128         }
05129         if (newHeight > mLastSize.height)
05130         {
05131           RECT drect;
05132 
05133           //getting taller
05134           drect.left = wp->x;
05135           drect.top = wp->y + mLastSize.height;
05136           drect.right = drect.left + newWidth;
05137           drect.bottom = drect.top + (newHeight - mLastSize.height);
05138 
05139           ::RedrawWindow(mWnd, &drect, NULL,
05140                          RDW_INVALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ERASENOW | RDW_ALLCHILDREN);
05141         }
05142 
05143 #ifdef MOZ_XUL
05144         if (mIsTranslucent)
05145           ResizeTranslucentWindow(newWidth, newHeight);
05146 #endif
05147         mBounds.width  = newWidth;
05148         mBounds.height = newHeight;
05149         mLastSize.width = newWidth;
05150         mLastSize.height = newHeight;
05152 
05153         // If we're being minimized, don't send the resize event to Gecko because
05154         // it will cause the scrollbar in the content area to go away and we'll
05155         // forget the scroll position of the page.
05156         if ( !newWidth && !newHeight ) {
05157           result = PR_FALSE;
05158           break;
05159         }
05160 
05161         // recalculate the width and height
05162         // this time based on the client area
05163         if (::GetClientRect(mWnd, &r)) {
05164           rect.width  = PRInt32(r.right - r.left);
05165           rect.height = PRInt32(r.bottom - r.top);
05166         }
05167         result = OnResize(rect);
05168       }
05169 
05170       /* handle size mode changes
05171          (the framechanged message seems a handy place to hook in,
05172          because it happens early enough (WM_SIZE is too late) and
05173          because in testing it seems an accurate harbinger of
05174          an impending min/max/restore change (WM_NCCALCSIZE would
05175          also work, but it's also sent when merely resizing.)) */
05176       if (wp->flags & SWP_FRAMECHANGED && ::IsWindowVisible(mWnd)) {
05177         WINDOWPLACEMENT pl;
05178         pl.length = sizeof(pl);
05179         ::GetWindowPlacement(mWnd, &pl);
05180 
05181         nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, this);
05182         if (pl.showCmd == SW_SHOWMAXIMIZED)
05183           event.mSizeMode = nsSizeMode_Maximized;
05184         else if (pl.showCmd == SW_SHOWMINIMIZED)
05185           event.mSizeMode = nsSizeMode_Minimized;
05186         else
05187           event.mSizeMode = nsSizeMode_Normal;
05188         InitEvent(event);
05189 
05190         result = DispatchWindowEvent(&event);
05191 
05192         if (pl.showCmd == SW_SHOWMINIMIZED) {
05193           // Deactivate
05194           WCHAR className[kMaxClassNameLength];
05195           nsToolkit::mGetClassName((HWND)wParam, className, kMaxClassNameLength);
05196           if (wcscmp(className, kWClassNameUI) &&
05197               wcscmp(className, kWClassNameContent) &&
05198               wcscmp(className, kWClassNameContentFrame) &&
05199               wcscmp(className, kWClassNameGeneral)) {
05200             isMozWindowTakingFocus = PR_FALSE;
05201           }
05202           gJustGotDeactivate = PR_FALSE;
05203           result = DispatchFocus(NS_DEACTIVATE, isMozWindowTakingFocus);
05204         } else if (pl.showCmd == SW_SHOWNORMAL){
05205           // Make sure we're active
05206           result = DispatchFocus(NS_GOTFOCUS, PR_TRUE);
05207           result = DispatchFocus(NS_ACTIVATE, PR_TRUE);
05208         }
05209 
05210         NS_RELEASE(event.widget);
05211       }
05212     }
05213     break;
05214 
05215     case WM_SETTINGCHANGE:
05216 #ifdef WINCE
05217       if (wParam == SPI_SETWORKAREA)
05218       {
05219         RECT workArea;
05220         ::SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
05221      
05222         SetWindowPos(mWnd, 
05223                      nsnull, 
05224                      workArea.left, 
05225                      workArea.top, 
05226                      workArea.right, 
05227                      workArea.bottom, 
05228                      SWP_NOACTIVATE | SWP_NOOWNERZORDER);
05229       }
05230       else
05231 #endif
05232         getWheelInfo = PR_TRUE;
05233       break;
05234 
05235     case WM_PALETTECHANGED:
05236       if ((HWND)wParam == mWnd) {
05237         // We caused the WM_PALETTECHANGED message so avoid realizing
05238         // another foreground palette
05239         result = PR_TRUE;
05240         break;
05241       }
05242       // fall thru...
05243 
05244     case WM_QUERYNEWPALETTE:      // this window is about to become active
05245       mContext->GetPaletteInfo(palInfo);
05246       if (palInfo.isPaletteDevice && palInfo.palette) {
05247         HDC hDC = ::GetDC(mWnd);
05248         HPALETTE hOldPal = ::SelectPalette(hDC, (HPALETTE)palInfo.palette, TRUE);
05249 
05250         // Realize the drawing palette
05251         int i = ::RealizePalette(hDC);
05252 
05253 #ifdef DEBUG
05254         //printf("number of colors that changed=%d\n",i);
05255 #endif
05256         // we should always invalidate.. because the lookup may have changed
05257         ::InvalidateRect(mWnd, (LPRECT)NULL, TRUE);
05258 
05259         ::ReleaseDC(mWnd, hDC);
05260         *aRetValue = TRUE;
05261       }
05262       result = PR_TRUE;
05263       break;
05264 
05265     case WM_IME_STARTCOMPOSITION:
05266       result = OnIMEStartComposition();
05267       break;
05268 
05269     case WM_IME_COMPOSITION:
05270       result = OnIMEComposition(lParam);
05271       break;
05272 
05273     case WM_IME_ENDCOMPOSITION:
05274       result = OnIMEEndComposition();
05275       break;
05276 
05277     case WM_IME_CHAR:
05278       // We receive double byte char code. No need to worry about the <Shift>
05279       mIsShiftDown = PR_FALSE;
05280       result = OnIMEChar((BYTE)(wParam >> 8), (BYTE)(wParam & 0x00FF), lParam);
05281       break;
05282 
05283     case WM_IME_NOTIFY:
05284       result = OnIMENotify(wParam, lParam, aRetValue);
05285       break;
05286 
05287     // This is a Window 98/2000 only message
05288     case WM_IME_REQUEST:
05289       result = OnIMERequest(wParam, lParam, aRetValue, nsToolkit::mIsNT);
05290       break;
05291 
05292     case WM_IME_SELECT:
05293       result = OnIMESelect(wParam, (WORD)(lParam & 0x0FFFF));
05294       break;
05295 
05296     case WM_IME_SETCONTEXT:
05297       result = OnIMESetContext(wParam, lParam);
05298       break;
05299 
05300 #ifndef WINCE
05301     case WM_INPUTLANGCHANGEREQUEST:
05302       *aRetValue = TRUE;
05303       result = PR_FALSE;
05304       break;
05305 
05306     case WM_INPUTLANGCHANGE:
05307       result = OnInputLangChange((HKL)lParam, aRetValue);
05308       break;
05309 
05310     case WM_DROPFILES:
05311     {
05312 #if 0
05313       HDROP hDropInfo = (HDROP) wParam;
05314       UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
05315 
05316       for (UINT iFile = 0; iFile < nFiles; iFile++) {
05317         TCHAR szFileName[_MAX_PATH];
05318         ::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
05319 #ifdef DEBUG
05320         printf("szFileName [%s]\n", szFileName);
05321 #endif  // DEBUG
05322         nsAutoString fileStr(szFileName);
05323         nsEventStatus status;
05324         nsDragDropEvent event(NS_DRAGDROP_EVENT, this);
05325         InitEvent(event);
05326         event.mType      = nsDragDropEventStatus_eDrop;
05327         event.mIsFileURL = PR_FALSE;
05328         event.mURL       = fileStr.get();
05329         DispatchEvent(&event, status);
05330         NS_RELEASE(event.widget);
05331       }
05332 #endif // 0
05333     }
05334     break;
05335 #endif // WINCE
05336 
05337     case WM_DESTROYCLIPBOARD:
05338     {
05339       nsIClipboard* clipboard;
05340       nsresult rv = CallGetService(kCClipboardCID, &clipboard);
05341       clipboard->EmptyClipboard(nsIClipboard::kGlobalClipboard);
05342       NS_RELEASE(clipboard);
05343     }
05344     break;
05345 
05346 #ifdef ACCESSIBILITY
05347     case WM_GETOBJECT:
05348     {
05349       LRESULT lAcc = 0;
05350       IAccessible *msaaAccessible = NULL;
05351       if (lParam == OBJID_CLIENT) { // oleacc.dll will be loaded dynamically
05352         nsCOMPtr<nsIAccessible> rootAccessible = GetRootAccessible(); // Held by a11y cache
05353         if (rootAccessible) {
05354           rootAccessible->GetNativeInterface((void**)&msaaAccessible); // does an addref
05355         }
05356       }
05357       else if (lParam == OBJID_CARET) {  // each root accessible owns a caret accessible
05358         nsCOMPtr<nsIAccessible> rootAccessible = GetRootAccessible();  // Held by a11y cache
05359         nsCOMPtr<nsIAccessibleDocument> accDoc(do_QueryInterface(rootAccessible));
05360         if (accDoc) {
05361           nsCOMPtr<nsIAccessible> accessibleCaret;
05362           accDoc->GetCaretAccessible(getter_AddRefs(accessibleCaret));
05363           if (accessibleCaret) {
05364             accessibleCaret->GetNativeInterface((void**)&msaaAccessible);
05365           }
05366         }
05367       }
05368       if (msaaAccessible) {
05369         lAcc = LresultFromObject(IID_IAccessible, wParam, msaaAccessible); // does an addref
05370         msaaAccessible->Release(); // release extra addref
05371       }
05372       return (*aRetValue = lAcc) != 0;
05373     }
05374 #endif
05375 
05376 #ifndef WINCE
05377     case WM_SYSCOMMAND:
05378       // prevent Windows from trimming the working set. bug 76831
05379       if (!gTrimOnMinimize && wParam == SC_MINIMIZE) {
05380         ::ShowWindow(mWnd, SW_SHOWMINIMIZED);
05381         result = PR_TRUE;
05382       }
05383       break;
05384 #endif
05385 
05386 
05387 #ifdef WINCE
05388   case WM_HIBERNATE:        
05389     nsMemory::HeapMinimize(PR_TRUE);
05390     break;
05391 #endif
05392     default:
05393     {
05394       // Handle both flavors of mouse wheel events.
05395 #ifndef WINCE
05396       if ((msg == WM_MOUSEWHEEL) || (msg == uMSH_MOUSEWHEEL) ||
05397           (msg == WM_MOUSEHWHEEL))
05398       {
05399         static int iDeltaPerLine, iDeltaPerChar;
05400         static ULONG ulScrollLines, ulScrollChars = 1;
05401         static int currentVDelta, currentHDelta;
05402         static HWND currentWindow = 0;
05403 
05404         PRBool isVertical = (msg == WM_MOUSEWHEEL) || (msg == uMSH_MOUSEWHEEL);
05405 
05406         // Get mouse wheel metrics (but only once).
05407         if (getWheelInfo) {
05408           getWheelInfo = PR_FALSE;
05409 
05410           // This needs to be done differently for Win95 than Win98/NT
05411           // Taken from sample code in MS Intellimouse SDK
05412           // http://www.microsoft.com/Mouse/intellimouse/sdk/sdkmessaging.htm
05413 
05414           OSVERSIONINFO osversion;
05415           memset(&osversion, 0, sizeof(OSVERSIONINFO));
05416           osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
05417           GetVersionEx(&osversion);
05418 
05419           if ((osversion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
05420               (osversion.dwMajorVersion == 4) &&
05421               (osversion.dwMinorVersion == 0))
05422           {
05423 #ifndef __MINGW32__
05424             // This is the Windows 95 case
05425             HWND hdlMsWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE);
05426             if (hdlMsWheel) {
05427               UINT uiMsh_MsgScrollLines = RegisterWindowMessage(MSH_SCROLL_LINES);
05428               if (uiMsh_MsgScrollLines) {
05429                 ulScrollLines = (int) SendMessage(hdlMsWheel, uiMsh_MsgScrollLines, 0, 0);
05430               }
05431             }
05432 #endif // __MINGW32__
05433           }
05434           else if (osversion.dwMajorVersion >= 4) {
05435             // This is the Win98/NT4/Win2K case
05436             SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &ulScrollLines, 0);
05437           }
05438 
05439           // ulScrollLines usually equals 3 or 0 (for no scrolling)
05440           // WHEEL_DELTA equals 120, so iDeltaPerLine will be 40.
05441 
05442           // However, if ulScrollLines > WHEEL_DELTA, we assume that
05443           // the mouse driver wants a page scroll.  The docs state that
05444           // ulScrollLines should explicitly equal WHEEL_PAGESCROLL, but
05445           // since some mouse drivers use an arbitrary large number instead,
05446           // we have to handle that as well.
05447 
05448           iDeltaPerLine = 0;
05449           if (ulScrollLines) {
05450             if (ulScrollLines <= WHEEL_DELTA) {
05451               iDeltaPerLine = WHEEL_DELTA / ulScrollLines;
05452             } else {
05453               ulScrollLines = WHEEL_PAGESCROLL;
05454             }
05455           }
05456 
05457           if (!SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
05458                                     &ulScrollChars, 0)) {
05459             // Note that we may always fail to get the value before Win Vista.
05460             ulScrollChars = 1;
05461           }
05462 
05463           iDeltaPerChar = 0;
05464           if (ulScrollChars) {
05465             if (ulScrollChars <= WHEEL_DELTA) {
05466               iDeltaPerChar = WHEEL_DELTA / ulScrollChars;
05467             } else {
05468               ulScrollChars = WHEEL_PAGESCROLL;
05469             }
05470           }
05471         }
05472 
05473         if ((isVertical  && ulScrollLines != WHEEL_PAGESCROLL && !iDeltaPerLine) ||
05474             (!isVertical && ulScrollChars != WHEEL_PAGESCROLL && !iDeltaPerChar))
05475           return 0;
05476 
05477         // The mousewheel event will be dispatched to the toplevel
05478         // window.  We need to give it to the child window
05479 
05480         POINT point;
05481         point.x = GET_X_LPARAM(lParam);
05482         point.y = GET_Y_LPARAM(lParam);
05483         HWND destWnd = ::WindowFromPoint(point);
05484 
05485         // Since we receive mousewheel events for as long as
05486         // we are focused, it's entirely possible that there
05487         // is another app's window or no window under the
05488         // pointer.
05489 
05490         if (!destWnd) {
05491           // No window is under the pointer
05492           break;
05493         }
05494 
05495         // We don't care about windows belonging to other processes.
05496         DWORD processId = 0;
05497         GetWindowThreadProcessId(destWnd, &processId);
05498         if (processId != GetCurrentProcessId())
05499         {
05500           // Somebody elses window
05501           break;
05502         }
05503 
05504         LONG proc = nsToolkit::mGetWindowLong(destWnd, GWL_WNDPROC);
05505         if (proc != (LONG)&nsWindow::WindowProc) {
05506           // Some other app, or a plugin window.
05507           // Windows directs WM_MOUSEWHEEL to the focused window.
05508           // However, Mozilla does not like plugins having focus, so a
05509           // Mozilla window (ie, the plugin's parent (us!) has focus.)
05510           // Therefore, plugins etc _should_ get first grab at the
05511           // message, but this focus vaguary means the plugin misses
05512           // out. If the window is a child of ours, forward it on.
05513           // Determine if a child by walking the parent list until
05514           // we find a parent matching our wndproc.
05515           HWND parentWnd = ::GetParent(destWnd);
05516           while (parentWnd) {
05517             LONG parentWndProc = ::GetClassLong(parentWnd, GCL_WNDPROC);
05518             if (parentWndProc == (LONG)&nsWindow::DefaultWindowProc || parentWndProc == (LONG)&nsWindow::WindowProc) {
05519               // We have a child window - quite possibly a plugin window.
05520               // However, not all plugins are created equal - some will handle this message themselves,
05521               // some will forward directly back to us, while others will call DefWndProc, which
05522               // itself still forwards back to us.
05523               // So if we have sent it once, we need to handle it ourself.
05524               if (mIsInMouseWheelProcessing) {
05525                 destWnd = parentWnd;
05526               } else {
05527                 // First time we have seen this message.
05528                 // Call the child - either it will consume it, or
05529                 // it will wind it's way back to us, triggering the destWnd case above.
05530                 // either way, when the call returns, we are all done with the message,
05531                 mIsInMouseWheelProcessing = PR_TRUE;
05532                 if (0 == nsToolkit::mSendMessage(destWnd, msg, wParam, lParam)) {
05533                   result = PR_TRUE; // consumed - don't call DefWndProc
05534                 }
05535                 destWnd = nsnull;
05536                 mIsInMouseWheelProcessing = PR_FALSE;
05537               }
05538               break; // stop parent search
05539             }
05540             parentWnd = ::GetParent(parentWnd);
05541           } // while parentWnd
05542         }
05543         if (destWnd == nsnull)
05544           break; // done with this message.
05545         if (destWnd != mWnd) {
05546           nsWindow* destWindow = GetNSWindowPtr(destWnd);
05547           if (destWindow) {
05548             return destWindow->ProcessMessage(msg, wParam, lParam, aRetValue);
05549           }
05550 #ifdef DEBUG
05551           else
05552             printf("WARNING: couldn't get child window for MW event\n");
05553 #endif
05554         }
05555 
05556         // We should cancel the surplus delta if the current window is not
05557         // same as previous.
05558         if (currentWindow != mWnd) {
05559           currentVDelta = 0;
05560           currentHDelta = 0;
05561           currentWindow = mWnd;
05562         }
05563 
05564         nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
05565         scrollEvent.delta = 0;
05566         if (isVertical) {
05567           scrollEvent.scrollFlags = nsMouseScrollEvent::kIsVertical;
05568           int verticalAmount =
05569             msg == WM_MOUSEWHEEL ? (short) HIWORD (wParam) : (int) wParam;
05570           if (ulScrollLines == WHEEL_PAGESCROLL) {
05571             scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
05572             scrollEvent.delta = verticalAmount > 0 ? -1 : 1;
05573           } else {
05574             currentVDelta -= verticalAmount;
05575             if (PR_ABS(currentVDelta) >= iDeltaPerLine) {
05576               scrollEvent.delta = currentVDelta / iDeltaPerLine;
05577               currentVDelta %= iDeltaPerLine;
05578             }
05579           }
05580         } else {
05581           scrollEvent.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
05582           if (ulScrollChars == WHEEL_PAGESCROLL) {
05583             scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
05584             scrollEvent.delta = (((short) HIWORD (wParam)) > 0) ? 1 : -1;
05585           } else {
05586             currentHDelta += (short) HIWORD (wParam);
05587             if (PR_ABS(currentHDelta) >= iDeltaPerChar) {
05588               scrollEvent.delta = currentHDelta / iDeltaPerChar;
05589               currentHDelta %= iDeltaPerChar;
05590             }
05591           }
05592         }
05593 
05594         scrollEvent.isShift   = IS_VK_DOWN(NS_VK_SHIFT);
05595         scrollEvent.isControl = IS_VK_DOWN(NS_VK_CONTROL);
05596         scrollEvent.isMeta    = PR_FALSE;
05597         scrollEvent.isAlt     = IS_VK_DOWN(NS_VK_ALT);
05598         InitEvent(scrollEvent);
05599         if (nsnull != mEventCallback) {
05600           result = DispatchWindowEvent(&scrollEvent);
05601         }
05602         NS_RELEASE(scrollEvent.widget);
05603         // Note that we should return zero if we process WM_MOUSEWHEEL.
05604         // But if we process WM_MOUSEHWHEEL, we should return non-zero.
05605         if (result)
05606           *aRetValue = isVertical ? 0 : TRUE;
05607       } // WM_MOUSEWHEEL || uMSH_MOUSEWHEEL || WM_MOUSEHWHEEL
05608 
05609       //
05610       // reconvert message for Windows 95 / NT 4.0
05611       //
05612       // See the following URL
05613       //  http://msdn.microsoft.com/library/specs/msimeif_perimeinterfaces.htm#WM_MSIME_RECONVERT
05614       //  http://www.justsystem.co.jp/tech/atok/api12_04.html#4_11
05615 
05616       else if ((msg == nsWindow::uWM_ATOK_RECONVERT) || (msg == nsWindow::uWM_MSIME_RECONVERT)) {
05617         result = OnIMERequest(wParam, lParam, aRetValue, PR_TRUE);
05618       }
05619       else if (msg == nsWindow::uWM_HEAP_DUMP) {
05620         // XXX for now we use c:\heapdump.txt until we figure out how to
05621         // XXX pass in message parameters.
05622         HeapDump("c:\\heapdump.txt", "whatever");
05623         result = PR_TRUE;
05624       }
05625 #endif // WINCE
05626 
05627     }
05628     break;
05629   }
05630 
05631   //*aRetValue = result;
05632   if (mWnd) {
05633     return result;
05634   }
05635   else {
05636     //Events which caused mWnd destruction and aren't consumed
05637     //will crash during the Windows default processing.
05638     return PR_TRUE;
05639   }
05640 }
05641 
05642 //-------------------------------------------------------------------------
05643 //
05644 // return the window class name and initialize the class if needed
05645 //
05646 //-------------------------------------------------------------------------
05647 
05648 #define CS_XP_DROPSHADOW       0x00020000
05649 
05650 LPCWSTR nsWindow::WindowClassW()
05651 {
05652   if (!nsWindow::sIsRegistered) {
05653     WNDCLASSW wc;
05654 
05655 //    wc.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
05656     wc.style         = CS_DBLCLKS;
05657     wc.lpfnWndProc   = nsWindow::DefaultWindowProc;
05658     wc.cbClsExtra    = 0;
05659     wc.cbWndExtra    = 0;
05660     wc.hInstance     = nsToolkit::mDllInstance;
05661     // XXX : we don't need LoadIconW for now (see bug 171349, comment 181)
05662     wc.hIcon         = ::LoadIcon(::GetModuleHandle(NULL), IDI_APPLICATION);
05663     wc.hCursor       = NULL;
05664     wc.hbrBackground = mBrush;
05665     wc.lpszMenuName  = NULL;
05666     wc.lpszClassName = kWClassNameHidden;
05667 
05668     BOOL succeeded =  nsToolkit::mRegisterClass(&wc) != 0;
05669     nsWindow::sIsRegistered = succeeded;
05670 
05671     wc.lpszClassName = kWClassNameContentFrame;
05672     if (!nsToolkit::mRegisterClass(&wc)) {
05673       nsWindow::sIsRegistered = FALSE;
05674     }
05675 
05676     wc.lpszClassName = kWClassNameContent;
05677     if (!nsToolkit::mRegisterClass(&wc)) {
05678       nsWindow::sIsRegistered = FALSE;
05679     }
05680 
05681     wc.lpszClassName = kWClassNameUI;
05682     if (!nsToolkit::mRegisterClass(&wc)) {
05683       nsWindow::sIsRegistered = FALSE;
05684     }
05685 
05686     wc.lpszClassName = kWClassNameGeneral;
05687     ATOM generalClassAtom = nsToolkit::mRegisterClass(&wc);
05688     if (!generalClassAtom) {
05689       nsWindow::sIsRegistered = FALSE;
05690     }
05691 
05692     // Call FilterClientWindows method since it enables ActiveIME on CJK Windows
05693     if (nsToolkit::gAIMMApp && generalClassAtom)
05694       nsToolkit::gAIMMApp->FilterClientWindows(&generalClassAtom, 1);
05695   }
05696 
05697   if (mWindowType == eWindowType_invisible) {
05698     return kWClassNameHidden;
05699   }
05700   if (mContentType == eContentTypeContent) {
05701     return kWClassNameContent;
05702   }
05703   if (mContentType == eContentTypeContentFrame) {
05704     return kWClassNameContentFrame;
05705   }
05706   if (mContentType == eContentTypeUI) {
05707     return kWClassNameUI;
05708   }
05709   return kWClassNameGeneral;
05710 }
05711 
05712 LPCWSTR nsWindow::WindowPopupClassW()
05713 {
05714   const LPCWSTR className = L"MozillaDropShadowWindowClass";
05715 
05716   if (!nsWindow::sIsPopupClassRegistered) {
05717     WNDCLASSW wc;
05718 
05719     wc.style = CS_DBLCLKS | CS_XP_DROPSHADOW;
05720     wc.lpfnWndProc   = nsWindow::DefaultWindowProc;
05721     wc.cbClsExtra    = 0;
05722     wc.cbWndExtra    = 0;
05723     wc.hInstance     = nsToolkit::mDllInstance;
05724     // XXX : we don't need LoadIconW for now (see bug 171349, comment 181)
05725     wc.hIcon         = ::LoadIcon(::GetModuleHandle(NULL), IDI_APPLICATION);
05726     wc.hCursor       = NULL;
05727     wc.hbrBackground = mBrush;
05728     wc.lpszMenuName  = NULL;
05729     wc.lpszClassName = className;
05730 
05731     nsWindow::sIsPopupClassRegistered = nsToolkit::mRegisterClass(&wc);
05732     if (!nsWindow::sIsPopupClassRegistered) {
05733       // For older versions of Win32 (i.e., not XP), the registration will
05734       // fail, so we have to re-register without the CS_XP_DROPSHADOW flag.
05735       wc.style = CS_DBLCLKS;
05736       nsWindow::sIsPopupClassRegistered = nsToolkit::mRegisterClass(&wc);
05737     }
05738   }
05739 
05740   return className;
05741 }
05742 
05743 LPCSTR nsWindow::WindowClass()
05744 {
05745   // Call into the wide version to make sure things get
05746   // registered properly.
05747   LPCWSTR classNameW = WindowClassW();
05748 
05749   // XXX: The class name used here must be kept in sync with
05750   //      the classname used in WindowClassW();
05751 
05752   if (classNameW == kWClassNameHidden) {
05753     return kClassNameHidden;
05754   }
05755   if (classNameW == kWClassNameUI) {
05756     return kClassNameUI;
05757   }
05758   if (classNameW == kWClassNameContent) {
05759     return kClassNameContent;
05760   }
05761   if (classNameW == kWClassNameContentFrame) {
05762     return kClassNameContentFrame;
05763   }
05764   return kClassNameGeneral;
05765 }
05766 
05767 LPCSTR nsWindow::WindowPopupClass()
05768 {
05769   // Call into the wide version to make sure things get
05770   // registered properly.
05771   WindowPopupClassW();
05772 
05773   // XXX: The class name used here must be kept in sync with
05774   //      the classname used in WindowPopupClassW();
05775   return "MozillaDropShadowWindowClass";
05776 }
05777 
05778 //-------------------------------------------------------------------------
05779 //
05780 // return nsWindow styles
05781 //
05782 //-------------------------------------------------------------------------
05783 DWORD nsWindow::WindowStyle()
05784 {
05785   DWORD style;
05786 
05787 #ifdef WINCE
05788   switch (mWindowType) {
05789     case eWindowType_child:
05790            style = WS_CHILD;
05791       break;
05792 
05793     case eWindowType_dialog:
05794          case eWindowType_popup:
05795                 style = WS_BORDER | WS_POPUP;
05796                 break;
05797 
05798     default:
05799       NS_ASSERTION(0, "unknown border style");
05800       // fall through
05801 
05802     case eWindowType_toplevel:
05803     case eWindowType_invisible:
05804       style = WS_BORDER;
05805       break;
05806   }
05807 
05808 #else
05809   switch (mWindowType) {
05810     case eWindowType_child:
05811       style = WS_OVERLAPPED;
05812       break;
05813 
05814     case eWindowType_dialog:
05815       if (mBorderStyle == eBorderStyle_default) {
05816         style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU |
05817                 DS_3DLOOK | DS_MODALFRAME;
05818       } else {
05819         style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU |
05820                 DS_3DLOOK | DS_MODALFRAME |
05821                 WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
05822       }
05823       break;
05824 
05825     case eWindowType_popup:
05826       style = WS_OVERLAPPED | WS_POPUP;
05827       break;
05828 
05829     default:
05830       NS_ASSERTION(0, "unknown border style");
05831       // fall through
05832 
05833     case eWindowType_toplevel:
05834     case eWindowType_invisible:
05835       style = WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_SYSMENU |
05836               WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
05837       break;
05838   }
05839 
05840   if (mBorderStyle != eBorderStyle_default && mBorderStyle != eBorderStyle_all) {
05841     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_border))
05842       style &= ~WS_BORDER;
05843 
05844     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_title)) {
05845       style &= ~WS_DLGFRAME;
05846       style |= WS_POPUP;
05847     }
05848 
05849     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_close))
05850       style &= ~0;
05851     // XXX The close box can only be removed by changing the window class,
05852     // as far as I know   --- roc+moz@cs.cmu.edu
05853 
05854     if (mBorderStyle == eBorderStyle_none ||
05855       !(mBorderStyle & (eBorderStyle_menu | eBorderStyle_close)))
05856       style &= ~WS_SYSMENU;
05857     // Looks like getting rid of the system menu also does away with the
05858     // close box. So, we only get rid of the system menu if you want neither it
05859     // nor the close box. How does the Windows "Dialog" window class get just
05860     // closebox and no sysmenu? Who knows.
05861 
05862     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_resizeh))
05863       style &= ~WS_THICKFRAME;
05864 
05865     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_minimize))
05866       style &= ~WS_MINIMIZEBOX;
05867 
05868     if (mBorderStyle == eBorderStyle_none || !(mBorderStyle & eBorderStyle_maximize))
05869       style &= ~WS_MAXIMIZEBOX;
05870   }
05871 #endif // WINCE
05872   return style;
05873 }
05874 
05875 
05876 //-------------------------------------------------------------------------
05877 //
05878 // return nsWindow extended styles
05879 //
05880 //-------------------------------------------------------------------------
05881 DWORD nsWindow::WindowExStyle()
05882 {
05883   switch (mWindowType)
05884   {
05885     case eWindowType_child:
05886       return 0;
05887 
05888     case eWindowType_dialog:
05889       return WS_EX_WINDOWEDGE;
05890 
05891     case eWindowType_popup:
05892       return WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
05893 
05894     default:
05895       NS_ASSERTION(0, "unknown border style");
05896       // fall through
05897 
05898     case eWindowType_toplevel:
05899     case eWindowType_invisible:
05900       return WS_EX_WINDOWEDGE;
05901   }
05902 }
05903 
05904 
05905 // -----------------------------------------------------------------------
05906 //
05907 // Subclass (or remove the subclass from) this component's nsWindow
05908 //
05909 // -----------------------------------------------------------------------
05910 void nsWindow::SubclassWindow(BOOL bState)
05911 {
05912   if (NULL != mWnd) {
05913     NS_PRECONDITION(::IsWindow(mWnd), "Invalid window handle");
05914 
05915     if (bState) {
05916       // change the nsWindow proc
05917       if (mUnicodeWidget)
05918         mPrevWndProc = (WNDPROC)nsToolkit::mSetWindowLong(mWnd, GWL_WNDPROC,
05919                                                 (LONG)nsWindow::WindowProc);
05920       else
05921         mPrevWndProc = (WNDPROC)::SetWindowLong(mWnd, GWL_WNDPROC,
05922                                                 (LONG)nsWindow::WindowProc);
05923       NS_ASSERTION(mPrevWndProc, "Null standard window procedure");
05924       // connect the this pointer to the nsWindow handle
05925       SetNSWindowPtr(mWnd, this);
05926     }
05927     else {
05928       if (mUnicodeWidget)
05929         nsToolkit::mSetWindowLong(mWnd, GWL_WNDPROC, (LONG)mPrevWndProc);
05930       else
05931         ::SetWindowLong(mWnd, GWL_WNDPROC, (LONG)mPrevWndProc);
05932       SetNSWindowPtr(mWnd, NULL);
05933       mPrevWndProc = NULL;
05934     }
05935   }
05936 }
05937 
05938 
05939 //-------------------------------------------------------------------------
05940 //
05941 // WM_DESTROY has been called
05942 //
05943 //-------------------------------------------------------------------------
05944 void nsWindow::OnDestroy()
05945 {
05946   mOnDestroyCalled = PR_TRUE;
05947 
05948   SubclassWindow(FALSE);
05949   mWnd = NULL;
05950 
05951   // free GDI objects
05952   if (mBrush) {
05953     VERIFY(::DeleteObject(mBrush));
05954     mBrush = NULL;
05955   }
05956 
05957 #if 0
05958   if (mPalette) {
05959     VERIFY(::DeleteObject(mPalette));
05960     mPalette = NULL;
05961   }
05962 #endif
05963 
05964   // if we were in the middle of deferred window positioning then
05965   // free the memory for the multiple-window position structure
05966   if (mDeferredPositioner) {
05967     VERIFY(::EndDeferWindowPos(mDeferredPositioner));
05968     mDeferredPositioner = NULL;
05969   }
05970 
05971   // release references to children, device context, toolkit, and app shell
05972   nsBaseWidget::OnDestroy();
05973 
05974   // dispatch the event
05975   if (!mIsDestroying) {
05976     // dispatching of the event may cause the reference count to drop to 0
05977     // and result in this object being destroyed. To avoid that, add a reference
05978     // and then release it after dispatching the event
05979     AddRef();
05980     DispatchStandardEvent(NS_DESTROY);
05981     Release();
05982   }
05983 }
05984 
05985 //-------------------------------------------------------------------------
05986 //
05987 // Move
05988 //
05989 //-------------------------------------------------------------------------
05990 PRBool nsWindow::OnMove(PRInt32 aX, PRInt32 aY)
05991 {
05992   mBounds.x = aX;
05993   mBounds.y = aY;
05994 
05995   nsGUIEvent event(PR_TRUE, NS_MOVE, this);
05996   InitEvent(event);
05997   event.point.x = aX;
05998   event.point.y = aY;
05999 
06000   PRBool result = DispatchWindowEvent(&event);
06001   NS_RELEASE(event.widget);
06002   return result;
06003 }
06004 
06005 //-------------------------------------------------------------------------
06006 //
06007 // Paint
06008 //
06009 //-------------------------------------------------------------------------
06010 PRBool nsWindow::OnPaint(HDC aDC)
06011 {
06012   nsRect bounds;
06013   PRBool result = PR_TRUE;
06014   PAINTSTRUCT ps;
06015   nsEventStatus eventStatus = nsEventStatus_eIgnore;
06016 
06017   mPainting = PR_TRUE;
06018 
06019 #ifdef NS_DEBUG
06020   HRGN debugPaintFlashRegion = NULL;
06021   HDC debugPaintFlashDC = NULL;
06022 
06023   if (debug_WantPaintFlashing())
06024   {
06025     debugPaintFlashRegion = ::CreateRectRgn(0, 0, 0, 0);
06026     ::GetUpdateRgn(mWnd, debugPaintFlashRegion, TRUE);
06027     debugPaintFlashDC = ::GetDC(mWnd);
06028   }
06029 #endif // NS_DEBUG
06030 
06031   HDC hDC = aDC ? aDC : (::BeginPaint(mWnd, &ps));
06032   RECT paintRect;
06033 
06034 #ifdef MOZ_XUL
06035   if (aDC || mIsTranslucent) {
06036 #else
06037   if (aDC) {
06038 #endif
06039     ::GetClientRect(mWnd, &paintRect);
06040   }
06041   else {
06042     paintRect = ps.rcPaint;
06043   }
06044 
06045   if (!IsRectEmpty(&paintRect))
06046   {
06047     // call the event callback
06048     if (mEventCallback)
06049     {
06050       nsPaintEvent event(PR_TRUE, NS_PAINT, this);
06051 
06052       InitEvent(event);
06053 
06054       nsRect rect(paintRect.left,
06055                   paintRect.top,
06056                   paintRect.right - paintRect.left,
06057                   paintRect.bottom - paintRect.top);
06058       event.region = nsnull;
06059       event.rect = &rect;
06060       // Should probably pass in a real region here, using GetRandomRgn
06061       // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/clipping_4q0e.asp
06062 
06063 #ifdef NS_DEBUG
06064       debug_DumpPaintEvent(stdout,
06065                            this,
06066                            &event,
06067                            nsCAutoString("noname"),
06068                            (PRInt32) mWnd);
06069 #endif // NS_DEBUG
06070 
06071       if (NS_SUCCEEDED(CallCreateInstance(kRenderingContextCID, &event.renderingContext)))
06072       {
06073         nsIRenderingContextWin *winrc;
06074 
06075         if (NS_SUCCEEDED(CallQueryInterface(event.renderingContext, &winrc)))
06076         {
06077           nsIDrawingSurface* surf;
06078 
06079           //i know all of this seems a little backwards. i'll fix it, i swear. MMP
06080 
06081           if (NS_OK == winrc->CreateDrawingSurface(hDC, surf))
06082           {
06083             event.renderingContext->Init(mContext, surf);
06084             result = DispatchWindowEvent(&event, eventStatus);
06085             event.renderingContext->DestroyDrawingSurface(surf);
06086 
06087 #ifdef MOZ_XUL
06088             if (mIsTranslucent && IsAlphaTranslucencySupported())
06089             {
06090               // Data from offscreen drawing surface was copied to memory bitmap of transparent
06091               // bitmap. Now it can be read from memory bitmap to apply alpha channel and after
06092               // that displayed on the screen.
06093               UpdateTranslucentWindow();
06094             }
06095 #endif
06096           }
06097 
06098           NS_RELEASE(winrc);
06099         }
06100 
06101         NS_RELEASE(event.renderingContext);
06102       }
06103       else
06104         result = PR_FALSE;
06105 
06106       NS_RELEASE(event.widget);
06107     }
06108   }
06109 
06110   if (!aDC) {
06111     ::EndPaint(mWnd, &ps);
06112   }
06113 
06114 #ifdef NS_DEBUG
06115   if (debug_WantPaintFlashing())
06116   {
06117     // Only flash paint events which have not ignored the paint message.
06118     // Those that ignore the paint message aren't painting anything so there
06119     // is only the overhead of the dispatching the paint event.
06120     if (nsEventStatus_eIgnore != eventStatus) {
06121       ::InvertRgn(debugPaintFlashDC, debugPaintFlashRegion);
06122       PR_Sleep(PR_MillisecondsToInterval(30));
06123       ::InvertRgn(debugPaintFlashDC, debugPaintFlashRegion);
06124       PR_Sleep(PR_MillisecondsToInterval(30));
06125     }
06126     ::ReleaseDC(mWnd, debugPaintFlashDC);
06127     ::DeleteObject(debugPaintFlashRegion);
06128   }
06129 #endif // NS_DEBUG
06130 
06131   mPainting = PR_FALSE;
06132 
06133   return result;
06134 }
06135 
06136 
06137 //-------------------------------------------------------------------------
06138 //
06139 // Send a resize message to the listener
06140 //
06141 //-------------------------------------------------------------------------
06142 PRBool nsWindow::OnResize(nsRect &aWindowRect)
06143 {
06144   // call the event callback
06145   if (mEventCallback) {
06146     nsSizeEvent event(PR_TRUE, NS_SIZE, this);
06147     InitEvent(event);
06148     event.windowSize = &aWindowRect;
06149     RECT r;
06150     if (::GetWindowRect(mWnd, &r)) {
06151       event.mWinWidth  = PRInt32(r.right - r.left);
06152       event.mWinHeight = PRInt32(r.bottom - r.top);
06153     } else {
06154       event.mWinWidth  = 0;
06155       event.mWinHeight = 0;
06156     }
06157     PRBool result = DispatchWindowEvent(&event);
06158     NS_RELEASE(event.widget);
06159     return result;
06160   }
06161 
06162   return PR_FALSE;
06163 }
06164 
06165 //-------------------------------------------------------------------------
06166 //
06167 // Deal with all sort of mouse event
06168 //
06169 //-------------------------------------------------------------------------
06170 PRBool nsWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam, nsPoint* aPoint)
06171 {
06172   PRBool result = PR_FALSE;
06173 
06174   if (nsnull == mEventCallback && nsnull == mMouseListener) {
06175     return result;
06176   }
06177 
06178   nsMouseEvent event(PR_TRUE, aEventType, this, nsMouseEvent::eReal);
06179   if (aEventType == NS_CONTEXTMENU_KEY) {
06180     nsPoint zero(0, 0);
06181     InitEvent(event, &zero);
06182   } else {
06183     InitEvent(event, aPoint);
06184   }
06185 
06186   event.isShift   = IS_VK_DOWN(NS_VK_SHIFT);
06187   event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
06188   event.isMeta    = PR_FALSE;
06189   event.isAlt     = IS_VK_DOWN(NS_VK_ALT);
06190 
06191   //Dblclicks are used to set the click count, then changed to mousedowns
06192   LONG curMsgTime = ::GetMessageTime();
06193   POINT mp;
06194   DWORD pos = ::GetMessagePos();
06195   mp.x      = GET_X_LPARAM(pos);
06196   mp.y      = GET_Y_LPARAM(pos);
06197   PRBool insideMovementThreshold = (abs(gLastMousePoint.x - mp.x) < (short)::GetSystemMetrics(SM_CXDOUBLECLK)) &&
06198                                    (abs(gLastMousePoint.y - mp.y) < (short)::GetSystemMetrics(SM_CYDOUBLECLK));
06199 
06200   // Supress mouse moves caused by widget creation
06201   if ((aEventType == NS_MOUSE_MOVE) &&
06202       (gLastMouseMovePoint.x == mp.x) &&
06203       (gLastMouseMovePoint.y == mp.y))
06204   {
06205     NS_RELEASE(event.widget);
06206     return result;
06207   } else {
06208     gLastMouseMovePoint.x = mp.x;
06209     gLastMouseMovePoint.y = mp.y;
06210   }
06211 
06212   BYTE eventButton;
06213   switch (aEventType) {
06214     case NS_MOUSE_LEFT_BUTTON_DOWN:
06215     case NS_MOUSE_LEFT_BUTTON_UP:
06216     case NS_MOUSE_LEFT_DOUBLECLICK:
06217       eventButton = VK_LBUTTON;
06218       break;
06219     case NS_MOUSE_MIDDLE_BUTTON_DOWN:
06220     case NS_MOUSE_MIDDLE_BUTTON_UP:
06221     case NS_MOUSE_MIDDLE_DOUBLECLICK:
06222       eventButton = VK_MBUTTON;
06223       break;
06224     case NS_MOUSE_RIGHT_BUTTON_DOWN:
06225     case NS_MOUSE_RIGHT_BUTTON_UP:
06226     case NS_MOUSE_RIGHT_DOUBLECLICK:
06227       eventButton = VK_RBUTTON;
06228       break;
06229     default:
06230       eventButton = 0;
06231       break;
06232   }
06233 
06234   // we're going to time double-clicks from mouse *up* to next mouse *down*
06235   if (aEventType == NS_MOUSE_LEFT_DOUBLECLICK) {
06236     event.message = NS_MOUSE_LEFT_BUTTON_DOWN;
06237     gLastClickCount = 2;
06238   }
06239   else if (aEventType == NS_MOUSE_MIDDLE_DOUBLECLICK) {
06240     event.message = NS_MOUSE_MIDDLE_BUTTON_DOWN;
06241     gLastClickCount = 2;
06242   }
06243   else if (aEventType == NS_MOUSE_RIGHT_DOUBLECLICK) {
06244     event.message = NS_MOUSE_RIGHT_BUTTON_DOWN;
06245     gLastClickCount = 2;
06246   }
06247   else if (aEventType == NS_MOUSE_LEFT_BUTTON_UP || aEventType == NS_MOUSE_MIDDLE_BUTTON_UP ||
06248            aEventType == NS_MOUSE_RIGHT_BUTTON_UP) {
06249     // remember when this happened for the next mouse down
06250     DWORD pos = ::GetMessagePos();
06251     gLastMousePoint.x = GET_X_LPARAM(pos);
06252     gLastMousePoint.y = GET_Y_LPARAM(pos);
06253     gLastMouseButton = eventButton;
06254   }
06255   else if (aEventType == NS_MOUSE_LEFT_BUTTON_DOWN || aEventType == NS_MOUSE_MIDDLE_BUTTON_DOWN ||
06256            aEventType == NS_MOUSE_RIGHT_BUTTON_DOWN) {
06257     // now look to see if we want to convert this to a double- or triple-click
06258 
06259 #ifdef NS_DEBUG_XX
06260     printf("Msg: %d Last: %d Dif: %d Max %d\n", curMsgTime, gLastMouseDownTime, curMsgTime-gLastMouseDownTime, ::GetDoubleClickTime());
06261     printf("Mouse %d %d\n", abs(gLastMousePoint.x - mp.x), abs(gLastMousePoint.y - mp.y));
06262 #endif
06263     if (((curMsgTime - gLastMouseDownTime) < (LONG)::GetDoubleClickTime()) && insideMovementThreshold &&
06264         eventButton == gLastMouseButton) {
06265       gLastClickCount ++;
06266     } else {
06267       // reset the click count, to count *this* click
06268       gLastClickCount = 1;
06269     }
06270     // Set last Click time on MouseDown only
06271     gLastMouseDownTime = curMsgTime;
06272   }
06273   else if (aEventType == NS_MOUSE_MOVE && !insideMovementThreshold) {
06274     gLastClickCount = 0;
06275   }
06276   event.clickCount = gLastClickCount;
06277 
06278 #ifdef NS_DEBUG_XX
06279   printf("Msg Time: %d Click Count: %d\n", curMsgTime, event.clickCount);
06280 #endif
06281 
06282   nsPluginEvent pluginEvent;
06283 
06284   switch (aEventType)//~~~
06285   {
06286     case NS_MOUSE_LEFT_BUTTON_DOWN:
06287       pluginEvent.event = WM_LBUTTONDOWN;
06288       break;
06289     case NS_MOUSE_LEFT_BUTTON_UP:
06290       pluginEvent.event = WM_LBUTTONUP;
06291       break;
06292     case NS_MOUSE_LEFT_DOUBLECLICK:
06293       pluginEvent.event = WM_LBUTTONDBLCLK;
06294       break;
06295     case NS_MOUSE_RIGHT_BUTTON_DOWN:
06296       pluginEvent.event = WM_RBUTTONDOWN;
06297       break;
06298     case NS_MOUSE_RIGHT_BUTTON_UP:
06299       pluginEvent.event = WM_RBUTTONUP;
06300       break;
06301     case NS_MOUSE_RIGHT_DOUBLECLICK:
06302       pluginEvent.event = WM_RBUTTONDBLCLK;
06303       break;
06304     case NS_MOUSE_MIDDLE_BUTTON_DOWN:
06305       pluginEvent.event = WM_MBUTTONDOWN;
06306       break;
06307     case NS_MOUSE_MIDDLE_BUTTON_UP:
06308       pluginEvent.event = WM_MBUTTONUP;
06309       break;
06310     case NS_MOUSE_MIDDLE_DOUBLECLICK:
06311       pluginEvent.event = WM_MBUTTONDBLCLK;
06312       break;
06313     case NS_MOUSE_MOVE:
06314       pluginEvent.event = WM_MOUSEMOVE;
06315       break;
06316     default:
06317       break;
06318   }
06319 
06320   pluginEvent.wParam = wParam;     // plugins NEED raw OS event flags!
06321   pluginEvent.lParam = MAKELONG(event.point.x, event.point.y);
06322 
06323   event.nativeMsg = (void *)&pluginEvent;
06324 
06325   // call the event callback
06326   if (nsnull != mEventCallback) {
06327     result = DispatchWindowEvent(&event);
06328 
06329     if (aEventType == NS_MOUSE_MOVE) {
06330       // if we are not in mouse capture mode (mouse down and hold)
06331       // then use "this" window
06332       // if we are in mouse capture, then all events are being directed
06333       // back to the nsWindow doing the capture. So therefore, the detection
06334       // of whether we are in a new nsWindow is wrong. Meaning this MOUSE_MOVE
06335       // event hold the captured windows pointer not the one the mouse is over.
06336       //
06337       // So we use "WindowFromPoint" to find what window we are over and
06338       // set that window into the mouse trailer timer.
06339       if (!mIsInMouseCapture) {
06340         MouseTrailer::GetSingleton().SetMouseTrailerWindow(this);
06341       } else {
06342         POINT mp;
06343         DWORD pos = ::GetMessagePos();
06344         mp.x      = GET_X_LPARAM(pos);
06345         mp.y      = GET_Y_LPARAM(pos);
06346 
06347         // OK, now find out if we are still inside
06348         // the captured native window
06349 
06350         nsWindow * someWindow = nsnull;
06351         HWND hWnd = ::WindowFromPoint(mp);
06352         if (hWnd != NULL) {
06353           POINT cpos = mp;
06354           ::ScreenToClient(hWnd, &cpos);
06355           RECT r;
06356           VERIFY(::GetClientRect(hWnd, &r));
06357           if (cpos.x >= r.left && cpos.x <= r.right &&
06358               cpos.y >= r.top && cpos.y <= r.bottom) {
06359             // yes we are so we should be able to get a valid window
06360             // although, strangley enough when we are on the frame part of the
06361             // window we get right here when in capture mode
06362             // but this window won't match the capture mode window so
06363             // we are ok
06364             someWindow = GetNSWindowPtr(hWnd);
06365           }
06366         }
06367         // only set the window into the mouse trailer if we have a good window
06368         if (nsnull != someWindow) {
06369           MouseTrailer::GetSingleton().SetMouseTrailerWindow(someWindow);
06370         }
06371       }
06372 
06373       nsRect rect;
06374       GetBounds(rect);
06375       rect.x = 0;
06376       rect.y = 0;
06377 
06378       if (rect.Contains(event.point.x, event.point.y)) {
06379         if (gCurrentWindow == NULL || gCurrentWindow != this) {
06380           if ((nsnull != gCurrentWindow) && (!gCurrentWindow->mIsDestroying)) {
06381             MouseTrailer::GetSingleton().IgnoreNextCycle();
06382             gCurrentWindow->DispatchMouseEvent(NS_MOUSE_EXIT, wParam);
06383           }
06384           gCurrentWindow = this;
06385           if (!mIsDestroying) {
06386             gCurrentWindow->DispatchMouseEvent(NS_MOUSE_ENTER, wParam);
06387           }
06388         }
06389       }
06390     } else if (aEventType == NS_MOUSE_EXIT) {
06391       if (gCurrentWindow == this) {
06392         gCurrentWindow = nsnull;
06393       }
06394     }
06395 
06396     // Release the widget with NS_IF_RELEASE() just in case
06397     // the context menu key code in nsEventListenerManager::HandleEvent()
06398     // released it already.
06399     NS_IF_RELEASE(event.widget);
06400     return result;
06401   }
06402 
06403   if (nsnull != mMouseListener) {
06404     switch (aEventType) {
06405       case NS_MOUSE_MOVE:
06406       {
06407         result = ConvertStatus(mMouseListener->MouseMoved(event));
06408         nsRect rect;
06409         GetBounds(rect);
06410         if (rect.Contains(event.point.x, event.point.y)) {
06411           if (gCurrentWindow == NULL || gCurrentWindow != this) {
06412             gCurrentWindow = this;
06413           }
06414         } else {
06415 #ifdef DEBUG
06416           //printf("Mouse exit");
06417 #endif
06418         }
06419       }
06420       break;
06421 
06422       case NS_MOUSE_LEFT_BUTTON_DOWN:
06423       case NS_MOUSE_MIDDLE_BUTTON_DOWN:
06424       case NS_MOUSE_RIGHT_BUTTON_DOWN:
06425         result = ConvertStatus(mMouseListener->MousePressed(event));
06426         break;
06427 
06428       case NS_MOUSE_LEFT_BUTTON_UP:
06429       case NS_MOUSE_MIDDLE_BUTTON_UP:
06430       case NS_MOUSE_RIGHT_BUTTON_UP:
06431         result = ConvertStatus(mMouseListener->MouseReleased(event));
06432         result = ConvertStatus(mMouseListener->MouseClicked(event));
06433         break;
06434     } // switch
06435   }
06436 
06437   NS_RELEASE(event.widget);
06438   return result;
06439 }
06440 
06441 //-------------------------------------------------------------------------
06442 //
06443 // Deal with accessibile event
06444 //
06445 //-------------------------------------------------------------------------
06446 #ifdef ACCESSIBILITY
06447 PRBool nsWindow::DispatchAccessibleEvent(PRUint32 aEventType, nsIAccessible** aAcc, nsPoint* aPoint)
06448 {
06449   PRBool result = PR_FALSE;
06450 
06451   if (nsnull == mEventCallback) {
06452     return result;
06453   }
06454 
06455   *aAcc = nsnull;
06456 
06457   nsAccessibleEvent event(PR_TRUE, aEventType, this);
06458   InitEvent(event, aPoint);
06459 
06460   event.isShift   = IS_VK_DOWN(NS_VK_SHIFT);
06461   event.isControl = IS_VK_DOWN(NS_VK_CONTROL);
06462   event.isMeta    = PR_FALSE;
06463   event.isAlt     = IS_VK_DOWN(NS_VK_ALT);
06464   event.accessible = nsnull;
06465 
06466   result = DispatchWindowEvent(&event);
06467 
06468   // if the event returned an accesssible get it.
06469   if (event.accessible)
06470     *aAcc = event.accessible;
06471 
06472   NS_RELEASE(event.widget);
06473 
06474   return result;
06475 }
06476 #endif
06477 
06478 //-------------------------------------------------------------------------
06479 //
06480 // Deal with focus messages
06481 //
06482 //-------------------------------------------------------------------------
06483 PRBool nsWindow::DispatchFocus(PRUint32 aEventType, PRBool isMozWindowTakingFocus)
06484 {
06485   // call the event callback
06486   if (mEventCallback) {
06487     nsFocusEvent event(PR_TRUE, aEventType, this);
06488     InitEvent(event);
06489 
06490     //focus and blur event should go to their base widget loc, not current mouse pos
06491     event.point.x = 0;
06492     event.point.y = 0;
06493 
06494     event.isMozWindowTakingFocus = isMozWindowTakingFocus;
06495 
06496     nsPluginEvent pluginEvent;
06497 
06498     switch (aEventType)//~~~
06499     {
06500       case NS_GOTFOCUS:
06501         pluginEvent.event = WM_SETFOCUS;
06502         break;
06503       case NS_LOSTFOCUS:
06504         pluginEvent.event = WM_KILLFOCUS;
06505         break;
06506       case NS_PLUGIN_ACTIVATE:
06507         pluginEvent.event = WM_KILLFOCUS;
06508         break;
06509       default:
06510         break;
06511     }
06512 
06513     event.nativeMsg = (void *)&pluginEvent;
06514 
06515     PRBool result = DispatchWindowEvent(&event);
06516     NS_RELEASE(event.widget);
06517 
06518     return result;
06519   }
06520   return PR_FALSE;
06521 }
06522 
06523 
06524 //-------------------------------------------------------------------------
06525 //
06526 // Deal with scrollbar messages (actually implemented only in nsScrollbar)
06527 //
06528 //-------------------------------------------------------------------------
06529 PRBool nsWindow::OnScroll(UINT scrollCode, int cPos)
06530 {
06531   return PR_FALSE;
06532 }
06533 
06534 
06535 //-------------------------------------------------------------------------
06536 //
06537 // Return the brush used to paint the background of this control
06538 //
06539 //-------------------------------------------------------------------------
06540 HBRUSH nsWindow::OnControlColor()
06541 {
06542   return mBrush;
06543 }
06544 
06545 //-------------------------------------------------------------------------
06546 //
06547 // Deal with all sort of mouse event
06548 //
06549 //-------------------------------------------------------------------------
06550 PRBool ChildWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam, nsPoint* aPoint)
06551 {
06552   PRBool result = PR_FALSE;
06553 
06554   if (nsnull == mEventCallback && nsnull == mMouseListener) {
06555     return result;
06556   }
06557 
06558   switch (aEventType) {
06559     case NS_MOUSE_LEFT_BUTTON_DOWN:
06560     case NS_MOUSE_MIDDLE_BUTTON_DOWN:
06561     case NS_MOUSE_RIGHT_BUTTON_DOWN:
06562       CaptureMouse(PR_TRUE);
06563       break;
06564 
06565     case NS_MOUSE_LEFT_BUTTON_UP:
06566     case NS_MOUSE_MIDDLE_BUTTON_UP:
06567     case NS_MOUSE_RIGHT_BUTTON_UP:
06568       CaptureMouse(PR_FALSE);
06569       break;
06570 
06571     default:
06572       break;
06573 
06574   } // switch
06575 
06576   return nsWindow::DispatchMouseEvent(aEventType, wParam, aPoint);
06577 }
06578 
06579 //-------------------------------------------------------------------------
06580 //
06581 // return the style for a child nsWindow
06582 //
06583 //-------------------------------------------------------------------------
06584 DWORD ChildWindow::WindowStyle()
06585 {
06586   return WS_CHILD | WS_CLIPCHILDREN | nsWindow::WindowStyle();
06587 }
06588 
06589 NS_METHOD nsWindow::SetTitle(const nsAString& aTitle)
06590 {
06591   const nsString& strTitle = PromiseFlatString(aTitle);
06592   nsToolkit::mSendMessage(mWnd, WM_SETTEXT, (WPARAM)0, (LPARAM)(LPCWSTR)strTitle.get());
06593   return NS_OK;
06594 }
06595 
06596 NS_METHOD nsWindow::SetIcon(const nsAString& aIconSpec) 
06597 {
06598   // Assume the given string is a local identifier for an icon file.
06599 
06600   nsCOMPtr<nsILocalFile> iconFile;
06601   ResolveIconName(aIconSpec, NS_LITERAL_STRING(".ico"),
06602                   getter_AddRefs(iconFile));
06603   if (!iconFile)
06604     return NS_OK; // not an error if icon is not found
06605 
06606   nsAutoString iconPath;
06607   iconFile->GetPath(iconPath);
06608 
06609   // XXX this should use MZLU (see bug 239279)
06610 
06611   ::SetLastError(0);
06612 
06613   HICON bigIcon = (HICON)::LoadImageW(NULL,
06614                                       (LPCWSTR)iconPath.get(),
06615                                       IMAGE_ICON,
06616                                       ::GetSystemMetrics(SM_CXICON),
06617                                       ::GetSystemMetrics(SM_CYICON),
06618                                       LR_LOADFROMFILE );
06619   HICON smallIcon = (HICON)::LoadImageW(NULL,
06620                                         (LPCWSTR)iconPath.get(),
06621                                         IMAGE_ICON,
06622                                         ::GetSystemMetrics(SM_CXSMICON),
06623                                         ::GetSystemMetrics(SM_CYSMICON),
06624                                         LR_LOADFROMFILE );
06625 
06626   // See if unicode API not implemented and if not, try ascii version
06627   if (::GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
06628     nsCOMPtr<nsILocalFile> pathConverter;
06629     if (NS_SUCCEEDED(NS_NewLocalFile(iconPath, PR_FALSE,
06630                                      getter_AddRefs(pathConverter)))) {
06631       // Now try the char* path.
06632       nsCAutoString aPath;
06633       pathConverter->GetNativePath(aPath);
06634       bigIcon = (HICON)::LoadImage(NULL,
06635                                    aPath.get(),
06636                                    IMAGE_ICON,
06637                                    ::GetSystemMetrics(SM_CXICON),
06638                                    ::GetSystemMetrics(SM_CYICON),
06639                                    LR_LOADFROMFILE );
06640       smallIcon = (HICON)::LoadImage(NULL,
06641                                      aPath.get(),
06642                                      IMAGE_ICON,
06643                                      ::GetSystemMetrics(SM_CXSMICON),
06644                                      ::GetSystemMetrics(SM_CYSMICON),
06645                                      LR_LOADFROMFILE );
06646     }
06647   }
06648 
06649   if (bigIcon) {
06650     HICON icon = (HICON) nsToolkit::mSendMessage(mWnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)bigIcon);
06651     if (icon)
06652       ::DestroyIcon(icon);
06653   }
06654 #ifdef DEBUG_SetIcon
06655   else {
06656     NS_LossyConvertUTF16toASCII cPath(iconPath);
06657     printf( "\nIcon load error; icon=%s, rc=0x%08X\n\n", cPath.get(), ::GetLastError() );
06658   }
06659 #endif
06660   if (smallIcon) {
06661     HICON icon = (HICON) nsToolkit::mSendMessage(mWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)smallIcon);
06662     if (icon)
06663       ::DestroyIcon(icon);
06664   }
06665 #ifdef DEBUG_SetIcon
06666   else {
06667     NS_LossyConvertUTF16toASCII cPath(iconPath);
06668     printf( "\nSmall icon load error; icon=%s, rc=0x%08X\n\n", cPath.get(), ::GetLastError() );
06669   }
06670 #endif
06671 
06672   return NS_OK;
06673 }
06674 
06675 
06676 PRBool nsWindow::AutoErase()
06677 {
06678   return PR_FALSE;
06679 }
06680 
06681 NS_METHOD nsWindow::GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight)
06682 {
06683   aWidth  = mPreferredWidth;
06684   aHeight = mPreferredHeight;
06685   return NS_ERROR_FAILURE;
06686 }
06687 
06688 NS_METHOD nsWindow::SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight)
06689 {
06690   mPreferredWidth  = aWidth;
06691   mPreferredHeight = aHeight;
06692   return NS_OK;
06693 }
06694 
06695 #define ZH_CN_INTELLEGENT_ABC_IME ((HKL)0xe0040804L)
06696 #define ZH_CN_MS_PINYIN_IME_3_0 ((HKL)0xe00e0804L)
06697 #define ZH_CN_NEIMA_IME ((HKL)0xe0050804L)
06698 #define PINYIN_IME_ON_XP(kl) ((nsToolkit::mIsWinXP) && \
06699                               (ZH_CN_MS_PINYIN_IME_3_0 == (kl)))
06700 PRBool gPinYinIMECaretCreated = PR_FALSE;
06701 
06702 void
06703 nsWindow::HandleTextEvent(HIMC hIMEContext,PRBool aCheckAttr)
06704 {
06705   NS_ASSERTION(sIMECompUnicode, "sIMECompUnicode is null");
06706   NS_ASSERTION(sIMEIsComposing, "conflict state");
06707 
06708   if (!sIMECompUnicode)
06709     return;
06710 
06711   nsTextEvent event(PR_TRUE, NS_TEXT_TEXT, this);
06712   nsPoint point(0, 0);
06713 
06714   InitEvent(event, &point);
06715 
06716   if (aCheckAttr) {
06717     GetTextRangeList(&(event.rangeCount),&(event.rangeArray));
06718   } else {
06719     event.rangeCount = 0;
06720     event.rangeArray = nsnull;
06721   }
06722 
06723   event.theText = sIMECompUnicode->get();
06724   event.isShift = mIsShiftDown;
06725   event.isControl = mIsControlDown;
06726   event.isMeta = PR_FALSE;
06727   event.isAlt = mIsAltDown;
06728 
06729   DispatchWindowEvent(&event);
06730   NS_RELEASE(event.widget);
06731 
06732   if (event.rangeArray)
06733     delete [] event.rangeArray;
06734 
06735   //
06736   // Post process event
06737   //
06738   if (event.theReply.mCursorPosition.width || event.theReply.mCursorPosition.height)
06739   {
06740     nsRect cursorPosition;
06741     ResolveIMECaretPos(this, event.theReply.mCursorPosition, cursorPosition);
06742     CANDIDATEFORM candForm;
06743     candForm.dwIndex = 0;
06744     candForm.dwStyle = CFS_EXCLUDE;
06745     candForm.ptCurrentPos.x = cursorPosition.x;
06746     candForm.ptCurrentPos.y = cursorPosition.y;
06747     candForm.rcArea.right = candForm.rcArea.left = candForm.ptCurrentPos.x;
06748     candForm.rcArea.top = candForm.ptCurrentPos.y;
06749     candForm.rcArea.bottom = candForm.ptCurrentPos.y +
06750                              cursorPosition.height;
06751 
06752     if (gPinYinIMECaretCreated)
06753     {
06754       SetCaretPos(candForm.ptCurrentPos.x, candForm.ptCurrentPos.y);
06755     }
06756 
06757     NS_IMM_SETCANDIDATEWINDOW(hIMEContext, &candForm);
06758 
06759     // somehow the "Intellegent ABC IME" in Simplified Chinese
06760     // window listen to the caret position to decide where to put the
06761     // candidate window
06762     if (gKeyboardLayout == ZH_CN_INTELLEGENT_ABC_IME)
06763     {
06764       CreateCaret(mWnd, nsnull, 1, 1);
06765       SetCaretPos(candForm.ptCurrentPos.x, candForm.ptCurrentPos.y);
06766       DestroyCaret();
06767     }
06768 
06769     // Record previous composing char position
06770     // The cursor is always on the right char before it, but not necessarily on the
06771     // left of next char, as what happens in wrapping.
06772     if (sIMECursorPosition && sIMECompCharPos &&
06773         sIMECursorPosition < IME_MAX_CHAR_POS) {
06774       sIMECompCharPos[sIMECursorPosition-1].right = cursorPosition.x;
06775       sIMECompCharPos[sIMECursorPosition-1].top = cursorPosition.y;
06776       sIMECompCharPos[sIMECursorPosition-1].bottom = cursorPosition.YMost();
06777       if (sIMECompCharPos[sIMECursorPosition-1].top != cursorPosition.y) {
06778         // wrapping, invalidate left position
06779         sIMECompCharPos[sIMECursorPosition-1].left = -1;
06780       }
06781       sIMECompCharPos[sIMECursorPosition].left = cursorPosition.x;
06782       sIMECompCharPos[sIMECursorPosition].top = cursorPosition.y;
06783       sIMECompCharPos[sIMECursorPosition].bottom = cursorPosition.YMost();
06784     }
06785     sIMECaretHeight = cursorPosition.height;
06786   } else {
06787     // for some reason we don't know yet, theReply may contain invalid result
06788     // need more debugging in nsCaret to find out the reason
06789     // the best we can do now is to ignore the invalid result
06790   }
06791 }
06792 
06793 BOOL
06794 nsWindow::HandleStartComposition(HIMC hIMEContext)
06795 {
06796   // ATOK send the messages following order at starting composition.
06797   // 1. WM_IME_COMPOSITION
06798   // 2. WM_IME_STARTCOMPOSITION
06799   // We call this function at both step #1 and #2.
06800   // However, the composition start event should occur only once.
06801   if (sIMEIsComposing)
06802     return PR_TRUE;
06803 
06804   if (sIMEReconvertUnicode) {
06805     nsMemory::Free(sIMEReconvertUnicode);
06806     sIMEReconvertUnicode = NULL;
06807   }
06808 
06809   nsCompositionEvent event(PR_TRUE, NS_COMPOSITION_START, this);
06810   nsPoint point(0, 0);
06811   CANDIDATEFORM candForm;
06812 
06813   InitEvent(event, &point);
06814   DispatchWindowEvent(&event);
06815 
06816   //
06817   // Post process event
06818   //
06819   if (event.theReply.mCursorPosition.width || event.theReply.mCursorPosition.height)
06820   {
06821     nsRect cursorPosition;
06822     ResolveIMECaretPos(this, event.theReply.mCursorPosition, cursorPosition);
06823     candForm.dwIndex = 0;
06824     candForm.dwStyle = CFS_CANDIDATEPOS;
06825     candForm.ptCurrentPos.x = cursorPosition.x + IME_X_OFFSET;
06826     candForm.ptCurrentPos.y = cursorPosition.y + IME_Y_OFFSET +
06827                               cursorPosition.height;
06828     candForm.rcArea.right = 0;
06829     candForm.rcArea.left = 0;
06830     candForm.rcArea.top = 0;
06831     candForm.rcArea.bottom = 0;
06832 #ifdef DEBUG_IME2
06833     printf("Candidate window position: x=%d, y=%d\n", candForm.ptCurrentPos.x, candForm.ptCurrentPos.y);
06834 #endif
06835 
06836     if (!gPinYinIMECaretCreated && PINYIN_IME_ON_XP(gKeyboardLayout))
06837     {
06838       gPinYinIMECaretCreated = CreateCaret(mWnd, nsnull, 1, 1);
06839       SetCaretPos(candForm.ptCurrentPos.x, candForm.ptCurrentPos.y);
06840     }
06841 
06842     NS_IMM_SETCANDIDATEWINDOW(hIMEContext, &candForm);
06843 
06844     sIMECompCharPos = (RECT*)PR_MALLOC(IME_MAX_CHAR_POS*sizeof(RECT));
06845     if (sIMECompCharPos) {
06846       memset(sIMECompCharPos, -1, sizeof(RECT)*IME_MAX_CHAR_POS);
06847       sIMECompCharPos[0].left = cursorPosition.x;
06848       sIMECompCharPos[0].top = cursorPosition.y;
06849       sIMECompCharPos[0].bottom = cursorPosition.YMost();
06850     }
06851     sIMECaretHeight = cursorPosition.height;
06852   } else {
06853     // for some reason we don't know yet, theReply may contain invalid result
06854     // need more debugging in nsCaret to find out the reason
06855     // the best we can do now is to ignore the invalid result
06856   }
06857 
06858   NS_RELEASE(event.widget);
06859 
06860   if (!sIMECompUnicode)
06861     sIMECompUnicode = new nsAutoString();
06862   sIMEIsComposing = PR_TRUE;
06863 
06864   return PR_TRUE;
06865 }
06866 
06867 void
06868 nsWindow::HandleEndComposition(void)
06869 {
06870   if (!sIMEIsComposing)
06871     return;
06872 
06873   nsCompositionEvent event(PR_TRUE, NS_COMPOSITION_END, this);
06874   nsPoint point(0, 0);
06875 
06876   if (gPinYinIMECaretCreated)
06877   {
06878     DestroyCaret();
06879     gPinYinIMECaretCreated = PR_FALSE;
06880   }
06881 
06882   InitEvent(event,&point);
06883   DispatchWindowEvent(&event);
06884   NS_RELEASE(event.widget);
06885   PR_FREEIF(sIMECompCharPos);
06886   sIMECompCharPos = nsnull;
06887   sIMECaretHeight = 0;
06888   sIMEIsComposing = PR_FALSE;
06889 }
06890 
06891 static PRUint32 PlatformToNSAttr(PRUint8 aAttr)
06892 {
06893   switch (aAttr)
06894   {
06895     case ATTR_INPUT_ERROR:
06896     // case ATTR_FIXEDCONVERTED:
06897     case ATTR_INPUT:
06898       return NS_TEXTRANGE_RAWINPUT;
06899     case ATTR_CONVERTED:
06900       return NS_TEXTRANGE_CONVERTEDTEXT;
06901     case ATTR_TARGET_NOTCONVERTED:
06902       return NS_TEXTRANGE_SELECTEDRAWTEXT;
06903     case ATTR_TARGET_CONVERTED:
06904       return NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
06905     default:
06906       NS_ASSERTION(PR_FALSE, "unknown attribute");
06907       return NS_TEXTRANGE_CARETPOSITION;
06908   }
06909 }
06910 //
06911 // This function converts the composition string (CGS_COMPSTR) into Unicode while mapping the
06912 //  attribute (GCS_ATTR) string t
06913 void
06914 nsWindow::GetTextRangeList(PRUint32* textRangeListLengthResult,nsTextRangeArray* textRangeListResult)
06915 {
06916   NS_ASSERTION(sIMECompUnicode, "sIMECompUnicode is null");
06917 
06918   if (!sIMECompUnicode)
06919     return;
06920 
06921   long maxlen = sIMECompUnicode->Length();
06922   long cursor = sIMECursorPosition;
06923   NS_ASSERTION(cursor <= maxlen, "wrong cursor positoin");
06924   if (cursor > maxlen)
06925     cursor = maxlen;
06926 
06927   //
06928   // figure out the ranges from the compclause string
06929   //
06930   if (sIMECompClauseArrayLength == 0) {
06931     *textRangeListLengthResult = 2;
06932     *textRangeListResult = new nsTextRange[2];
06933     (*textRangeListResult)[0].mStartOffset = 0;
06934     (*textRangeListResult)[0].mEndOffset = sIMECompUnicode->Length();
06935     (*textRangeListResult)[0].mRangeType = NS_TEXTRANGE_RAWINPUT;
06936     (*textRangeListResult)[1].mStartOffset = cursor;
06937     (*textRangeListResult)[1].mEndOffset = cursor;
06938     (*textRangeListResult)[1].mRangeType = NS_TEXTRANGE_CARETPOSITION;
06939   } else {
06940     *textRangeListLengthResult = sIMECompClauseArrayLength;
06941 
06942     //
06943     //  allocate the offset array
06944     //
06945     *textRangeListResult = new nsTextRange[*textRangeListLengthResult];
06946 
06947     //
06948     // figure out the cursor position
06949     //
06950     (*textRangeListResult)[0].mStartOffset = cursor;
06951     (*textRangeListResult)[0].mEndOffset = cursor;
06952     (*textRangeListResult)[0].mRangeType = NS_TEXTRANGE_CARETPOSITION;
06953 
06954     //
06955     // iterate over the attributes and convert them into unicode 
06956     //
06957     int lastOffset = 0;
06958     for(int i = 1; i < sIMECompClauseArrayLength; i++) {
06959       long current = sIMECompClauseArray[i];
06960       NS_ASSERTION(current <= maxlen, "wrong offset");
06961       if(current > maxlen)
06962         current = maxlen;
06963 
06964       (*textRangeListResult)[i].mRangeType = 
06965         PlatformToNSAttr(sIMEAttributeArray[lastOffset]);
06966       (*textRangeListResult)[i].mStartOffset = lastOffset;
06967       (*textRangeListResult)[i].mEndOffset = current;
06968 
06969       lastOffset = current;
06970     } // for
06971   } // if else
06972 }
06973 
06974 
06975 //==========================================================================
06976 BOOL nsWindow::OnInputLangChange(HKL aHKL, LRESULT *oRetValue)
06977 {
06978 #ifdef KE_DEBUG
06979   printf("OnInputLanguageChange\n");
06980 #endif
06981 
06982   if (gKeyboardLayout != aHKL)
06983   {
06984     gKeyboardLayout = aHKL;
06985     *oRetValue = LangIDToCP((WORD)((DWORD)gKeyboardLayout & 0x0FFFF), gCurrentKeyboardCP);
06986     if (nsToolkit::mW2KXP_CP936) {
06987       DWORD imeProp = 0;
06988       NS_IMM_GETPROPERTY(gKeyboardLayout, IGP_PROPERTY, imeProp);
06989       nsToolkit::mUseImeApiW = (imeProp & IME_PROP_UNICODE) ? PR_TRUE : PR_FALSE;
06990     }
06991   }
06992 
06993   ResetInputState();
06994 
06995   if (sIMEIsComposing) {
06996     HandleEndComposition();
06997   }
06998 
06999   return PR_FALSE;   // always pass to child window
07000 }
07001 //==========================================================================
07002 BOOL nsWindow::OnIMEChar(BYTE aByte1, BYTE aByte2, LPARAM aKeyState)
07003 {
07004 #ifdef DEBUG_IME
07005   printf("OnIMEChar\n");
07006 #endif
07007   wchar_t uniChar;
07008   char    charToConvert[3];
07009   size_t  length;
07010   int err = 0;
07011 
07012   if (nsToolkit::mIsNT) {
07013     uniChar = MAKEWORD(aByte2, aByte1);
07014   }
07015   else {
07016     if (aByte1) {
07017       charToConvert[0] = aByte1;
07018       charToConvert[1] = aByte2;
07019       length=2;
07020     }
07021     else {
07022       charToConvert[0] = aByte2;
07023       length=1;
07024     }
07025     err = ::MultiByteToWideChar(gCurrentKeyboardCP, MB_PRECOMPOSED, charToConvert,
07026                                 length, &uniChar, 1);
07027   }
07028 
07029 #ifdef DEBUG_IME
07030   if (!err) {
07031     DWORD lastError = ::GetLastError();
07032     switch (lastError)
07033     {
07034       case ERROR_INSUFFICIENT_BUFFER:
07035         printf("ERROR_INSUFFICIENT_BUFFER\n");
07036         break;
07037 
07038       case ERROR_INVALID_FLAGS:
07039         printf("ERROR_INVALID_FLAGS\n");
07040         break;
07041 
07042       case ERROR_INVALID_PARAMETER:
07043         printf("ERROR_INVALID_PARAMETER\n");
07044         break;
07045 
07046       case ERROR_NO_UNICODE_TRANSLATION:
07047         printf("ERROR_NO_UNICODE_TRANSLATION\n");
07048         break;
07049     }
07050   }
07051 #endif
07052 
07053   // We need to return TRUE here so that Windows doesn't
07054   // send two WM_CHAR msgs
07055   DispatchKeyEvent(NS_KEY_PRESS, uniChar, 0, 0);
07056   return PR_TRUE;
07057 }
07058 
07059 //==========================================================================
07060 // This function is used when aIndex is GCS_COMPSTR, GCS_COMPREADSTR,
07061 // GCS_RESULTSTR, and GCS_RESULTREADSTR.
07062 // Otherwise use NS_IMM_GETCOMPOSITIONSTRING.
07063 // If on NT, we only need aStrUnicode. aStrAnsi is not used.
07064 void nsWindow::GetCompositionString(HIMC aHIMC, DWORD aIndex, nsString* aStrUnicode, nsCString* aStrAnsi)
07065 {
07066   long lRtn;
07067   if (nsToolkit::mUseImeApiW) {
07068     NS_IMM_GETCOMPOSITIONSTRINGW(aHIMC, aIndex, NULL, 0, lRtn);
07069     if (!EnsureStringLength(*aStrUnicode, (lRtn / sizeof(WCHAR)) + 1))
07070       return; // out of memory
07071 
07072     long buflen = lRtn + sizeof(WCHAR);
07073     NS_IMM_GETCOMPOSITIONSTRINGW(aHIMC, aIndex, (LPVOID)aStrUnicode->BeginWriting(), buflen, lRtn);
07074     lRtn = lRtn / sizeof(WCHAR);
07075     aStrUnicode->SetLength(lRtn);
07076   } else {
07077     NS_IMM_GETCOMPOSITIONSTRINGA(aHIMC, aIndex, NULL, 0, lRtn);
07078     if (!EnsureStringLength(*aStrAnsi, lRtn + 1))
07079       return; // out of memory
07080 
07081     long buflen = lRtn + 1;
07082     NS_IMM_GETCOMPOSITIONSTRINGA(aHIMC, aIndex, (LPVOID)aStrAnsi->BeginWriting(), buflen, lRtn);
07083     aStrAnsi->SetLength(lRtn);
07084 
07085     size_t unicharSize = MultiByteToWideChar(gCurrentKeyboardCP, MB_PRECOMPOSED,
07086       aStrAnsi->get(), aStrAnsi->Length(), NULL, 0);
07087     if (!EnsureStringLength(*aStrUnicode, unicharSize + 1))
07088       return; // out of memory
07089 
07090     unicharSize = MultiByteToWideChar(gCurrentKeyboardCP, MB_PRECOMPOSED,
07091       aStrAnsi->get(), aStrAnsi->Length(), aStrUnicode->BeginWriting(), unicharSize + 1);
07092     aStrUnicode->SetLength(unicharSize);
07093   }
07094 }
07095 
07096 //==========================================================================
07097 BOOL nsWindow::OnIMEComposition(LPARAM aGCS)
07098 {
07099 #ifdef DEBUG_IME
07100   printf("OnIMEComposition\n");
07101 #endif
07102   // for bug #60050
07103   // MS-IME 95/97/98/2000 may send WM_IME_COMPOSITION with non-conversion
07104   // mode before it send WM_IME_STARTCOMPOSITION.
07105   if (!sIMECompUnicode)
07106     sIMECompUnicode = new nsAutoString();
07107 
07108   NS_ASSERTION(sIMECompUnicode, "sIMECompUnicode is null");
07109   if (!sIMECompUnicode)
07110     return PR_TRUE;
07111 
07112   HIMC hIMEContext;
07113   NS_IMM_GETCONTEXT(mWnd, hIMEContext);
07114   if (hIMEContext==NULL) 
07115     return PR_TRUE;
07116 
07117   // will change this if an IME message we handle
07118   BOOL result = PR_FALSE;
07119 
07120   PRBool startCompositionMessageHasBeenSent = sIMEIsComposing;
07121 
07122   //
07123   // This catches a fixed result
07124   //
07125   if (aGCS & GCS_RESULTSTR) {
07126 #ifdef DEBUG_IME
07127     printf("Handling GCS_RESULTSTR\n");
07128 #endif
07129     if (!sIMEIsComposing) 
07130       HandleStartComposition(hIMEContext);
07131 
07132     nsCAutoString strIMECompAnsi;
07133     GetCompositionString(hIMEContext, GCS_RESULTSTR, sIMECompUnicode, &strIMECompAnsi);
07134 #ifdef DEBUG_IME
07135     printf("GCS_RESULTSTR compStrLen = %d\n", sIMECompUnicode->Length());
07136 #endif
07137     result = PR_TRUE;
07138     HandleTextEvent(hIMEContext, PR_FALSE);
07139     HandleEndComposition();
07140   }
07141 
07142 
07143   //
07144   // This provides us with a composition string
07145   //
07146   if (aGCS & (GCS_COMPSTR | GCS_COMPATTR | GCS_COMPCLAUSE | GCS_CURSORPOS))
07147   {
07148 #ifdef DEBUG_IME
07149     printf("Handling GCS_COMPSTR\n");
07150 #endif
07151 
07152     if (!sIMEIsComposing) 
07153       HandleStartComposition(hIMEContext);
07154 
07155     //--------------------------------------------------------
07156     // 1. Get GCS_COMPSTR
07157     //--------------------------------------------------------
07158     nsCAutoString strIMECompAnsi;
07159     GetCompositionString(hIMEContext, GCS_COMPSTR, sIMECompUnicode, &strIMECompAnsi);
07160 
07161     // See https://bugzilla.mozilla.org/show_bug.cgi?id=296339
07162     if (sIMECompUnicode->IsEmpty() &&
07163         !startCompositionMessageHasBeenSent) {
07164       // In this case, maybe, the sender is MSPinYin. That sends *only*
07165       // WM_IME_COMPOSITION with GCS_COMP* and GCS_RESULT* when
07166       // user inputted the Chinese full stop. So, that doesn't send
07167       // WM_IME_STARTCOMPOSITION and WM_IME_ENDCOMPOSITION.
07168       // If WM_IME_STARTCOMPOSITION was not sent and the composition
07169       // string is null (it indicates the composition transaction ended),
07170       // WM_IME_ENDCOMPOSITION may not be sent. If so, we cannot run
07171       // HandleEndComposition() in other place.
07172 #ifdef DEBUG_IME
07173       printf("Aborting GCS_COMPSTR\n");
07174 #endif
07175       HandleEndComposition();
07176       return result;
07177     }
07178 
07179 #ifdef DEBUG_IME
07180     printf("GCS_COMPSTR compStrLen = %d\n", sIMECompUnicode->Length());
07181 #endif
07182 
07183     //--------------------------------------------------------
07184     // 2. Get GCS_COMPCLAUSE
07185     //--------------------------------------------------------
07186     long compClauseLen, compClauseLen2;
07187     NS_IMM_GETCOMPOSITIONSTRING(hIMEContext, GCS_COMPCLAUSE, NULL, 0, compClauseLen);
07188 #ifdef DEBUG_IME
07189     printf("GCS_COMPCLAUSE compClauseLen = %d\n", compClauseLen);
07190 #endif
07191     compClauseLen = compClauseLen / sizeof(PRUint32);
07192 
07193     if (compClauseLen > sIMECompClauseArraySize) {
07194       if (sIMECompClauseArray) 
07195         delete [] sIMECompClauseArray;
07196       // Allocate some extra space to avoid reallocations.
07197       sIMECompClauseArray = new PRUint32[compClauseLen + 32];
07198       sIMECompClauseArraySize = compClauseLen + 32;
07199     }
07200 
07201     NS_IMM_GETCOMPOSITIONSTRING(hIMEContext, GCS_COMPCLAUSE, sIMECompClauseArray,
07202       sIMECompClauseArraySize * sizeof(PRUint32), compClauseLen2);
07203 
07204     compClauseLen2 = compClauseLen2 / sizeof(PRUint32);
07205     NS_ASSERTION(compClauseLen2 == compClauseLen, "strange result");
07206     if (compClauseLen > compClauseLen2)
07207       compClauseLen = compClauseLen2;
07208     sIMECompClauseArrayLength = compClauseLen;
07209 
07210     // if using "A" API, we need to convert A's array of "CLAUSE" to W's that.
07211     if (!nsToolkit::mUseImeApiW && sIMECompClauseArrayLength > 0) {
07212       PRUint32 maxlen = strIMECompAnsi.Length();
07213       // sIMECompClauseArray[0] is always 0. So, converting start from 1.
07214       for (int i = 1; i < sIMECompClauseArrayLength; i++) {
07215 #ifdef DEBUG_IME
07216         printf("sIMECompClauseArray(ANSI)[%d]: %d\n", i, sIMECompClauseArray[i]);
07217 #endif
07218         NS_ASSERTION(sIMECompClauseArray[i] <= maxlen, "wrong offset");
07219         if (sIMECompClauseArray[i] > maxlen)
07220           sIMECompClauseArray[i] = maxlen;
07221 
07222         sIMECompClauseArray[i] = ::MultiByteToWideChar(gCurrentKeyboardCP, MB_PRECOMPOSED,
07223           strIMECompAnsi.get(), sIMECompClauseArray[i], NULL, 0);
07224       }
07225 #ifdef DEBUG_IME
07226       for (int i = 0; i < sIMECompClauseArrayLength; i++) {
07227         printf("sIMECompClauseArray(Unicode)[%d]: %d\n", i, sIMECompClauseArray[i]);
07228       }
07229 #endif
07230     }
07231 
07232     //--------------------------------------------------------
07233     // 3. Get GCS_COMPATTR
07234     //--------------------------------------------------------
07235     // This provides us with the attribute string necessary 
07236     // for doing hiliting
07237     long attrStrLen;
07238     NS_IMM_GETCOMPOSITIONSTRING(hIMEContext, GCS_COMPATTR, NULL, 0, attrStrLen);
07239 #ifdef DEBUG_IME
07240     printf("GCS_COMPATTR attrStrLen = %d\n", attrStrLen);
07241 #endif
07242     if (attrStrLen > sIMEAttributeArraySize) {
07243       if (sIMEAttributeArray) 
07244         delete [] sIMEAttributeArray;
07245       // Allocate some extra space to avoid reallocations.
07246       sIMEAttributeArray = new PRUint8[attrStrLen + 64];
07247       sIMEAttributeArraySize = attrStrLen + 64;
07248     }
07249     NS_IMM_GETCOMPOSITIONSTRING(hIMEContext, GCS_COMPATTR, sIMEAttributeArray, sIMEAttributeArraySize, attrStrLen);
07250 
07251     sIMEAttributeArrayLength = attrStrLen;
07252 
07253     // if using "A" API, we need to convert A's array of "ATTR" to W's that.
07254     if (!nsToolkit::mUseImeApiW && sIMEAttributeArrayLength > 0) {
07255       int offset = 0;
07256       long compUnicodeLength = sIMECompUnicode->Length();
07257       for (int i = 0; i < compUnicodeLength; i++) {
07258 #ifdef DEBUG_IME
07259         printf("sIMEAttributeArray(ANSI)[%d]: %d\n", offset, sIMEAttributeArray[offset]);
07260 #endif
07261         NS_ASSERTION(offset < sIMEAttributeArrayLength, "wrong offset");
07262         if (offset >= sIMEAttributeArrayLength)
07263           offset = sIMEAttributeArrayLength - 1;
07264 
07265         sIMEAttributeArray[i] = sIMEAttributeArray[offset];
07266 
07267         offset += ::WideCharToMultiByte(gCurrentKeyboardCP, 0,
07268           sIMECompUnicode->get() + i, 1, NULL, 0, NULL, NULL);
07269       }
07270 
07271       sIMEAttributeArrayLength = sIMECompUnicode->Length();
07272 #ifdef DEBUG_IME
07273       for (int i = 0; i < sIMEAttributeArrayLength; i++) {
07274         printf("sIMEAttributeArray(Unicode)[%d]: %d\n", i, sIMEAttributeArray[i]);
07275       }
07276 #endif
07277     }
07278 
07279     //--------------------------------------------------------
07280     // 4. Get GCS_CURSOPOS
07281     //--------------------------------------------------------
07282     NS_IMM_GETCOMPOSITIONSTRING(hIMEContext, GCS_CURSORPOS, NULL, 0, sIMECursorPosition);
07283 
07284     // if using "A" API, we need to convert A's "CURSORPOS" to W's that.
07285     if (!nsToolkit::mUseImeApiW && sIMECursorPosition > 0) {
07286       sIMECursorPosition = ::MultiByteToWideChar(gCurrentKeyboardCP, MB_PRECOMPOSED, 
07287                             strIMECompAnsi.get(), sIMECursorPosition, NULL, 0);
07288     }
07289 
07290     NS_ASSERTION(sIMECursorPosition <= sIMECompUnicode->Length(), "illegal pos");
07291 
07292 #ifdef DEBUG_IME
07293     printf("sIMECursorPosition(Unicode): %d\n", sIMECursorPosition);
07294 #endif
07295     //--------------------------------------------------------
07296     // 5. Send the text event
07297     //--------------------------------------------------------
07298     HandleTextEvent(hIMEContext);
07299     result = PR_TRUE;
07300   }
07301   if (!result) {
07302 #ifdef DEBUG_IME
07303     fprintf(stderr,"Haandle 0 length TextEvent. \n");
07304 #endif
07305     if (!sIMEIsComposing) 
07306       HandleStartComposition(hIMEContext);
07307 
07308     sIMECompUnicode->Truncate();
07309     HandleTextEvent(hIMEContext, PR_FALSE);
07310     result = PR_TRUE;
07311   }
07312 
07313   NS_IMM_RELEASECONTEXT(mWnd, hIMEContext);
07314   return result;
07315 }
07316 //==========================================================================
07317 BOOL nsWindow::OnIMECompositionFull()
07318 {
07319 #ifdef DEBUG_IME2
07320   printf("OnIMECompositionFull\n");
07321 #endif
07322 
07323   // not implement yet
07324   return PR_FALSE;
07325 }
07326 //==========================================================================
07327 BOOL nsWindow::OnIMEEndComposition()
07328 {
07329 #ifdef DEBUG_IME
07330   printf("OnIMEEndComposition\n");
07331 #endif
07332   if (sIMEIsComposing) {
07333     HIMC hIMEContext;
07334 
07335     if (sIMEProperty & (IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET)) 
07336       return PR_FALSE;
07337 
07338     NS_IMM_GETCONTEXT(mWnd, hIMEContext);
07339     if (hIMEContext==NULL) 
07340       return PR_TRUE;
07341 
07342     // IME on Korean NT somehow send WM_IME_ENDCOMPOSITION
07343     // first when we hit space in composition mode
07344     // we need to clear out the current composition string
07345     // in that case.
07346     sIMECompUnicode->Truncate(0);
07347 
07348     HandleTextEvent(hIMEContext, PR_FALSE);
07349 
07350     HandleEndComposition();
07351     NS_IMM_RELEASECONTEXT(mWnd, hIMEContext);
07352   }
07353   return PR_TRUE;
07354 }
07355 //==========================================================================
07356 BOOL nsWindow::OnIMENotify(WPARAM aIMN, LPARAM aData, LRESULT *oResult)
07357 {
07358 #ifdef DEBUG_IME2
07359   printf("OnIMENotify ");
07360   switch (aIMN) {
07361     case IMN_CHANGECANDIDATE:
07362       printf("IMN_CHANGECANDIDATE %x\n", aData);
07363       break;
07364     case IMN_CLOSECANDIDATE:
07365       printf("IMN_CLOSECANDIDATE %x\n", aData);
07366       break;
07367     case IMN_CLOSESTATUSWINDOW:
07368       printf("IMN_CLOSESTATUSWINDOW\n");
07369       break;
07370     case IMN_GUIDELINE:
07371       printf("IMN_GUIDELINE\n");
07372       break;
07373     case IMN_OPENCANDIDATE:
07374       printf("IMN_OPENCANDIDATE %x\n", aData);
07375       break;
07376     case IMN_OPENSTATUSWINDOW:
07377       printf("IMN_OPENSTATUSWINDOW\n");
07378       break;
07379     case IMN_SETCANDIDATEPOS:
07380       printf("IMN_SETCANDIDATEPOS %x\n", aData);
07381       break;
07382     case IMN_SETCOMPOSITIONFONT:
07383       printf("IMN_SETCOMPOSITIONFONT\n");
07384       break;
07385     case IMN_SETCOMPOSITIONWINDOW:
07386       printf("IMN_SETCOMPOSITIONWINDOW\n");
07387       break;
07388     case IMN_SETCONVERSIONMODE:
07389       printf("IMN_SETCONVERSIONMODE\n");
07390       break;
07391     case IMN_SETOPENSTATUS:
07392       printf("IMN_SETOPENSTATUS\n");
07393       break;
07394     case IMN_SETSENTENCEMODE:
07395       printf("IMN_SETSENTENCEMODE\n");
07396       break;
07397     case IMN_SETSTATUSWINDOWPOS:
07398       printf("IMN_SETSTATUSWINDOWPOS\n");
07399       break;
07400     case IMN_PRIVATE:
07401       printf("IMN_PRIVATE\n");
07402       break;
07403   };
07404 #endif
07405 
07406   // add hacky code here
07407   if (IS_VK_DOWN(NS_VK_ALT)) {
07408     mIsShiftDown = PR_FALSE;
07409     mIsControlDown = PR_FALSE;
07410     mIsAltDown = PR_TRUE;
07411 
07412     DispatchKeyEvent(NS_KEY_PRESS, 0, 192, 0); // XXX hack hack hack
07413     if (aIMN == IMN_SETOPENSTATUS)
07414       sIMEIsStatusChanged = PR_TRUE;
07415   }
07416   // not implemented yet
07417   return PR_FALSE;
07418 }
07419 //==========================================================================
07420 BOOL nsWindow::OnIMERequest(WPARAM aIMR, LPARAM aData, LRESULT *oResult, PRBool aUseUnicode)
07421 {
07422 #ifdef DEBUG_IME
07423   printf("OnIMERequest\n");
07424 #endif
07425 
07426   PRBool result = PR_FALSE;
07427 
07428   switch (aIMR) {
07429     case IMR_RECONVERTSTRING:
07430       result = OnIMEReconvert(aData, oResult, aUseUnicode);
07431       break;
07432     case IMR_QUERYCHARPOSITION:
07433       result = OnIMEQueryCharPosition(aData, oResult, aUseUnicode);
07434       break;
07435   }
07436 
07437   return result;
07438 }
07439 
07440 //==========================================================================
07441 PRBool nsWindow::OnIMEReconvert(LPARAM aData, LRESULT *oResult, PRBool aUseUnicode)
07442 {
07443 #ifdef DEBUG_IME
07444   printf("OnIMEReconvert\n");
07445 #endif
07446 
07447   PRBool           result  = PR_FALSE;
07448   RECONVERTSTRING* pReconv = (RECONVERTSTRING*) aData;
07449   int              len = 0;
07450 
07451   if (!pReconv) {
07452 
07453     //
07454     // When reconvert, it must return need size to reconvert.
07455     //
07456     if (sIMEReconvertUnicode) {
07457       nsMemory::Free(sIMEReconvertUnicode);
07458       sIMEReconvertUnicode = NULL;
07459     }
07460 
07461     // Get reconversion string
07462     nsReconversionEvent event(PR_TRUE, NS_RECONVERSION_QUERY, this);
07463     nsPoint point(0, 0);
07464 
07465     InitEvent(event, &point);
07466     event.theReply.mReconversionString = NULL;
07467     DispatchWindowEvent(&event);
07468 
07469     sIMEReconvertUnicode = event.theReply.mReconversionString;
07470     NS_RELEASE(event.widget);
07471 
07472     // Return need size
07473 
07474     if (sIMEReconvertUnicode) {
07475       if (aUseUnicode) {
07476         len = nsCRT::strlen(sIMEReconvertUnicode);
07477         *oResult = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
07478       } else {
07479         len = ::WideCharToMultiByte(gCurrentKeyboardCP, 0,
07480                                     sIMEReconvertUnicode,
07481                                     nsCRT::strlen(sIMEReconvertUnicode),
07482                                     NULL, 0, NULL, NULL);
07483         *oResult = sizeof(RECONVERTSTRING) + len;
07484       }
07485 
07486       result = PR_TRUE;
07487     }
07488   } else {
07489 
07490     //
07491     // Fill reconvert struct
07492     //
07493 
07494     if (aUseUnicode) {
07495       len = nsCRT::strlen(sIMEReconvertUnicode);
07496       *oResult = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
07497     } else {
07498       len = ::WideCharToMultiByte(gCurrentKeyboardCP, 0,
07499                                   sIMEReconvertUnicode,
07500                                   nsCRT::strlen(sIMEReconvertUnicode),
07501                                   NULL, 0, NULL, NULL);
07502       *oResult = sizeof(RECONVERTSTRING) + len;
07503     }
07504 
07505     if (pReconv->dwSize < *oResult) {
07506       *oResult = 0;
07507       return PR_FALSE;
07508     }
07509 
07510     DWORD tmpSize = pReconv->dwSize;
07511     ::ZeroMemory(pReconv, tmpSize);
07512     pReconv->dwSize            = tmpSize;
07513     pReconv->dwVersion         = 0;
07514     pReconv->dwStrLen          = len;
07515     pReconv->dwStrOffset       = sizeof(RECONVERTSTRING);
07516     pReconv->dwCompStrLen      = len;
07517     pReconv->dwCompStrOffset   = 0;
07518     pReconv->dwTargetStrLen    = len;
07519     pReconv->dwTargetStrOffset = 0;
07520 
07521     if (aUseUnicode) {
07522       ::CopyMemory((LPVOID) (aData + sizeof(RECONVERTSTRING)),
07523                    sIMEReconvertUnicode, len * sizeof(WCHAR));
07524     } else {
07525       ::WideCharToMultiByte(gCurrentKeyboardCP, 0,
07526                             sIMEReconvertUnicode,
07527                             nsCRT::strlen(sIMEReconvertUnicode),
07528                             (LPSTR) (aData + sizeof(RECONVERTSTRING)),
07529                             len,
07530                             NULL, NULL);
07531     }
07532 
07533     result = PR_TRUE;
07534   }
07535 
07536   return result;
07537 }
07538 
07539 //==========================================================================
07540 PRBool nsWindow::OnIMEQueryCharPosition(LPARAM aData, LRESULT *oResult, PRBool aUseUnicode)
07541 {
07542 #ifdef DEBUG_IME
07543   printf("OnIMEQueryCharPosition\n");
07544 #endif
07545   IMECHARPOSITION* pCharPosition = (IMECHARPOSITION*)aData;
07546   if (!pCharPosition ||
07547       pCharPosition->dwSize < sizeof(IMECHARPOSITION) ||
07548       ::GetFocus() != mWnd) {
07549     *oResult = FALSE;
07550     return PR_FALSE;
07551   }
07552 
07553   if (!sIMEIsComposing) {  // Including |!sIMECompUnicode| and |!sIMECompUnicode->IsEmpty|.
07554     if (pCharPosition->dwCharPos != 0) {
07555       *oResult = FALSE;
07556       return PR_FALSE;
07557     }
07558     nsPoint point(0, 0);
07559     nsQueryCaretRectEvent event(PR_TRUE, NS_QUERYCARETRECT, this);
07560     InitEvent(event, &point);
07561     DispatchWindowEvent(&event);
07562     // The active widget doesn't support this event.
07563     if (!event.theReply.mRectIsValid) {
07564       *oResult = FALSE;
07565       return PR_FALSE;
07566     }
07567     NS_RELEASE(event.widget);
07568 
07569     nsRect screenRect;
07570     ResolveIMECaretPos(nsnull, event.theReply.mCaretRect, screenRect);
07571     pCharPosition->pt.x = screenRect.x;
07572     pCharPosition->pt.y = screenRect.y;
07573 
07574     pCharPosition->cLineHeight = event.theReply.mCaretRect.height;
07575 
07576     ::GetWindowRect(mWnd, &pCharPosition->rcDocument);
07577 
07578     *oResult = TRUE;
07579     return PR_TRUE;
07580   }
07581 
07582   // If the char positions are not cached, we should not return the values by LPARAM.
07583   // Because in this case, the active widget is not editor.
07584   if (!sIMECompCharPos) {
07585     *oResult = FALSE;
07586     return PR_FALSE;
07587   }
07588 
07589   long charPosition;
07590   if (aUseUnicode || pCharPosition->dwCharPos == 0) {
07591     if (pCharPosition->dwCharPos > sIMECompUnicode->Length()) {
07592       *oResult = FALSE;
07593       return PR_FALSE;
07594     }
07595     charPosition = pCharPosition->dwCharPos;
07596   } else {
07597     nsCAutoString strIMECompAnsi;
07598     NS_CopyUnicodeToNative(*sIMECompUnicode, strIMECompAnsi);
07599     if (pCharPosition->dwCharPos > strIMECompAnsi.Length()) {
07600       *oResult = FALSE;
07601       return PR_FALSE;
07602     }
07603     charPosition = ::MultiByteToWideChar(gCurrentKeyboardCP, MB_PRECOMPOSED,
07604                     strIMECompAnsi.get(), pCharPosition->dwCharPos, NULL, 0);
07605   }
07606   // We only support insertion at the cursor position or at the leftmost position.
07607   // Because sIMECompCharPos may be broken by user converting the string.
07608   // But leftmost position and cursor position is always correctly.
07609   if ((charPosition != 0 && charPosition != sIMECursorPosition) ||
07610       charPosition > IME_MAX_CHAR_POS) {
07611     *oResult = FALSE;
07612     return PR_FALSE;
07613   }
07614   POINT pt;
07615   pt.x = sIMECompCharPos[charPosition].left;
07616   pt.y = sIMECompCharPos[charPosition].top;
07617   ::ClientToScreen(mWnd, &pt);
07618   pCharPosition->pt = pt;
07619 
07620   pCharPosition->cLineHeight = sIMECaretHeight;
07621 
07622   ::GetWindowRect(mWnd, &pCharPosition->rcDocument);
07623 
07624   *oResult = TRUE;
07625   return PR_TRUE;
07626 }
07627 
07628 //==========================================================================
07629 void
07630 nsWindow::ResolveIMECaretPos(nsWindow* aClient,
07631                              nsRect&   aEventResult,
07632                              nsRect&   aResult)
07633 {
07634   // RootView coordinates -> Screen coordinates
07635   nsWindow* topWindow = GetTopLevelWindow();
07636   topWindow->WidgetToScreen(aEventResult, aResult);
07637   NS_RELEASE(topWindow);
07638   // if aClient is nsnull, returns screen coordinates
07639   if (!aClient)
07640     return;
07641   // screen coordinates -> client coordinates
07642   aClient->ScreenToWidget(aResult, aResult);
07643 }
07644 
07645 //==========================================================================
07646 BOOL nsWindow::OnIMESelect(BOOL  aSelected, WORD aLangID)
07647 {
07648 #ifdef DEBUG_IME2
07649   printf("OnIMESelect\n");
07650 #endif
07651 
07652   // not implement yet
07653   return PR_FALSE;
07654 }
07655 //==========================================================================
07656 BOOL nsWindow::OnIMESetContext(BOOL aActive, LPARAM& aISC)
07657 {
07658 #ifdef DEBUG_IME2
07659   printf("OnIMESetContext %x %s %s %s Candidate[%s%s%s%s]\n", this,
07660     (aActive ? "Active" : "Deactiv"),
07661     ((aISC & ISC_SHOWUICOMPOSITIONWINDOW) ? "[Comp]" : ""),
07662     ((aISC & ISC_SHOWUIGUIDELINE) ? "[GUID]" : ""),
07663     ((aISC & ISC_SHOWUICANDIDATEWINDOW) ? "0" : ""),
07664     ((aISC & (ISC_SHOWUICANDIDATEWINDOW<<1)) ? "1" : ""),
07665     ((aISC & (ISC_SHOWUICANDIDATEWINDOW<<2)) ? "2" : ""),
07666     ((aISC & (ISC_SHOWUICANDIDATEWINDOW<<3)) ? "3" : ""));
07667 #endif
07668   if (! aActive)
07669     ResetInputState();
07670 
07671   aISC &= ~ISC_SHOWUICOMPOSITIONWINDOW;
07672 
07673   // We still return false here because we need to pass the
07674   // aISC w/ ISC_SHOWUICOMPOSITIONWINDOW clear to the default
07675   // window proc so it will draw the candidcate window for us...
07676   return PR_FALSE;
07677 }
07678 //==========================================================================
07679 BOOL nsWindow::OnIMEStartComposition()
07680 {
07681 #ifdef DEBUG_IME
07682   printf("OnIMEStartComposition\n");
07683 #endif
07684   HIMC hIMEContext;
07685 
07686   if (sIMEProperty & (IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET))
07687     return PR_FALSE;
07688 
07689   NS_IMM_GETCONTEXT(mWnd, hIMEContext);
07690   if (hIMEContext == NULL)
07691     return PR_TRUE;
07692 
07693   PRBool rtn = HandleStartComposition(hIMEContext);
07694   NS_IMM_RELEASECONTEXT(mWnd, hIMEContext);
07695   return rtn;
07696 }
07697 
07698 //==========================================================================
07699 NS_IMETHODIMP nsWindow::ResetInputState()
07700 {
07701 #ifdef DEBUG_KBSTATE
07702   printf("ResetInputState\n");
07703 #endif
07704   HIMC hIMC;
07705   NS_IMM_GETCONTEXT(mWnd, hIMC);
07706   if (hIMC) {
07707     BOOL ret = FALSE;
07708     NS_IMM_NOTIFYIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, NULL, ret);
07709     NS_IMM_NOTIFYIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, NULL, ret);
07710     //NS_ASSERTION(ret, "ImmNotify failed");
07711     NS_IMM_RELEASECONTEXT(mWnd, hIMC);
07712   }
07713   return NS_OK;
07714 }
07715 
07716 //==========================================================================
07717 NS_IMETHODIMP nsWindow::SetIMEOpenState(PRBool aState)
07718 {
07719 #ifdef DEBUG_KBSTATE
07720   printf("SetIMEOpenState %s\n", (aState ? "Open" : "Close"));
07721 #endif 
07722   HIMC hIMC;
07723   NS_IMM_GETCONTEXT(mWnd, hIMC);
07724   if (hIMC) {
07725     NS_IMM_SETOPENSTATUS(hIMC, aState ? TRUE : FALSE);
07726     NS_IMM_RELEASECONTEXT(mWnd, hIMC);
07727   }
07728   return NS_OK;
07729 }
07730 
07731 //==========================================================================
07732 NS_IMETHODIMP nsWindow::GetIMEOpenState(PRBool* aState)
07733 {
07734   HIMC hIMC;
07735   NS_IMM_GETCONTEXT(mWnd, hIMC);
07736   if (hIMC) {
07737     BOOL isOpen;
07738     NS_IMM_GETOPENSTATUS(hIMC, isOpen);
07739     *aState = isOpen ? PR_TRUE : PR_FALSE;
07740     NS_IMM_RELEASECONTEXT(mWnd, hIMC);
07741   } else 
07742     *aState = PR_FALSE;
07743   return NS_OK;
07744 }
07745 
07746 //==========================================================================
07747 NS_IMETHODIMP nsWindow::CancelIMEComposition()
07748 {
07749 #ifdef DEBUG_KBSTATE
07750   printf("CancelIMEComposition\n");
07751 #endif 
07752   HIMC hIMC;
07753   NS_IMM_GETCONTEXT(mWnd, hIMC);
07754   if (hIMC) {
07755     BOOL ret = FALSE;
07756     NS_IMM_NOTIFYIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, NULL, ret);
07757     NS_IMM_RELEASECONTEXT(mWnd, hIMC);
07758   }
07759   return NS_OK;
07760 }
07761 
07762 
07763 #define PT_IN_RECT(pt, rc)  ((pt).x>(rc).left && (pt).x <(rc).right && (pt).y>(rc).top && (pt).y<(rc).bottom)
07764 
07765 // Mouse operation of IME
07766 PRBool
07767 nsWindow::IMEMouseHandling(PRUint32 aEventType, PRInt32 aAction, LPARAM lParam)
07768 {
07769   POINT ptPos;
07770   ptPos.x = (short)LOWORD(lParam);
07771   ptPos.y = (short)HIWORD(lParam);
07772 
07773   if (sIMEIsComposing && nsWindow::uWM_MSIME_MOUSE) {
07774     if (IMECompositionHitTest(aEventType, &ptPos))
07775       if (HandleMouseActionOfIME(aAction, &ptPos))
07776         return PR_TRUE;
07777   } else {
07778     HWND parentWnd = ::GetParent(mWnd);
07779     if (parentWnd) {
07780       nsWindow* parentWidget = GetNSWindowPtr(parentWnd);
07781       if (parentWidget && parentWidget->sIMEIsComposing && nsWindow::uWM_MSIME_MOUSE) {
07782         if (parentWidget->IMECompositionHitTest(aEventType, &ptPos))
07783           if (parentWidget->HandleMouseActionOfIME(aAction, &ptPos))
07784             return PR_TRUE;
07785       }
07786     }
07787   }
07788   return PR_FALSE;
07789 }
07790 
07791 
07792 PRBool
07793 nsWindow::HandleMouseActionOfIME(int aAction, POINT *ptPos)
07794 {
07795   PRBool IsHandle = PR_FALSE;
07796 
07797   if (mWnd) {
07798     HIMC hIMC = NULL;
07799     NS_IMM_GETCONTEXT(mWnd, hIMC);
07800     if (hIMC) {
07801       int positioning = 0;
07802       int offset = 0;
07803 
07804       // calcurate positioning and offset
07805       // char :            JCH1|JCH2|JCH3
07806       // offset:           0011 1122 2233
07807       // positioning:      2301 2301 2301
07808 
07809       // Note: hitText has been done, so no check of sIMECompCharPos
07810       // and composing char maximum limit is necessary.
07811       PRUint32 i = 0;
07812       for (i = 0; i < sIMECompUnicode->Length(); i++) {
07813         if (PT_IN_RECT(*ptPos, sIMECompCharPos[i]))
07814           break;
07815       }
07816       offset = i;
07817       if (ptPos->x - sIMECompCharPos[i].left > sIMECompCharPos[i].right - ptPos->x)
07818         offset++;
07819 
07820       positioning = (ptPos->x - sIMECompCharPos[i].left) * 4 /
07821                     (sIMECompCharPos[i].right - sIMECompCharPos[i].left);
07822       positioning = (positioning + 2) % 4;
07823 
07824       // send MS_MSIME_MOUSE message to default IME window.
07825       HWND imeWnd;
07826       NS_IMM_GETDEFAULTIMEWND(mWnd, &imeWnd);
07827       if (nsToolkit::mSendMessage(imeWnd, nsWindow::uWM_MSIME_MOUSE,
07828                                   MAKELONG(MAKEWORD(aAction, positioning), offset),
07829                                   (LPARAM) hIMC) == 1)
07830         IsHandle = PR_TRUE;
07831     }
07832     NS_IMM_RELEASECONTEXT(mWnd, hIMC);
07833   }
07834 
07835   return IsHandle;
07836 }
07837 
07838 //The coordinate is relative to the upper-left corner of the client area.
07839 PRBool nsWindow::IMECompositionHitTest(PRUint32 aEventType, POINT * ptPos)
07840 {
07841   PRBool IsHit = PR_FALSE;
07842 
07843   if (sIMECompCharPos){
07844     // figure out how many char in composing string,
07845     // but keep it below the limit we can handle
07846     PRInt32 len = sIMECompUnicode->Length();
07847     if (len > IME_MAX_CHAR_POS)
07848       len = IME_MAX_CHAR_POS;
07849 
07850     PRInt32 i;
07851     PRInt32 aveWidth = 0;
07852     // found per char width
07853     for (i = 0; i < len; i++) {
07854       if (sIMECompCharPos[i].left >= 0 && sIMECompCharPos[i].right > 0) {
07855         aveWidth = sIMECompCharPos[i].right - sIMECompCharPos[i].left;
07856         break;
07857       }
07858     }
07859 
07860     // validate each rect and test
07861     for (i = 0; i < len; i++) {
07862       if (sIMECompCharPos[i].left < 0) {
07863         if (i != 0 && sIMECompCharPos[i-1].top == sIMECompCharPos[i].top)
07864           sIMECompCharPos[i].left = sIMECompCharPos[i-1].right;
07865         else
07866           sIMECompCharPos[i].left = sIMECompCharPos[i].right - aveWidth;
07867       }
07868       if (sIMECompCharPos[i].right < 0)
07869         sIMECompCharPos[i].right = sIMECompCharPos[i].left + aveWidth;
07870       if (sIMECompCharPos[i].top < 0) {
07871         sIMECompCharPos[i].top = sIMECompCharPos[i-1].top;
07872         sIMECompCharPos[i].bottom = sIMECompCharPos[i-1].bottom;
07873       }
07874 
07875       if (PT_IN_RECT(*ptPos, sIMECompCharPos[i])) {
07876         IsHit = PR_TRUE;
07877         break;
07878       }
07879     }
07880   }
07881 
07882   return IsHit;
07883 }
07884 
07885 void nsWindow::GetCompositionWindowPos(HIMC hIMC, PRUint32 aEventType, COMPOSITIONFORM *cpForm)
07886 {
07887   nsTextEvent event(PR_TRUE, 0, this);
07888   POINT point;
07889   point.x = 0;
07890   point.y = 0;
07891   DWORD pos = ::GetMessagePos();
07892 
07893   point.x = GET_X_LPARAM(pos);
07894   point.y = GET_Y_LPARAM(pos);
07895 
07896   if (mWnd != NULL) {
07897     ::ScreenToClient(mWnd, &point);
07898     event.point.x = point.x;
07899     event.point.y = point.y;
07900   } else {
07901     event.point.x = 0;
07902     event.point.y = 0;
07903   }
07904 
07905   NS_IMM_GETCOMPOSITIONWINDOW(hIMC, cpForm);
07906 
07907   cpForm->ptCurrentPos.x = event.theReply.mCursorPosition.x + IME_X_OFFSET;
07908   cpForm->ptCurrentPos.y = event.theReply.mCursorPosition.y + IME_Y_OFFSET +
07909                            event.theReply.mCursorPosition.height;
07910   cpForm->rcArea.left = cpForm->ptCurrentPos.x;
07911   cpForm->rcArea.top = cpForm->ptCurrentPos.y;
07912   cpForm->rcArea.right = cpForm->ptCurrentPos.x + event.theReply.mCursorPosition.width;
07913   cpForm->rcArea.bottom = cpForm->ptCurrentPos.y + event.theReply.mCursorPosition.height;
07914 }
07915 
07916 // This function is called on a timer to do the flashing.  It simply toggles the flash
07917 // status until the window comes to the foreground.
07918 static VOID CALLBACK nsGetAttentionTimerFunc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
07919 {
07920   // flash the window until we're in the foreground.
07921   if (::GetForegroundWindow() != hwnd)
07922   {
07923     // flash the outermost owner
07924     HWND flashwnd = gAttentionTimerMonitor->GetFlashWindowFor(hwnd);
07925 
07926     PRInt32 maxFlashCount = gAttentionTimerMonitor->GetMaxFlashCount(hwnd);
07927     PRInt32 flashCount = gAttentionTimerMonitor->GetFlashCount(hwnd);
07928     if (maxFlashCount > 0) {
07929       // We have a max flash count, if we haven't met it yet, flash again.
07930       if (flashCount < maxFlashCount) {
07931         ::FlashWindow(flashwnd, TRUE);
07932         gAttentionTimerMonitor->IncrementFlashCount(hwnd);
07933       }
07934       else
07935         gAttentionTimerMonitor->KillTimer(hwnd);
07936     }
07937     else {
07938       // The caller didn't specify a flash count.
07939       ::FlashWindow(flashwnd, TRUE);
07940     }
07941 
07942     gAttentionTimerMonitor->SetFlashed(hwnd);
07943   }
07944   else
07945     gAttentionTimerMonitor->KillTimer(hwnd);
07946 }
07947 
07948 // Draw user's attention to this window until it comes to foreground.
07949 NS_IMETHODIMP
07950 nsWindow::GetAttention(PRInt32 aCycleCount)
07951 {
07952   // Got window?
07953   if (!mWnd)
07954     return NS_ERROR_NOT_INITIALIZED;
07955 
07956   // Don't flash if the flash count is 0.
07957   if (aCycleCount == 0)
07958     return NS_OK;
07959 
07960   // timer is on the parentmost window; window to flash is its ownermost
07961   HWND timerwnd = GetTopLevelHWND(mWnd);
07962   HWND flashwnd = timerwnd;
07963   HWND nextwnd;
07964   while ((nextwnd = ::GetWindow(flashwnd, GW_OWNER)) != 0)
07965     flashwnd = nextwnd;
07966 
07967   // If window is in foreground, no notification is necessary.
07968   if (::GetForegroundWindow() != timerwnd) {
07969     // kick off a timer that does single flash until the window comes to the foreground
07970     if (!gAttentionTimerMonitor)
07971       gAttentionTimerMonitor = new nsAttentionTimerMonitor;
07972     if (gAttentionTimerMonitor) {
07973       gAttentionTimerMonitor->AddTimer(timerwnd, flashwnd, aCycleCount, NS_FLASH_TIMER_ID);
07974       ::SetTimer(timerwnd, NS_FLASH_TIMER_ID, GetCaretBlinkTime(), (TIMERPROC)nsGetAttentionTimerFunc);
07975     }
07976   }
07977 
07978   return NS_OK;
07979 }
07980 
07981 NS_IMETHODIMP
07982 nsWindow::GetLastInputEventTime(PRUint32& aTime)
07983 {
07984   WORD qstatus = HIWORD(GetQueueStatus(QS_INPUT));
07985 
07986   // If there is pending input or the user is currently
07987   // moving the window then return the current time.
07988   // Note: When the user is moving the window WIN32 spins
07989   // a separate event loop and input events are not
07990   // reported to the application.
07991   nsToolkit* toolkit = (nsToolkit *)mToolkit;
07992   if (qstatus || (toolkit && toolkit->UserIsMovingWindow())) {
07993     gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
07994   }
07995 
07996   aTime = gLastInputEventTime;
07997 
07998   return NS_OK;
07999 }
08000 
08001 //-------------------------------------------------------------------------
08002 //-------------------------------------------------------------------------
08003 //-- NOTE!!! These hook functions can be removed when we migrate to
08004 //-- XBL-Form Controls
08005 //-------------------------------------------------------------------------
08006 //-------------------------------------------------------------------------
08007 //#define DISPLAY_NOISY_MSGF_MSG
08008 
08009 #ifdef DISPLAY_NOISY_MSGF_MSG
08010 typedef struct {
08011   char * mStr;
08012   int    mId;
08013 } MSGFEventMsgInfo;
08014 
08015 MSGFEventMsgInfo gMSGFEvents[] = {
08016   "MSGF_DIALOGBOX",      0,
08017   "MSGF_MESSAGEBOX",     1,
08018   "MSGF_MENU",           2,
08019   "MSGF_SCROLLBAR",      5,
08020   "MSGF_NEXTWINDOW",     6,
08021   "MSGF_MAX",            8,
08022   "MSGF_USER",           4096,
08023   NULL, 0};
08024 
08025   void PrintEvent(UINT msg, PRBool aShowAllEvents, PRBool aShowMouseMoves);
08026   int gLastMsgCode = 0;
08027 
08028 #define DISPLAY_NMM_PRT(_arg) printf((_arg));
08029 #else
08030 #define DISPLAY_NMM_PRT(_arg)
08031 #endif
08032 
08033 
08034 
08035 #ifndef WINCE
08036 
08037 //-------------------------------------------------------------------------
08038 // Schedules a timer for a window, so we can rollup after processing the hook event
08039 void nsWindow::ScheduleHookTimer(HWND aWnd, UINT aMsgId)
08040 {
08041   // In some cases multiple hooks may be scheduled
08042   // so ignore any other requests once one timer is scheduled
08043   if (gHookTimerId == 0) {
08044     // Remember the window handle and the message ID to be used later
08045     gRollupMsgId = aMsgId;
08046     gRollupMsgWnd = aWnd;
08047     // Schedule native timer for doing the rollup after
08048     // this event is done being processed
08049     gHookTimerId = ::SetTimer(NULL, 0, 0, (TIMERPROC)HookTimerForPopups);
08050     NS_ASSERTION(gHookTimerId, "Timer couldn't be created.");
08051   }
08052 }
08053 
08054 //-------------------------------------------------------------------------
08055 // Process Menu messages
08056 // Rollup when when is clicked
08057 
08058 LRESULT CALLBACK nsWindow::MozSpecialMsgFilter(int code, WPARAM wParam, LPARAM lParam)
08059 {
08060 #ifdef DISPLAY_NOISY_MSGF_MSG
08061   if (gProcessHook) {
08062     MSG* pMsg = (MSG*)lParam;
08063 
08064     int inx = 0;
08065     while (gMSGFEvents[inx].mId != code && gMSGFEvents[inx].mStr != NULL) {
08066       inx++;
08067     }
08068     if (code != gLastMsgCode) {
08069       if (gMSGFEvents[inx].mId == code) {
08070 #ifdef DEBUG
08071         printf("MozSpecialMessageProc - code: 0x%X  - %s  hw: %p\n", code, gMSGFEvents[inx].mStr, pMsg->hwnd);
08072 #endif
08073       } else {
08074 #ifdef DEBUG
08075         printf("MozSpecialMessageProc - code: 0x%X  - %d  hw: %p\n", code, gMSGFEvents[inx].mId, pMsg->hwnd);
08076 #endif
08077       }
08078       gLastMsgCode = code;
08079     }
08080     PrintEvent(pMsg->message, FALSE, FALSE);
08081   }
08082 #endif
08083 
08084   if (gProcessHook && code == MSGF_MENU) {
08085     MSG* pMsg = (MSG*)lParam;
08086     ScheduleHookTimer( pMsg->hwnd, pMsg->message);
08087   }
08088 
08089   return ::CallNextHookEx(gMsgFilterHook, code, wParam, lParam);
08090 }
08091 
08092 //-------------------------------------------------------------------------
08093 // Process all mouse messages
08094 // Roll up when a click is in a native window that doesn't have an nsIWidget
08095 LRESULT CALLBACK nsWindow::MozSpecialMouseProc(int code, WPARAM wParam, LPARAM lParam)
08096 {
08097   if (gProcessHook) {
08098     MOUSEHOOKSTRUCT* ms = (MOUSEHOOKSTRUCT*)lParam;
08099     if (wParam == WM_LBUTTONDOWN) {
08100       nsIWidget* mozWin = (nsIWidget*)GetNSWindowPtr(ms->hwnd);
08101       if (mozWin == NULL) {
08102         ScheduleHookTimer(ms->hwnd, (UINT)wParam);
08103       }
08104     }
08105   }
08106   return ::CallNextHookEx(gCallMouseHook, code, wParam, lParam);
08107 }
08108 
08109 //-------------------------------------------------------------------------
08110 // Process all messages
08111 // Roll up when the window is moving, or is resizing or when maximized or mininized
08112 LRESULT CALLBACK nsWindow::MozSpecialWndProc(int code, WPARAM wParam, LPARAM lParam)
08113 {
08114 #ifdef DISPLAY_NOISY_MSGF_MSG
08115   if (gProcessHook) {
08116     CWPSTRUCT* cwpt = (CWPSTRUCT*)lParam;
08117     PrintEvent(cwpt->message, FALSE, FALSE);
08118   }
08119 #endif
08120 
08121   if (gProcessHook) {
08122     CWPSTRUCT* cwpt = (CWPSTRUCT*)lParam;
08123     if (cwpt->message == WM_MOVING ||
08124         cwpt->message == WM_SIZING ||
08125         cwpt->message == WM_GETMINMAXINFO) {
08126       ScheduleHookTimer(cwpt->hwnd, (UINT)cwpt->message);
08127     }
08128   }
08129 
08130   return ::CallNextHookEx(gCallProcHook, code, wParam, lParam);
08131 }
08132 
08133 //-------------------------------------------------------------------------
08134 // Register the special "hooks" for dropdown processing
08135 
08136 void nsWindow::RegisterSpecialDropdownHooks()
08137 {
08138   NS_ASSERTION(!gMsgFilterHook, "gMsgFilterHook must be NULL!");
08139   NS_ASSERTION(!gCallProcHook,  "gCallProcHook must be NULL!");
08140 
08141   DISPLAY_NMM_PRT("***************** Installing Msg Hooks ***************\n");
08142 
08143   //HMODULE hMod = GetModuleHandle("gkwidget.dll");
08144 
08145   // Install msg hook for moving the window and resizing
08146   if (!gMsgFilterHook) {
08147     DISPLAY_NMM_PRT("***** Hooking gMsgFilterHook!\n");
08148     gMsgFilterHook = SetWindowsHookEx(WH_MSGFILTER, MozSpecialMsgFilter, NULL, GetCurrentThreadId());
08149 #ifdef DISPLAY_NOISY_MSGF_MSG
08150     if (!gMsgFilterHook) {
08151       printf("***** SetWindowsHookEx is NOT installed for WH_MSGFILTER!\n");
08152     }
08153 #endif
08154   }
08155 
08156   // Install msg hook for menus
08157   if (!gCallProcHook) {
08158     DISPLAY_NMM_PRT("***** Hooking gCallProcHook!\n");
08159     gCallProcHook  = SetWindowsHookEx(WH_CALLWNDPROC, MozSpecialWndProc, NULL, GetCurrentThreadId());
08160 #ifdef DISPLAY_NOISY_MSGF_MSG
08161     if (!gCallProcHook) {
08162       printf("***** SetWindowsHookEx is NOT installed for WH_CALLWNDPROC!\n");
08163     }
08164 #endif
08165   }
08166 
08167   // Install msg hook for the mouse
08168   if (!gCallMouseHook) {
08169     DISPLAY_NMM_PRT("***** Hooking gCallMouseHook!\n");
08170     gCallMouseHook  = SetWindowsHookEx(WH_MOUSE, MozSpecialMouseProc, NULL, GetCurrentThreadId());
08171 #ifdef DISPLAY_NOISY_MSGF_MSG
08172     if (!gCallMouseHook) {
08173       printf("***** SetWindowsHookEx is NOT installed for WH_MOUSE!\n");
08174     }
08175 #endif
08176   }
08177 }
08178 
08179 //-------------------------------------------------------------------------
08180 // Unhook special message hooks for dropdowns
08181 
08182 void nsWindow::UnregisterSpecialDropdownHooks()
08183 {
08184   DISPLAY_NMM_PRT("***************** De-installing Msg Hooks ***************\n");
08185 
08186   if (gCallProcHook) {
08187     DISPLAY_NMM_PRT("***** Unhooking gCallProcHook!\n");
08188     if (!::UnhookWindowsHookEx(gCallProcHook)) {
08189       DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for gCallProcHook!\n");
08190     }
08191     gCallProcHook = NULL;
08192   }
08193 
08194   if (gMsgFilterHook) {
08195     DISPLAY_NMM_PRT("***** Unhooking gMsgFilterHook!\n");
08196     if (!::UnhookWindowsHookEx(gMsgFilterHook)) {
08197       DISPLAY_NMM_PRT("***** UnhookWindowsHookEx failed for gMsgFilterHook!\n");
08198     }
08199     gMsgFilterHook = NULL;
08200   }
08201 
08202   if (gCallMouseHook) {
08203     DISPLAY_NMM_PRT("***** Unhooking gCallMouseHook!\n");
08204     if (!::UnhookWindowsHookEx(gCallMouseHook)) {
08205