1 /*
   2  * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "awt.h"
  27 
  28 #include <windowsx.h>
  29 #include <zmouse.h>
  30 
  31 #include "jlong.h"
  32 #include "awt_AWTEvent.h"
  33 #include "awt_BitmapUtil.h"
  34 #include "awt_Component.h"
  35 #include "awt_Cursor.h"
  36 #include "awt_Dimension.h"
  37 #include "awt_Frame.h"
  38 #include "awt_InputEvent.h"
  39 #include "awt_InputTextInfor.h"
  40 #include "awt_Insets.h"
  41 #include "awt_KeyEvent.h"
  42 #include "awt_MenuItem.h"
  43 #include "awt_MouseEvent.h"
  44 #include "awt_Palette.h"
  45 #include "awt_Toolkit.h"
  46 #include "awt_Window.h"
  47 #include "awt_Win32GraphicsDevice.h"
  48 #include "Hashtable.h"
  49 #include "ComCtl32Util.h"
  50 
  51 #include <Region.h>
  52 
  53 #include <jawt.h>
  54 
  55 #include <java_awt_Toolkit.h>
  56 #include <java_awt_FontMetrics.h>
  57 #include <java_awt_Color.h>
  58 #include <java_awt_Event.h>
  59 #include <java_awt_event_KeyEvent.h>
  60 #include <java_awt_Insets.h>
  61 #include <sun_awt_windows_WPanelPeer.h>
  62 #include <java_awt_event_InputEvent.h>
  63 #include <java_awt_event_ActionEvent.h>
  64 #include <java_awt_event_InputMethodEvent.h>
  65 #include <sun_awt_windows_WInputMethod.h>
  66 #include <java_awt_event_MouseEvent.h>
  67 #include <java_awt_event_MouseWheelEvent.h>
  68 
  69 // Begin -- Win32 SDK include files
  70 #include <imm.h>
  71 #include <ime.h>
  72 // End -- Win32 SDK include files
  73 
  74 #include <awt_DnDDT.h>
  75 
  76 LPCTSTR szAwtComponentClassName = TEXT("SunAwtComponent");
  77 // register a message that no other window in the process (even in a plugin
  78 // scenario) will be using
  79 const UINT AwtComponent::WmAwtIsComponent =
  80     ::RegisterWindowMessage(szAwtComponentClassName);
  81 
  82 static HWND g_hwndDown = NULL;
  83 static DCList activeDCList;
  84 static DCList passiveDCList;
  85 
  86 extern void CheckFontSmoothingSettings(HWND);
  87 
  88 extern "C" {
  89     // Remember the input language has changed by some user's action
  90     // (Alt+Shift or through the language icon on the Taskbar) to control the
  91     // race condition between the toolkit thread and the AWT event thread.
  92     // This flag remains TRUE until the next WInputMethod.getNativeLocale() is
  93     // issued.
  94     BOOL g_bUserHasChangedInputLang = FALSE;
  95 }
  96 
  97 BOOL AwtComponent::sm_suppressFocusAndActivation = FALSE;
  98 BOOL AwtComponent::sm_restoreFocusAndActivation = FALSE;
  99 HWND AwtComponent::sm_focusOwner = NULL;
 100 HWND AwtComponent::sm_focusedWindow = NULL;
 101 BOOL AwtComponent::sm_bMenuLoop = FALSE;
 102 AwtComponent* AwtComponent::sm_getComponentCache = NULL;
 103 BOOL AwtComponent::sm_inSynthesizeFocus = FALSE;
 104 
 105 /************************************************************************/
 106 // Struct for _Reshape() and ReshapeNoCheck() methods
 107 struct ReshapeStruct {
 108     jobject component;
 109     jint x, y;
 110     jint w, h;
 111 };
 112 // Struct for _NativeHandleEvent() method
 113 struct NativeHandleEventStruct {
 114     jobject component;
 115     jobject event;
 116 };
 117 // Struct for _SetForeground() and _SetBackground() methods
 118 struct SetColorStruct {
 119     jobject component;
 120     jint rgb;
 121 };
 122 // Struct for _SetFont() method
 123 struct SetFontStruct {
 124     jobject component;
 125     jobject font;
 126 };
 127 // Struct for _CreatePrintedPixels() method
 128 struct CreatePrintedPixelsStruct {
 129     jobject component;
 130     int srcx, srcy;
 131     int srcw, srch;
 132     jint alpha;
 133 };
 134 // Struct for _SetRectangularShape() method
 135 struct SetRectangularShapeStruct {
 136     jobject component;
 137     jint x1, x2, y1, y2;
 138     jobject region;
 139 };
 140 // Struct for _GetInsets function
 141 struct GetInsetsStruct {
 142     jobject window;
 143     RECT *insets;
 144 };
 145 // Struct for _SetZOrder function
 146 struct SetZOrderStruct {
 147     jobject component;
 148     jlong above;
 149 };
 150 // Struct for _SetFocus function
 151 struct SetFocusStruct {
 152     jobject component;
 153     jboolean doSetFocus;
 154 };
 155 /************************************************************************/
 156 
 157 //////////////////////////////////////////////////////////////////////////
 158 
 159 /*************************************************************************
 160  * AwtComponent fields
 161  */
 162 
 163 
 164 jfieldID AwtComponent::peerID;
 165 jfieldID AwtComponent::xID;
 166 jfieldID AwtComponent::yID;
 167 jfieldID AwtComponent::widthID;
 168 jfieldID AwtComponent::heightID;
 169 jfieldID AwtComponent::visibleID;
 170 jfieldID AwtComponent::backgroundID;
 171 jfieldID AwtComponent::foregroundID;
 172 jfieldID AwtComponent::enabledID;
 173 jfieldID AwtComponent::parentID;
 174 jfieldID AwtComponent::graphicsConfigID;
 175 jfieldID AwtComponent::peerGCID;
 176 jfieldID AwtComponent::focusableID;
 177 jfieldID AwtComponent::appContextID;
 178 jfieldID AwtComponent::cursorID;
 179 jfieldID AwtComponent::hwndID;
 180 
 181 jmethodID AwtComponent::getFontMID;
 182 jmethodID AwtComponent::getToolkitMID;
 183 jmethodID AwtComponent::isEnabledMID;
 184 jmethodID AwtComponent::getLocationOnScreenMID;
 185 jmethodID AwtComponent::replaceSurfaceDataMID;
 186 jmethodID AwtComponent::replaceSurfaceDataLaterMID;
 187 jmethodID AwtComponent::disposeLaterMID;
 188 
 189 HKL    AwtComponent::m_hkl = ::GetKeyboardLayout(0);
 190 LANGID AwtComponent::m_idLang = LOWORD(::GetKeyboardLayout(0));
 191 UINT   AwtComponent::m_CodePage
 192                        = AwtComponent::LangToCodePage(m_idLang);
 193 
 194 jint *AwtComponent::masks;
 195 
 196 static BOOL bLeftShiftIsDown = false;
 197 static BOOL bRightShiftIsDown = false;
 198 static UINT lastShiftKeyPressed = 0; // init to safe value
 199 
 200 // Added by waleed to initialize the RTL Flags
 201 BOOL AwtComponent::sm_rtl = PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC ||
 202                             PRIMARYLANGID(GetInputLanguage()) == LANG_HEBREW;
 203 BOOL AwtComponent::sm_rtlReadingOrder =
 204     PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC;
 205 
 206 BOOL AwtComponent::sm_PrimaryDynamicTableBuilt = FALSE;
 207 
 208 HWND AwtComponent::sm_cursorOn;
 209 BOOL AwtComponent::m_QueryNewPaletteCalled = FALSE;
 210 
 211 CriticalSection windowMoveLock;
 212 BOOL windowMoveLockHeld = FALSE;
 213 
 214 /************************************************************************
 215  * AwtComponent methods
 216  */
 217 
 218 AwtComponent::AwtComponent()
 219 {
 220     m_mouseButtonClickAllowed = 0;
 221     m_callbacksEnabled = FALSE;
 222     m_hwnd = NULL;
 223 
 224     m_colorForeground = 0;
 225     m_colorBackground = 0;
 226     m_backgroundColorSet = FALSE;
 227     m_penForeground = NULL;
 228     m_brushBackground = NULL;
 229     m_DefWindowProc = NULL;
 230     m_nextControlID = 1;
 231     m_childList = NULL;
 232     m_myControlID = 0;
 233     m_hdwp = NULL;
 234     m_validationNestCount = 0;
 235 
 236     m_dropTarget = NULL;
 237 
 238     m_InputMethod = NULL;
 239     m_useNativeCompWindow = TRUE;
 240     m_PendingLeadByte = 0;
 241     m_bitsCandType = 0;
 242 
 243     windowMoveLockPosX = 0;
 244     windowMoveLockPosY = 0;
 245     windowMoveLockPosCX = 0;
 246     windowMoveLockPosCY = 0;
 247 
 248     m_hCursorCache = NULL;
 249 
 250     m_bSubclassed = FALSE;
 251     m_bPauseDestroy = FALSE;
 252 
 253     m_MessagesProcessing = 0;
 254     m_wheelRotationAmount = 0;
 255     if (!sm_PrimaryDynamicTableBuilt) {
 256         // do it once.
 257         AwtComponent::BuildPrimaryDynamicTable();
 258         sm_PrimaryDynamicTableBuilt = TRUE;
 259     }
 260 
 261     deadKeyActive = FALSE;
 262 }
 263 
 264 AwtComponent::~AwtComponent()
 265 {
 266     DASSERT(AwtToolkit::IsMainThread());
 267 
 268     /* Disconnect all links. */
 269     UnlinkObjects();
 270 
 271     /*
 272      * All the messages for this component are processed, native
 273      * resources are freed, and Java object is not connected to
 274      * the native one anymore. So we can safely destroy component's
 275      * handle.
 276      */
 277     DestroyHWnd();
 278 
 279     if (sm_getComponentCache == this) {
 280         sm_getComponentCache = NULL;
 281     }
 282 }
 283 
 284 void AwtComponent::Dispose()
 285 {
 286     // NOTE: in case the component/toplevel was focused, Java should
 287     // have already taken care of proper transferring it or clearing.
 288 
 289     if (m_hdwp != NULL) {
 290     // end any deferred window positioning, regardless
 291     // of m_validationNestCount
 292         ::EndDeferWindowPos(m_hdwp);
 293     }
 294 
 295     // Send final message to release all DCs associated with this component
 296     SendMessage(WM_AWT_RELEASE_ALL_DCS);
 297 
 298     /* Stop message filtering. */
 299     UnsubclassHWND();
 300 
 301     /* Release global ref to input method */
 302     SetInputMethod(NULL, TRUE);
 303 
 304     if (m_childList != NULL)
 305         delete m_childList;
 306 
 307     DestroyDropTarget();
 308     ReleaseDragCapture(0);
 309 
 310     if (m_myControlID != 0) {
 311         AwtComponent* parent = GetParent();
 312         if (parent != NULL)
 313             parent->RemoveChild(m_myControlID);
 314     }
 315 
 316     ::RemoveProp(GetHWnd(), DrawingStateProp);
 317 
 318     /* Release any allocated resources. */
 319     if (m_penForeground != NULL) {
 320         m_penForeground->Release();
 321         m_penForeground = NULL;
 322     }
 323     if (m_brushBackground != NULL) {
 324         m_brushBackground->Release();
 325         m_brushBackground = NULL;
 326     }
 327 
 328     if (m_bPauseDestroy) {
 329         // AwtComponent::WmNcDestroy could be released now
 330         m_bPauseDestroy = FALSE;
 331         m_hwnd = NULL;
 332     }
 333 
 334     // The component instance is deleted using AwtObject::Dispose() method
 335     AwtObject::Dispose();
 336 }
 337 
 338 /* store component pointer in window extra bytes */
 339 void AwtComponent::SetComponentInHWND() {
 340     DASSERT(::GetWindowLongPtr(GetHWnd(), GWLP_USERDATA) == NULL);
 341     ::SetWindowLongPtr(GetHWnd(), GWLP_USERDATA, (LONG_PTR)this);
 342 }
 343 
 344 /*
 345  * static function to get AwtComponent pointer from hWnd --
 346  * you don't want to call this from inside a wndproc to avoid
 347  * infinite recursion
 348  */
 349 AwtComponent* AwtComponent::GetComponent(HWND hWnd) {
 350     // Requests for Toolkit hwnd resolution happen pretty often. Check first.
 351     if (hWnd == AwtToolkit::GetInstance().GetHWnd()) {
 352         return NULL;
 353     }
 354     if (sm_getComponentCache && sm_getComponentCache->GetHWnd() == hWnd) {
 355         return sm_getComponentCache;
 356     }
 357 
 358     // check that it's an AWT component from the same toolkit as the caller
 359     if (::IsWindow(hWnd) &&
 360         AwtToolkit::MainThread() == ::GetWindowThreadProcessId(hWnd, NULL))
 361     {
 362         DASSERT(WmAwtIsComponent != 0);
 363         if (::SendMessage(hWnd, WmAwtIsComponent, 0, 0L)) {
 364             return sm_getComponentCache = GetComponentImpl(hWnd);
 365         }
 366     }
 367     return NULL;
 368 }
 369 
 370 /*
 371  * static function to get AwtComponent pointer from hWnd--
 372  * different from GetComponent because caller knows the
 373  * hwnd is an AWT component hwnd
 374  */
 375 AwtComponent* AwtComponent::GetComponentImpl(HWND hWnd) {
 376     AwtComponent *component =
 377         (AwtComponent *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
 378     DASSERT(!component || !IsBadReadPtr(component, sizeof(AwtComponent)) );
 379     DASSERT(!component || component->GetHWnd() == hWnd );
 380     return component;
 381 }
 382 
 383 /*
 384  * Single window proc for all the components. Delegates real work to
 385  * the component's WindowProc() member function.
 386  */
 387 LRESULT CALLBACK AwtComponent::WndProc(HWND hWnd, UINT message,
 388                                        WPARAM wParam, LPARAM lParam)
 389 {
 390     TRY;
 391 
 392     AwtComponent * self = AwtComponent::GetComponentImpl(hWnd);
 393     if (self == NULL || self->GetHWnd() != hWnd ||
 394         message == WM_UNDOCUMENTED_CLIENTSHUTDOWN) // handle log-off gracefully
 395     {
 396         return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam);
 397     } else {
 398         return self->WindowProc(message, wParam, lParam);
 399     }
 400 
 401     CATCH_BAD_ALLOC_RET(0);
 402 }
 403 
 404 BOOL AwtComponent::IsFocusable() {
 405     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 406     jobject peer = GetPeer(env);
 407     jobject target = env->GetObjectField(peer, AwtObject::targetID);
 408     BOOL res = env->GetBooleanField(target, focusableID);
 409     AwtWindow *pCont = GetContainer();
 410     if (pCont) {
 411         res &= pCont->IsFocusableWindow();
 412     }
 413     env->DeleteLocalRef(target);
 414     return res;
 415 }
 416 
 417 /************************************************************************
 418  * AwtComponent dynamic methods
 419  *
 420  * Window class registration routines
 421  */
 422 
 423 /*
 424  * Fix for 4964237: Win XP: Changing theme changes java dialogs title icon
 425  */
 426 void AwtComponent::FillClassInfo(WNDCLASSEX *lpwc)
 427 {
 428     lpwc->cbSize        = sizeof(WNDCLASSEX);
 429     lpwc->style         = 0L;//CS_OWNDC;
 430     lpwc->lpfnWndProc   = (WNDPROC)::DefWindowProc;
 431     lpwc->cbClsExtra    = 0;
 432     lpwc->cbWndExtra    = 0;
 433     lpwc->hInstance     = AwtToolkit::GetInstance().GetModuleHandle(),
 434     lpwc->hIcon         = AwtToolkit::GetInstance().GetAwtIcon();
 435     lpwc->hCursor       = NULL;
 436     lpwc->hbrBackground = NULL;
 437     lpwc->lpszMenuName  = NULL;
 438     lpwc->lpszClassName = GetClassName();
 439     //Fixed 6233560: PIT: Java Cup Logo on the title bar of top-level windows look blurred, Win32
 440     lpwc->hIconSm       = AwtToolkit::GetInstance().GetAwtIconSm();
 441 }
 442 
 443 void AwtComponent::RegisterClass()
 444 {
 445     WNDCLASSEX wc;
 446     if (!::GetClassInfoEx(AwtToolkit::GetInstance().GetModuleHandle(), GetClassName(), &wc)) {
 447         FillClassInfo(&wc);
 448         ATOM ret = ::RegisterClassEx(&wc);
 449         DASSERT(ret != 0);
 450     }
 451 }
 452 
 453 void AwtComponent::UnregisterClass()
 454 {
 455     ::UnregisterClass(GetClassName(), AwtToolkit::GetInstance().GetModuleHandle());
 456 }
 457 
 458 /*
 459  * Copy the graphicsConfig reference from Component into WComponentPeer
 460  */
 461 void AwtComponent::InitPeerGraphicsConfig(JNIEnv *env, jobject peer)
 462 {
 463     jobject target = env->GetObjectField(peer, AwtObject::targetID);
 464     //Get graphicsConfig object ref from Component
 465     jobject compGC = env->GetObjectField(target,
 466                       AwtComponent::graphicsConfigID);
 467 
 468     //Set peer's graphicsConfig to Component's graphicsConfig
 469     if (compGC != NULL) {
 470         jclass win32GCCls = env->FindClass("sun/awt/Win32GraphicsConfig");
 471         DASSERT(win32GCCls != NULL);
 472         DASSERT(env->IsInstanceOf(compGC, win32GCCls));
 473         if (win32GCCls == NULL) {
 474             throw std::bad_alloc();
 475         }
 476         env->SetObjectField(peer, AwtComponent::peerGCID, compGC);
 477     }
 478 }
 479 
 480 void
 481 AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title,
 482                          DWORD windowStyle,
 483                          DWORD windowExStyle,
 484                          int x, int y, int w, int h,
 485                          HWND hWndParent, HMENU hMenu,
 486                          COLORREF colorForeground,
 487                          COLORREF colorBackground,
 488                          jobject peer)
 489 {
 490     if (env->EnsureLocalCapacity(2) < 0) {
 491         return;
 492     }
 493 
 494     /*
 495      * The window class of multifont label must be "BUTTON" because
 496      * "STATIC" class can't get WM_DRAWITEM message, and m_peerObject
 497      * member is referred in the GetClassName method of AwtLabel class.
 498      * So m_peerObject member must be set here.
 499      */
 500     if (m_peerObject == NULL) {
 501         m_peerObject = env->NewGlobalRef(peer);
 502     } else {
 503         assert(env->IsSameObject(m_peerObject, peer));
 504     }
 505 
 506     RegisterClass();
 507 
 508     jobject target = env->GetObjectField(peer, AwtObject::targetID);
 509     jboolean visible = env->GetBooleanField(target, AwtComponent::visibleID);
 510     m_visible = visible;
 511 
 512     if (visible) {
 513         windowStyle |= WS_VISIBLE;
 514     } else {
 515         windowStyle &= ~WS_VISIBLE;
 516     }
 517 
 518     InitPeerGraphicsConfig(env, peer);
 519 
 520     SetLastError(0);
 521     HWND hwnd = ::CreateWindowEx(windowExStyle,
 522                                  GetClassName(),
 523                                  title,
 524                                  windowStyle,
 525                                  x, y, w, h,
 526                                  hWndParent,
 527                                  hMenu,
 528                                  AwtToolkit::GetInstance().GetModuleHandle(),
 529                                  NULL);
 530 
 531     // fix for 5088782
 532     // check if CreateWindowsEx() returns not null value and if it does -
 533     //   create an InternalError or OutOfMemoryError based on GetLastError().
 534     //   This error is set to createError field of WObjectPeer and then
 535     //   checked and thrown in WComponentPeer constructor. We can't throw an
 536     //   error here because this code is invoked on Toolkit thread
 537     if (hwnd == NULL)
 538     {
 539         DWORD dw = ::GetLastError();
 540         jobject createError = NULL;
 541         if (dw == ERROR_OUTOFMEMORY)
 542         {
 543             jstring errorMsg = JNU_NewStringPlatform(env, L"too many window handles");
 544             if (errorMsg == NULL || env->ExceptionCheck()) {
 545                 env->ExceptionClear();
 546                 createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "()V");
 547             } else {
 548                 createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError",
 549                                                       "(Ljava/lang/String;)V",
 550                                                       errorMsg);
 551                 env->DeleteLocalRef(errorMsg);
 552             }
 553         }
 554         else
 555         {
 556             TCHAR *buf;
 557             FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
 558                 NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 559                 (LPTSTR)&buf, 0, NULL);
 560             jstring s = JNU_NewStringPlatform(env, buf);
 561             if (s == NULL || env->ExceptionCheck()) {
 562                 env->ExceptionClear();
 563                 createError = JNU_NewObjectByName(env, "java/lang/InternalError", "()V");
 564             } else {
 565                 createError = JNU_NewObjectByName(env, "java/lang/InternalError",
 566                                                                   "(Ljava/lang/String;)V", s);
 567                 env->DeleteLocalRef(s);
 568             }
 569             LocalFree(buf);
 570         }
 571         if (createError != NULL) {
 572             env->SetObjectField(peer, AwtObject::createErrorID, createError);
 573             env->DeleteLocalRef(createError);
 574         }
 575         env->DeleteLocalRef(target);
 576         return;
 577     }
 578 
 579     m_hwnd = hwnd;
 580 
 581     ::ImmAssociateContext(m_hwnd, NULL);
 582 
 583     SetDrawState((jint)JAWT_LOCK_SURFACE_CHANGED |
 584         (jint)JAWT_LOCK_BOUNDS_CHANGED |
 585         (jint)JAWT_LOCK_CLIP_CHANGED);
 586 
 587     LinkObjects(env, peer);
 588 
 589     /* Subclass the window now so that we can snoop on its messages */
 590     SubclassHWND();
 591 
 592     /*
 593       * Fix for 4046446.
 594       */
 595     SetWindowPos(GetHWnd(), 0, x, y, w, h, SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOACTIVATE);
 596 
 597     /* Set default colors. */
 598     m_colorForeground = colorForeground;
 599     m_colorBackground = colorBackground;
 600 
 601     /*
 602      * Only set background color if the color is actually set on the
 603      * target -- this avoids inheriting a parent's color unnecessarily,
 604      * and has to be done here because there isn't an API to get the
 605      * real background color from outside the AWT package.
 606      */
 607     jobject bkgrd = env->GetObjectField(target, AwtComponent::backgroundID) ;
 608     if (bkgrd != NULL) {
 609         JNU_CallMethodByName(env, NULL, peer, "setBackground",
 610                              "(Ljava/awt/Color;)V", bkgrd);
 611         DASSERT(!safe_ExceptionOccurred(env));
 612     }
 613     env->DeleteLocalRef(target);
 614     env->DeleteLocalRef(bkgrd);
 615 }
 616 
 617 /*
 618  * Destroy this window's HWND
 619  */
 620 void AwtComponent::DestroyHWnd() {
 621     if (m_hwnd != NULL) {
 622         AwtToolkit::DestroyComponentHWND(m_hwnd);
 623         //AwtToolkit::DestroyComponent(this);
 624         m_hwnd = NULL;
 625     }
 626 }
 627 
 628 /*
 629  * Returns hwnd for target on non Toolkit thread
 630  */
 631 HWND
 632 AwtComponent::GetHWnd(JNIEnv* env, jobject target) {
 633     if (JNU_IsNull(env, target)) {
 634         return 0;
 635     }
 636     jobject peer = env->GetObjectField(target, AwtComponent::peerID);
 637     if (JNU_IsNull(env, peer)) {
 638         return 0;
 639     }
 640     HWND hwnd = reinterpret_cast<HWND>(static_cast<LONG_PTR> (
 641         env->GetLongField(peer, AwtComponent::hwndID)));
 642     env->DeleteLocalRef(peer);
 643     return hwnd;
 644 }
 645 //
 646 // Propagate the background color to synchronize Java field and peer's field.
 647 // This is needed to fix 4148334
 648 //
 649 void AwtComponent::UpdateBackground(JNIEnv *env, jobject target)
 650 {
 651     if (env->EnsureLocalCapacity(1) < 0) {
 652         return;
 653     }
 654 
 655     jobject bkgrnd = env->GetObjectField(target, AwtComponent::backgroundID);
 656 
 657     if (bkgrnd == NULL) {
 658         bkgrnd = JNU_NewObjectByName(env, "java/awt/Color", "(III)V",
 659                                      GetRValue(m_colorBackground),
 660                                      GetGValue(m_colorBackground),
 661                                      GetBValue(m_colorBackground));
 662         if (bkgrnd != NULL) {
 663             env->SetObjectField(target, AwtComponent::backgroundID, bkgrnd);
 664         }
 665     }
 666     env->DeleteLocalRef(bkgrnd);
 667 }
 668 
 669 /*
 670  * Install our window proc as the proc for our HWND, and save off the
 671  * previous proc as the default
 672  */
 673 void AwtComponent::SubclassHWND()
 674 {
 675     if (m_bSubclassed) {
 676         return;
 677     }
 678     const WNDPROC wndproc = WndProc; // let compiler type check WndProc
 679     m_DefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(GetHWnd(), wndproc);
 680     m_bSubclassed = TRUE;
 681 }
 682 
 683 /*
 684  * Reinstall the original window proc as the proc for our HWND
 685  */
 686 void AwtComponent::UnsubclassHWND()
 687 {
 688     if (!m_bSubclassed) {
 689         return;
 690     }
 691     ComCtl32Util::GetInstance().UnsubclassHWND(GetHWnd(), WndProc, m_DefWindowProc);
 692     m_bSubclassed = FALSE;
 693 }
 694 
 695 /////////////////////////////////////
 696 // (static method)
 697 // Determines the top-level ancestor for a given window. If the given
 698 // window is a top-level window, return itself.
 699 //
 700 // 'Top-level' includes dialogs as well.
 701 //
 702 HWND AwtComponent::GetTopLevelParentForWindow(HWND hwndDescendant) {
 703     if (hwndDescendant == NULL) {
 704         return NULL;
 705     }
 706 
 707     DASSERT(IsWindow(hwndDescendant));
 708     HWND hwnd = hwndDescendant;
 709     for(;;) {
 710         DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
 711         // a) found a non-child window so terminate
 712         // b) found real toplevel window (e.g. EmbeddedFrame
 713         //    that is child though)
 714         if ( (style & WS_CHILD) == 0 ||
 715              AwtComponent::IsTopLevelHWnd(hwnd) )
 716         {
 717             break;
 718         }
 719         hwnd = ::GetParent(hwnd);
 720     }
 721 
 722     return hwnd;
 723 }
 724 ////////////////////
 725 
 726 jobject AwtComponent::FindHeavyweightUnderCursor(BOOL useCache) {
 727     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 728     if (env->EnsureLocalCapacity(1) < 0) {
 729         return NULL;
 730     }
 731 
 732     HWND hit = NULL;
 733     POINT p = { 0, 0 };
 734     AwtComponent *comp = NULL;
 735 
 736     if (useCache) {
 737         if (sm_cursorOn == NULL) {
 738             return NULL;
 739         }
 740 
 741 
 742         DASSERT(::IsWindow(sm_cursorOn));
 743         VERIFY(::GetCursorPos(&p));
 744         /*
 745          * Fix for BugTraq ID 4304024.
 746          * Allow a non-default cursor only for the client area.
 747          */
 748         comp = AwtComponent::GetComponent(sm_cursorOn);
 749         if (comp != NULL &&
 750             ::SendMessage(sm_cursorOn, WM_NCHITTEST, 0,
 751                           MAKELPARAM(p.x, p.y)) == HTCLIENT) {
 752             goto found;
 753         }
 754     }
 755 
 756     ::GetCursorPos(&p);
 757     hit = ::WindowFromPoint(p);
 758     while (hit != NULL) {
 759         comp = AwtComponent::GetComponent(hit);
 760 
 761         if (comp != NULL) {
 762             INT nHittest = (INT)::SendMessage(hit, WM_NCHITTEST,
 763                                           0, MAKELPARAM(p.x, p.y));
 764             /*
 765              * Fix for BugTraq ID 4304024.
 766              * Allow a non-default cursor only for the client area.
 767              */
 768             if (nHittest != HTCLIENT) {
 769                 /*
 770                  * When over the non-client area, send WM_SETCURSOR
 771                  * to revert the cursor to an arrow.
 772                  */
 773                 ::SendMessage(hit, WM_SETCURSOR, (WPARAM)hit,
 774                               MAKELPARAM(nHittest, WM_MOUSEMOVE));
 775                 return NULL;
 776             } else {
 777               sm_cursorOn = hit;
 778               goto found;
 779             }
 780         }
 781 
 782         if ((::GetWindowLong(hit, GWL_STYLE) & WS_CHILD) == 0) {
 783             return NULL;
 784         }
 785         hit = ::GetParent(hit);
 786     }
 787 
 788     return NULL;
 789 
 790 found:
 791     jobject localRef = comp->GetTarget(env);
 792     jobject globalRef = env->NewGlobalRef(localRef);
 793     env->DeleteLocalRef(localRef);
 794     return globalRef;
 795 }
 796 
 797 void AwtComponent::SetColor(COLORREF c)
 798 {
 799     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
 800     int grayscale = AwtWin32GraphicsDevice::GetGrayness(screen);
 801     if (grayscale != GS_NOTGRAY) {
 802         int g;
 803 
 804         g = (int) (.299 * (c & 0xFF) + .587 * ((c >> 8) & 0xFF) +
 805             .114 * ((c >> 16) & 0xFF) + 0.5);
 806         // c = g | (g << 8) | (g << 16);
 807         c = PALETTERGB(g, g, g);
 808     }
 809 
 810     if (m_colorForeground == c) {
 811         return;
 812     }
 813 
 814     m_colorForeground = c;
 815     if (m_penForeground != NULL) {
 816         m_penForeground->Release();
 817         m_penForeground = NULL;
 818     }
 819     VERIFY(::InvalidateRect(GetHWnd(), NULL, FALSE));
 820 }
 821 
 822 void AwtComponent::SetBackgroundColor(COLORREF c)
 823 {
 824     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
 825     int grayscale = AwtWin32GraphicsDevice::GetGrayness(screen);
 826     if (grayscale != GS_NOTGRAY) {
 827         int g;
 828 
 829         g = (int) (.299 * (c & 0xFF) + .587 * ((c >> 8) & 0xFF) +
 830             .114 * ((c >> 16) & 0xFF) + 0.5);
 831         // c = g | (g << 8) | (g << 16);
 832         c = PALETTERGB(g, g, g);
 833     }
 834 
 835     if (m_colorBackground == c) {
 836         return;
 837     }
 838     m_colorBackground = c;
 839     m_backgroundColorSet = TRUE;
 840     if (m_brushBackground != NULL) {
 841         m_brushBackground->Release();
 842         m_brushBackground = NULL;
 843     }
 844     VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE));
 845 }
 846 
 847 HPEN AwtComponent::GetForegroundPen()
 848 {
 849     if (m_penForeground == NULL) {
 850         m_penForeground = AwtPen::Get(m_colorForeground);
 851     }
 852     return (HPEN)m_penForeground->GetHandle();
 853 }
 854 
 855 COLORREF AwtComponent::GetBackgroundColor()
 856 {
 857     if (m_backgroundColorSet == FALSE) {
 858         AwtComponent* c = this;
 859         while ((c = c->GetParent()) != NULL) {
 860             if (c->IsBackgroundColorSet()) {
 861                 return c->GetBackgroundColor();
 862             }
 863         }
 864     }
 865     return m_colorBackground;
 866 }
 867 
 868 HBRUSH AwtComponent::GetBackgroundBrush()
 869 {
 870     if (m_backgroundColorSet == FALSE) {
 871         if (m_brushBackground != NULL) {
 872             m_brushBackground->Release();
 873             m_brushBackground = NULL;
 874         }
 875           AwtComponent* c = this;
 876           while ((c = c->GetParent()) != NULL) {
 877               if (c->IsBackgroundColorSet()) {
 878                   m_brushBackground =
 879                       AwtBrush::Get(c->GetBackgroundColor());
 880                   break;
 881               }
 882           }
 883     }
 884     if (m_brushBackground == NULL) {
 885         m_brushBackground = AwtBrush::Get(m_colorBackground);
 886     }
 887     return (HBRUSH)m_brushBackground->GetHandle();
 888 }
 889 
 890 void AwtComponent::SetFont(AwtFont* font)
 891 {
 892     DASSERT(font != NULL);
 893     if (font->GetAscent() < 0) {
 894         AwtFont::SetupAscent(font);
 895     }
 896     SendMessage(WM_SETFONT, (WPARAM)font->GetHFont(), MAKELPARAM(FALSE, 0));
 897     VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE));
 898 }
 899 
 900 AwtComponent* AwtComponent::GetParent()
 901 {
 902     HWND hwnd = ::GetParent(GetHWnd());
 903     if (hwnd == NULL) {
 904         return NULL;
 905     }
 906     return GetComponent(hwnd);
 907 }
 908 
 909 AwtWindow* AwtComponent::GetContainer()
 910 {
 911     AwtComponent* comp = this;
 912     while (comp != NULL) {
 913         if (comp->IsContainer()) {
 914             return (AwtWindow*)comp;
 915         }
 916         comp = comp->GetParent();
 917     }
 918     return NULL;
 919 }
 920 
 921 void AwtComponent::Show()
 922 {
 923     m_visible = true;
 924     ::ShowWindow(GetHWnd(), SW_SHOWNA);
 925 }
 926 
 927 void AwtComponent::Hide()
 928 {
 929     m_visible = false;
 930     ::ShowWindow(GetHWnd(), SW_HIDE);
 931 }
 932 
 933 BOOL
 934 AwtComponent::SetWindowPos(HWND wnd, HWND after,
 935                            int x, int y, int w, int h, UINT flags)
 936 {
 937     // Conditions we shouldn't handle:
 938     // z-order changes, correct window dimensions
 939     if (after != NULL || (w < 32767 && h < 32767)
 940         || ((::GetWindowLong(wnd, GWL_STYLE) & WS_CHILD) == 0))
 941     {
 942         return ::SetWindowPos(wnd, after, x, y, w, h, flags);
 943     }
 944     WINDOWPLACEMENT wp;
 945     ::ZeroMemory(&wp, sizeof(wp));
 946 
 947     wp.length = sizeof(wp);
 948     ::GetWindowPlacement(wnd, &wp);
 949     wp.rcNormalPosition.left = x;
 950     wp.rcNormalPosition.top = y;
 951     wp.rcNormalPosition.right = x + w;
 952     wp.rcNormalPosition.bottom = y + h;
 953     if ( flags & SWP_NOACTIVATE ) {
 954         wp.showCmd = SW_SHOWNOACTIVATE;
 955     }
 956     ::SetWindowPlacement(wnd, &wp);
 957     return 1;
 958 }
 959 
 960 
 961 void AwtComponent::Reshape(int x, int y, int w, int h)
 962 {
 963 #if defined(DEBUG)
 964     RECT        rc;
 965     ::GetWindowRect(GetHWnd(), &rc);
 966     ::MapWindowPoints(HWND_DESKTOP, ::GetParent(GetHWnd()), (LPPOINT)&rc, 2);
 967     DTRACE_PRINTLN4("AwtComponent::Reshape from %d, %d, %d, %d", rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
 968 #endif
 969 
 970     x = ScaleUpX(x);
 971     y = ScaleUpY(y);
 972     w = ScaleUpX(w);
 973     h = ScaleUpY(h);
 974 
 975     AwtWindow* container = GetContainer();
 976     AwtComponent* parent = GetParent();
 977     if (container != NULL && container == parent) {
 978         container->SubtractInsetPoint(x, y);
 979     }
 980     DTRACE_PRINTLN4("AwtComponent::Reshape to %d, %d, %d, %d", x, y, w, h);
 981     UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
 982 
 983     RECT        r;
 984 
 985     ::GetWindowRect(GetHWnd(), &r);
 986     // if the component size is changing , don't copy window bits
 987     if (r.right - r.left != w || r.bottom - r.top != h) {
 988         flags |= SWP_NOCOPYBITS;
 989     }
 990 
 991     if (parent && _tcscmp(parent->GetClassName(), TEXT("SunAwtScrollPane")) == 0) {
 992         if (x > 0) {
 993             x = 0;
 994         }
 995         if (y > 0) {
 996             y = 0;
 997         }
 998     }
 999     if (m_hdwp != NULL) {
1000         m_hdwp = ::DeferWindowPos(m_hdwp, GetHWnd(), 0, x, y, w, h, flags);
1001         DASSERT(m_hdwp != NULL);
1002     } else {
1003         /*
1004          * Fox for 4046446
1005          * If window has dimensions above the short int limit, ::SetWindowPos doesn't work.
1006          * We should use SetWindowPlacement instead.
1007          */
1008         SetWindowPos(GetHWnd(), 0, x, y, w, h, flags);
1009     }
1010 }
1011 
1012 void AwtComponent::SetScrollValues(UINT bar, int min, int value, int max)
1013 {
1014     int minTmp, maxTmp;
1015 
1016     ::GetScrollRange(GetHWnd(), bar, &minTmp, &maxTmp);
1017     if (min == INT_MAX) {
1018         min = minTmp;
1019     }
1020     if (value == INT_MAX) {
1021         value = ::GetScrollPos(GetHWnd(), bar);
1022     }
1023     if (max == INT_MAX) {
1024         max = maxTmp;
1025     }
1026     if (min == max) {
1027         max++;
1028     }
1029     ::SetScrollRange(GetHWnd(), bar, min, max, FALSE);
1030     ::SetScrollPos(GetHWnd(), bar, value, TRUE);
1031 }
1032 
1033 /*
1034  * Save Global Reference of sun.awt.windows.WInputMethod object
1035  */
1036 void AwtComponent::SetInputMethod(jobject im, BOOL useNativeCompWindow)
1037 {
1038     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1039 
1040     if (m_InputMethod!=NULL)
1041         env->DeleteGlobalRef(m_InputMethod);
1042 
1043     if (im!=NULL){
1044         m_InputMethod = env->NewGlobalRef(im);
1045         m_useNativeCompWindow = useNativeCompWindow;
1046     } else {
1047         m_InputMethod = NULL;
1048         m_useNativeCompWindow = TRUE;
1049     }
1050 
1051 }
1052 
1053 /*
1054  * Opportunity to process and/or eat a message before it is dispatched
1055  */
1056 MsgRouting AwtComponent::PreProcessMsg(MSG& msg)
1057 {
1058     return mrPassAlong;
1059 }
1060 
1061 static UINT lastMessage = WM_NULL;
1062 
1063 #ifndef SPY_MESSAGES
1064 #define SpyWinMessage(hwin,msg,str)
1065 #else
1066 
1067 #define FMT_MSG(x,y) case x: _stprintf(szBuf, \
1068     "0x%8.8x(%s):%s\n", hwnd, szComment, y); break;
1069 #define WIN_MSG(x) FMT_MSG(x,#x)
1070 
1071 void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment) {
1072 
1073     TCHAR szBuf[256];
1074 
1075     switch (message) {
1076         WIN_MSG(WM_NULL)
1077         WIN_MSG(WM_CREATE)
1078         WIN_MSG(WM_DESTROY)
1079         WIN_MSG(WM_MOVE)
1080         WIN_MSG(WM_SIZE)
1081         WIN_MSG(WM_ACTIVATE)
1082         WIN_MSG(WM_SETFOCUS)
1083         WIN_MSG(WM_KILLFOCUS)
1084         WIN_MSG(WM_ENABLE)
1085         WIN_MSG(WM_SETREDRAW)
1086         WIN_MSG(WM_SETTEXT)
1087         WIN_MSG(WM_GETTEXT)
1088         WIN_MSG(WM_GETTEXTLENGTH)
1089         WIN_MSG(WM_PAINT)
1090         WIN_MSG(WM_CLOSE)
1091         WIN_MSG(WM_QUERYENDSESSION)
1092         WIN_MSG(WM_QUIT)
1093         WIN_MSG(WM_QUERYOPEN)
1094         WIN_MSG(WM_ERASEBKGND)
1095         WIN_MSG(WM_SYSCOLORCHANGE)
1096         WIN_MSG(WM_ENDSESSION)
1097         WIN_MSG(WM_SHOWWINDOW)
1098         FMT_MSG(WM_WININICHANGE,"WM_WININICHANGE/WM_SETTINGCHANGE")
1099         WIN_MSG(WM_DEVMODECHANGE)
1100         WIN_MSG(WM_ACTIVATEAPP)
1101         WIN_MSG(WM_FONTCHANGE)
1102         WIN_MSG(WM_TIMECHANGE)
1103         WIN_MSG(WM_CANCELMODE)
1104         WIN_MSG(WM_SETCURSOR)
1105         WIN_MSG(WM_MOUSEACTIVATE)
1106         WIN_MSG(WM_CHILDACTIVATE)
1107         WIN_MSG(WM_QUEUESYNC)
1108         WIN_MSG(WM_GETMINMAXINFO)
1109         WIN_MSG(WM_PAINTICON)
1110         WIN_MSG(WM_ICONERASEBKGND)
1111         WIN_MSG(WM_NEXTDLGCTL)
1112         WIN_MSG(WM_SPOOLERSTATUS)
1113         WIN_MSG(WM_DRAWITEM)
1114         WIN_MSG(WM_MEASUREITEM)
1115         WIN_MSG(WM_DELETEITEM)
1116         WIN_MSG(WM_VKEYTOITEM)
1117         WIN_MSG(WM_CHARTOITEM)
1118         WIN_MSG(WM_SETFONT)
1119         WIN_MSG(WM_GETFONT)
1120         WIN_MSG(WM_SETHOTKEY)
1121         WIN_MSG(WM_GETHOTKEY)
1122         WIN_MSG(WM_QUERYDRAGICON)
1123         WIN_MSG(WM_COMPAREITEM)
1124         FMT_MSG(0x003D, "WM_GETOBJECT")
1125         WIN_MSG(WM_COMPACTING)
1126         WIN_MSG(WM_COMMNOTIFY)
1127         WIN_MSG(WM_WINDOWPOSCHANGING)
1128         WIN_MSG(WM_WINDOWPOSCHANGED)
1129         WIN_MSG(WM_POWER)
1130         WIN_MSG(WM_COPYDATA)
1131         WIN_MSG(WM_CANCELJOURNAL)
1132         WIN_MSG(WM_NOTIFY)
1133         WIN_MSG(WM_INPUTLANGCHANGEREQUEST)
1134         WIN_MSG(WM_INPUTLANGCHANGE)
1135         WIN_MSG(WM_TCARD)
1136         WIN_MSG(WM_HELP)
1137         WIN_MSG(WM_USERCHANGED)
1138         WIN_MSG(WM_NOTIFYFORMAT)
1139         WIN_MSG(WM_CONTEXTMENU)
1140         WIN_MSG(WM_STYLECHANGING)
1141         WIN_MSG(WM_STYLECHANGED)
1142         WIN_MSG(WM_DISPLAYCHANGE)
1143         WIN_MSG(WM_GETICON)
1144         WIN_MSG(WM_SETICON)
1145         WIN_MSG(WM_NCCREATE)
1146         WIN_MSG(WM_NCDESTROY)
1147         WIN_MSG(WM_NCCALCSIZE)
1148         WIN_MSG(WM_NCHITTEST)
1149         WIN_MSG(WM_NCPAINT)
1150         WIN_MSG(WM_NCACTIVATE)
1151         WIN_MSG(WM_GETDLGCODE)
1152         WIN_MSG(WM_SYNCPAINT)
1153         WIN_MSG(WM_NCMOUSEMOVE)
1154         WIN_MSG(WM_NCLBUTTONDOWN)
1155         WIN_MSG(WM_NCLBUTTONUP)
1156         WIN_MSG(WM_NCLBUTTONDBLCLK)
1157         WIN_MSG(WM_NCRBUTTONDOWN)
1158         WIN_MSG(WM_NCRBUTTONUP)
1159         WIN_MSG(WM_NCRBUTTONDBLCLK)
1160         WIN_MSG(WM_NCMBUTTONDOWN)
1161         WIN_MSG(WM_NCMBUTTONUP)
1162         WIN_MSG(WM_NCMBUTTONDBLCLK)
1163         WIN_MSG(WM_KEYDOWN)
1164         WIN_MSG(WM_KEYUP)
1165         WIN_MSG(WM_CHAR)
1166         WIN_MSG(WM_DEADCHAR)
1167         WIN_MSG(WM_SYSKEYDOWN)
1168         WIN_MSG(WM_SYSKEYUP)
1169         WIN_MSG(WM_SYSCHAR)
1170         WIN_MSG(WM_SYSDEADCHAR)
1171         WIN_MSG(WM_IME_STARTCOMPOSITION)
1172         WIN_MSG(WM_IME_ENDCOMPOSITION)
1173         WIN_MSG(WM_IME_COMPOSITION)
1174         WIN_MSG(WM_INITDIALOG)
1175         WIN_MSG(WM_COMMAND)
1176         WIN_MSG(WM_SYSCOMMAND)
1177         WIN_MSG(WM_TIMER)
1178         WIN_MSG(WM_HSCROLL)
1179         WIN_MSG(WM_VSCROLL)
1180         WIN_MSG(WM_INITMENU)
1181         WIN_MSG(WM_INITMENUPOPUP)
1182         WIN_MSG(WM_MENUSELECT)
1183         WIN_MSG(WM_MENUCHAR)
1184         WIN_MSG(WM_ENTERIDLE)
1185         FMT_MSG(0x0122, "WM_MENURBUTTONUP")
1186         FMT_MSG(0x0123, "WM_MENUDRAG")
1187         FMT_MSG(0x0124, "WM_MENUGETOBJECT")
1188         FMT_MSG(0x0125, "WM_UNINITMENUPOPUP")
1189         FMT_MSG(0x0126, "WM_MENUCOMMAND")
1190         WIN_MSG(WM_CTLCOLORMSGBOX)
1191         WIN_MSG(WM_CTLCOLOREDIT)
1192         WIN_MSG(WM_CTLCOLORLISTBOX)
1193         WIN_MSG(WM_CTLCOLORBTN)
1194         WIN_MSG(WM_CTLCOLORDLG)
1195         WIN_MSG(WM_CTLCOLORSCROLLBAR)
1196         WIN_MSG(WM_CTLCOLORSTATIC)
1197         WIN_MSG(WM_MOUSEMOVE)
1198         WIN_MSG(WM_LBUTTONDOWN)
1199         WIN_MSG(WM_LBUTTONUP)
1200         WIN_MSG(WM_LBUTTONDBLCLK)
1201         WIN_MSG(WM_RBUTTONDOWN)
1202         WIN_MSG(WM_RBUTTONUP)
1203         WIN_MSG(WM_RBUTTONDBLCLK)
1204         WIN_MSG(WM_MBUTTONDOWN)
1205         WIN_MSG(WM_MBUTTONUP)
1206         WIN_MSG(WM_MBUTTONDBLCLK)
1207         WIN_MSG(WM_XBUTTONDBLCLK)
1208         WIN_MSG(WM_XBUTTONDOWN)
1209         WIN_MSG(WM_XBUTTONUP)
1210         WIN_MSG(WM_MOUSEWHEEL)
1211         WIN_MSG(WM_PARENTNOTIFY)
1212         WIN_MSG(WM_ENTERMENULOOP)
1213         WIN_MSG(WM_EXITMENULOOP)
1214         WIN_MSG(WM_NEXTMENU)
1215         WIN_MSG(WM_SIZING)
1216         WIN_MSG(WM_CAPTURECHANGED)
1217         WIN_MSG(WM_MOVING)
1218         WIN_MSG(WM_POWERBROADCAST)
1219         WIN_MSG(WM_DEVICECHANGE)
1220         WIN_MSG(WM_MDICREATE)
1221         WIN_MSG(WM_MDIDESTROY)
1222         WIN_MSG(WM_MDIACTIVATE)
1223         WIN_MSG(WM_MDIRESTORE)
1224         WIN_MSG(WM_MDINEXT)
1225         WIN_MSG(WM_MDIMAXIMIZE)
1226         WIN_MSG(WM_MDITILE)
1227         WIN_MSG(WM_MDICASCADE)
1228         WIN_MSG(WM_MDIICONARRANGE)
1229         WIN_MSG(WM_MDIGETACTIVE)
1230         WIN_MSG(WM_MDISETMENU)
1231         WIN_MSG(WM_ENTERSIZEMOVE)
1232         WIN_MSG(WM_EXITSIZEMOVE)
1233         WIN_MSG(WM_DROPFILES)
1234         WIN_MSG(WM_MDIREFRESHMENU)
1235         WIN_MSG(WM_IME_SETCONTEXT)
1236         WIN_MSG(WM_IME_NOTIFY)
1237         WIN_MSG(WM_IME_CONTROL)
1238         WIN_MSG(WM_IME_COMPOSITIONFULL)
1239         WIN_MSG(WM_IME_SELECT)
1240         WIN_MSG(WM_IME_CHAR)
1241         FMT_MSG(WM_IME_REQUEST)
1242         WIN_MSG(WM_IME_KEYDOWN)
1243         WIN_MSG(WM_IME_KEYUP)
1244         FMT_MSG(0x02A1, "WM_MOUSEHOVER")
1245         FMT_MSG(0x02A3, "WM_MOUSELEAVE")
1246         WIN_MSG(WM_CUT)
1247         WIN_MSG(WM_COPY)
1248         WIN_MSG(WM_PASTE)
1249         WIN_MSG(WM_CLEAR)
1250         WIN_MSG(WM_UNDO)
1251         WIN_MSG(WM_RENDERFORMAT)
1252         WIN_MSG(WM_RENDERALLFORMATS)
1253         WIN_MSG(WM_DESTROYCLIPBOARD)
1254         WIN_MSG(WM_DRAWCLIPBOARD)
1255         WIN_MSG(WM_PAINTCLIPBOARD)
1256         WIN_MSG(WM_VSCROLLCLIPBOARD)
1257         WIN_MSG(WM_SIZECLIPBOARD)
1258         WIN_MSG(WM_ASKCBFORMATNAME)
1259         WIN_MSG(WM_CHANGECBCHAIN)
1260         WIN_MSG(WM_HSCROLLCLIPBOARD)
1261         WIN_MSG(WM_QUERYNEWPALETTE)
1262         WIN_MSG(WM_PALETTEISCHANGING)
1263         WIN_MSG(WM_PALETTECHANGED)
1264         WIN_MSG(WM_HOTKEY)
1265         WIN_MSG(WM_PRINT)
1266         WIN_MSG(WM_PRINTCLIENT)
1267         WIN_MSG(WM_HANDHELDFIRST)
1268         WIN_MSG(WM_HANDHELDLAST)
1269         WIN_MSG(WM_AFXFIRST)
1270         WIN_MSG(WM_AFXLAST)
1271         WIN_MSG(WM_PENWINFIRST)
1272         WIN_MSG(WM_PENWINLAST)
1273         WIN_MSG(WM_AWT_COMPONENT_CREATE)
1274         WIN_MSG(WM_AWT_DESTROY_WINDOW)
1275         WIN_MSG(WM_AWT_MOUSEENTER)
1276         WIN_MSG(WM_AWT_MOUSEEXIT)
1277         WIN_MSG(WM_AWT_COMPONENT_SHOW)
1278         WIN_MSG(WM_AWT_COMPONENT_HIDE)
1279         WIN_MSG(WM_AWT_COMPONENT_SETFOCUS)
1280         WIN_MSG(WM_AWT_WINDOW_SETACTIVE)
1281         WIN_MSG(WM_AWT_LIST_SETMULTISELECT)
1282         WIN_MSG(WM_AWT_HANDLE_EVENT)
1283         WIN_MSG(WM_AWT_PRINT_COMPONENT)
1284         WIN_MSG(WM_AWT_RESHAPE_COMPONENT)
1285         WIN_MSG(WM_AWT_SETALWAYSONTOP)
1286         WIN_MSG(WM_AWT_BEGIN_VALIDATE)
1287         WIN_MSG(WM_AWT_END_VALIDATE)
1288         WIN_MSG(WM_AWT_FORWARD_CHAR)
1289         WIN_MSG(WM_AWT_FORWARD_BYTE)
1290         WIN_MSG(WM_AWT_SET_SCROLL_INFO)
1291         WIN_MSG(WM_AWT_CREATECONTEXT)
1292         WIN_MSG(WM_AWT_DESTROYCONTEXT)
1293         WIN_MSG(WM_AWT_ASSOCIATECONTEXT)
1294         WIN_MSG(WM_AWT_GET_DEFAULT_IME_HANDLER)
1295         WIN_MSG(WM_AWT_HANDLE_NATIVE_IME_EVENT)
1296         WIN_MSG(WM_AWT_PRE_KEYDOWN)
1297         WIN_MSG(WM_AWT_PRE_KEYUP)
1298         WIN_MSG(WM_AWT_PRE_SYSKEYDOWN)
1299         WIN_MSG(WM_AWT_PRE_SYSKEYUP)
1300         WIN_MSG(WM_AWT_ENDCOMPOSITION,)
1301         WIN_MSG(WM_AWT_DISPOSE,)
1302         WIN_MSG(WM_AWT_DELETEOBJECT,)
1303         WIN_MSG(WM_AWT_SETCONVERSIONSTATUS,)
1304         WIN_MSG(WM_AWT_GETCONVERSIONSTATUS,)
1305         WIN_MSG(WM_AWT_SETOPENSTATUS,)
1306         WIN_MSG(WM_AWT_GETOPENSTATUS)
1307         WIN_MSG(WM_AWT_ACTIVATEKEYBOARDLAYOUT)
1308         WIN_MSG(WM_AWT_OPENCANDIDATEWINDOW)
1309         WIN_MSG(WM_AWT_DLG_SHOWMODAL,)
1310         WIN_MSG(WM_AWT_DLG_ENDMODAL,)
1311         WIN_MSG(WM_AWT_SETCURSOR,)
1312         WIN_MSG(WM_AWT_WAIT_FOR_SINGLE_OBJECT,)
1313         WIN_MSG(WM_AWT_INVOKE_METHOD,)
1314         WIN_MSG(WM_AWT_INVOKE_VOID_METHOD,)
1315         WIN_MSG(WM_AWT_EXECUTE_SYNC,)
1316         WIN_MSG(WM_AWT_CURSOR_SYNC)
1317         WIN_MSG(WM_AWT_GETDC)
1318         WIN_MSG(WM_AWT_RELEASEDC)
1319         WIN_MSG(WM_AWT_RELEASE_ALL_DCS)
1320         WIN_MSG(WM_AWT_SHOWCURSOR)
1321         WIN_MSG(WM_AWT_HIDECURSOR)
1322         WIN_MSG(WM_AWT_CREATE_PRINTED_PIXELS)
1323         WIN_MSG(WM_AWT_OBJECTLISTCLEANUP)
1324         default:
1325             sprintf(szBuf, "0x%8.8x(%s):Unknown message 0x%8.8x\n",
1326                 hwnd, szComment, message);
1327             break;
1328     }
1329     printf(szBuf);
1330 }
1331 
1332 #endif /* SPY_MESSAGES */
1333 
1334 /*
1335  * Dispatch messages for this window class--general component
1336  */
1337 LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
1338 {
1339     CounterHelper ch(&m_MessagesProcessing);
1340 
1341     JNILocalFrame lframe(AwtToolkit::GetEnv(), 10);
1342     SpyWinMessage(GetHWnd(), message,
1343         (message == WM_AWT_RELEASE_ALL_DCS) ? TEXT("Disposed Component") : GetClassName());
1344 
1345     LRESULT retValue = 0;
1346     MsgRouting mr = mrDoDefault;
1347     AwtToolkit::GetInstance().eventNumber++;
1348 
1349     static BOOL ignoreNextLBTNUP = FALSE; //Ignore next LBUTTONUP msg?
1350 
1351     lastMessage = message;
1352 
1353     if (message == WmAwtIsComponent) {
1354     // special message to identify AWT HWND's without using
1355     // resource hogging ::SetProp
1356         return (LRESULT)TRUE;
1357     }
1358 
1359     DWORD curPos = 0;
1360 
1361     UINT switchMessage = message;
1362     switch (switchMessage) {
1363       case WM_AWT_GETDC:
1364       {
1365             HDC hDC;
1366             // First, release the DCs scheduled for deletion
1367             ReleaseDCList(GetHWnd(), passiveDCList);
1368 
1369             GetDCReturnStruct *returnStruct = new GetDCReturnStruct;
1370             returnStruct->gdiLimitReached = FALSE;
1371             if (AwtGDIObject::IncrementIfAvailable()) {
1372                 hDC = ::GetDCEx(GetHWnd(), NULL,
1373                                 DCX_CACHE | DCX_CLIPCHILDREN |
1374                                 DCX_CLIPSIBLINGS);
1375                 if (hDC != NULL) {
1376                     // Add new DC to list of DC's associated with this Component
1377                     activeDCList.AddDC(hDC, GetHWnd());
1378                 } else {
1379                     // Creation failed; decrement counter in AwtGDIObject
1380                     AwtGDIObject::Decrement();
1381                 }
1382             } else {
1383                 hDC = NULL;
1384                 returnStruct->gdiLimitReached = TRUE;
1385             }
1386             returnStruct->hDC = hDC;
1387             retValue = (LRESULT)returnStruct;
1388             mr = mrConsume;
1389             break;
1390       }
1391       case WM_AWT_RELEASEDC:
1392       {
1393             HDC hDC = (HDC)wParam;
1394             MoveDCToPassiveList(hDC, GetHWnd());
1395             ReleaseDCList(GetHWnd(), passiveDCList);
1396             mr = mrConsume;
1397             break;
1398       }
1399       case WM_AWT_RELEASE_ALL_DCS:
1400       {
1401             // Called during Component destruction.  Gets current list of
1402             // DC's associated with Component and releases each DC.
1403             ReleaseDCList(GetHWnd(), activeDCList);
1404             ReleaseDCList(GetHWnd(), passiveDCList);
1405             mr = mrConsume;
1406             break;
1407       }
1408       case WM_AWT_SHOWCURSOR:
1409           ::ShowCursor(TRUE);
1410           break;
1411       case WM_AWT_HIDECURSOR:
1412           ::ShowCursor(FALSE);
1413           break;
1414       case WM_CREATE: mr = WmCreate(); break;
1415       case WM_CLOSE:      mr = WmClose(); break;
1416       case WM_DESTROY:    mr = WmDestroy(); break;
1417       case WM_NCDESTROY:  mr = WmNcDestroy(); break;
1418 
1419       case WM_ERASEBKGND:
1420           mr = WmEraseBkgnd((HDC)wParam, *(BOOL*)&retValue); break;
1421       case WM_PAINT:
1422           CheckFontSmoothingSettings(GetHWnd());
1423           /* Set draw state */
1424           SetDrawState(GetDrawState() | JAWT_LOCK_CLIP_CHANGED);
1425           mr = WmPaint((HDC)wParam);
1426           break;
1427 
1428       case WM_GETMINMAXINFO:
1429           mr = WmGetMinMaxInfo((LPMINMAXINFO)lParam);
1430           break;
1431 
1432       case WM_WINDOWPOSCHANGING:
1433       {
1434           // We process this message so that we can synchronize access to
1435           // a moving window.  The Scale/Blt functions in Win32BlitLoops
1436           // take the same windowMoveLock to ensure that a window is not
1437           // moving while we are trying to copy pixels into it.
1438           WINDOWPOS *lpPosInfo = (WINDOWPOS *)lParam;
1439           if ((lpPosInfo->flags & (SWP_NOMOVE | SWP_NOSIZE)) !=
1440               (SWP_NOMOVE | SWP_NOSIZE))
1441           {
1442               // Move or Size command.
1443               // Windows tends to send erroneous events that the window
1444               // is about to move when the coordinates are exactly the
1445               // same as the last time.  This can cause problems with
1446               // our windowMoveLock CriticalSection because we enter it
1447               // here and never get to WM_WINDOWPOSCHANGED to release it.
1448               // So make sure this is a real move/size event before bothering
1449               // to grab the critical section.
1450               BOOL takeLock = FALSE;
1451               if (!(lpPosInfo->flags & SWP_NOMOVE) &&
1452                   ((windowMoveLockPosX != lpPosInfo->x) ||
1453                    (windowMoveLockPosY != lpPosInfo->y)))
1454               {
1455                   // Real move event
1456                   takeLock = TRUE;
1457                   windowMoveLockPosX = lpPosInfo->x;
1458                   windowMoveLockPosY = lpPosInfo->y;
1459               }
1460               if (!(lpPosInfo->flags & SWP_NOSIZE) &&
1461                   ((windowMoveLockPosCX != lpPosInfo->cx) ||
1462                    (windowMoveLockPosCY != lpPosInfo->cy)))
1463               {
1464                   // Real size event
1465                   takeLock = TRUE;
1466                   windowMoveLockPosCX = lpPosInfo->cx;
1467                   windowMoveLockPosCY = lpPosInfo->cy;
1468               }
1469               if (takeLock) {
1470                   if (!windowMoveLockHeld) {
1471                       windowMoveLock.Enter();
1472                       windowMoveLockHeld = TRUE;
1473                   }
1474               }
1475           }
1476           mr = WmWindowPosChanging(lParam);
1477           break;
1478       }
1479       case WM_WINDOWPOSCHANGED:
1480       {
1481           // Release lock grabbed in the POSCHANGING message
1482           if (windowMoveLockHeld) {
1483               windowMoveLockHeld = FALSE;
1484               windowMoveLock.Leave();
1485           }
1486           mr = WmWindowPosChanged(lParam);
1487           break;
1488       }
1489       case WM_MOVE: {
1490           RECT r;
1491           ::GetWindowRect(GetHWnd(), &r);
1492           mr = WmMove(r.left, r.top);
1493           break;
1494       }
1495       case WM_SIZE:
1496       {
1497           RECT r;
1498           // fix 4128317 : use GetClientRect for full 32-bit int precision and
1499           // to avoid negative client area dimensions overflowing 16-bit params - robi
1500           ::GetClientRect( GetHWnd(), &r );
1501           mr = WmSize(static_cast<UINT>(wParam), r.right - r.left, r.bottom - r.top);
1502           //mr = WmSize(wParam, LOWORD(lParam), HIWORD(lParam));
1503           SetCompositionWindow(r);
1504           break;
1505       }
1506       case WM_SIZING:
1507           mr = WmSizing();
1508           break;
1509       case WM_SHOWWINDOW:
1510           mr = WmShowWindow(static_cast<BOOL>(wParam),
1511                             static_cast<UINT>(lParam)); break;
1512       case WM_SYSCOMMAND:
1513           mr = WmSysCommand(static_cast<UINT>(wParam & 0xFFF0),
1514                             GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1515           break;
1516       case WM_EXITSIZEMOVE:
1517           mr = WmExitSizeMove();
1518           break;
1519       // Bug #4039858 (Selecting menu item causes bogus mouse click event)
1520       case WM_ENTERMENULOOP:
1521           mr = WmEnterMenuLoop((BOOL)wParam);
1522           sm_bMenuLoop = TRUE;
1523           // we need to release grab if menu is shown
1524           if (AwtWindow::GetGrabbedWindow() != NULL) {
1525               AwtWindow::GetGrabbedWindow()->Ungrab();
1526           }
1527           break;
1528       case WM_EXITMENULOOP:
1529           mr = WmExitMenuLoop((BOOL)wParam);
1530           sm_bMenuLoop = FALSE;
1531           break;
1532 
1533       // We don't expect any focus messages on non-proxy component,
1534       // except those that came from Java.
1535       case WM_SETFOCUS:
1536           if (sm_inSynthesizeFocus) {
1537               mr = WmSetFocus((HWND)wParam);
1538           } else {
1539               mr = mrConsume;
1540           }
1541           break;
1542       case WM_KILLFOCUS:
1543           if (sm_inSynthesizeFocus) {
1544               mr = WmKillFocus((HWND)wParam);
1545           } else {
1546               mr = mrConsume;
1547           }
1548           break;
1549       case WM_ACTIVATE: {
1550           UINT nState = LOWORD(wParam);
1551           BOOL fMinimized = (BOOL)HIWORD(wParam);
1552           mr = mrConsume;
1553 
1554           if (!sm_suppressFocusAndActivation &&
1555               (!fMinimized || (nState == WA_INACTIVE)))
1556           {
1557               mr = WmActivate(nState, fMinimized, (HWND)lParam);
1558 
1559               // When the window is deactivated, send WM_IME_ENDCOMPOSITION
1560               // message to deactivate the composition window so that
1561               // it won't receive keyboard input focus.
1562               HIMC hIMC;
1563               HWND hwnd = ImmGetHWnd();
1564               if ((hIMC = ImmGetContext(hwnd)) != NULL) {
1565                   ImmReleaseContext(hwnd, hIMC);
1566                   DefWindowProc(WM_IME_ENDCOMPOSITION, 0, 0);
1567               }
1568           }
1569           break;
1570       }
1571       case WM_MOUSEACTIVATE: {
1572           AwtWindow *window = GetContainer();
1573           if (window && window->IsFocusableWindow()) {
1574               // AWT/Swing will later request focus to a proper component
1575               // on handling the Java mouse event. Anyway, we have to
1576               // activate the window here as it works both for AWT & Swing.
1577               // Do it in our own fassion,
1578               window->AwtSetActiveWindow(TRUE, LOWORD(lParam)/*hittest*/);
1579           }
1580           mr = mrConsume;
1581           retValue = MA_NOACTIVATE;
1582           break;
1583       }
1584       case WM_CTLCOLORMSGBOX:
1585       case WM_CTLCOLOREDIT:
1586       case WM_CTLCOLORLISTBOX:
1587       case WM_CTLCOLORBTN:
1588       case WM_CTLCOLORDLG:
1589       case WM_CTLCOLORSCROLLBAR:
1590       case WM_CTLCOLORSTATIC:
1591           mr = WmCtlColor((HDC)wParam, (HWND)lParam,
1592                           message-WM_CTLCOLORMSGBOX+CTLCOLOR_MSGBOX,
1593                           *(HBRUSH*)&retValue);
1594           break;
1595       case WM_HSCROLL:
1596           mr = WmHScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
1597           break;
1598       case WM_VSCROLL:
1599           mr = WmVScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
1600           break;
1601       // 4664415: We're seeing a WM_LBUTTONUP when the user releases the
1602       // mouse button after a WM_NCLBUTTONDBLCLK.  We want to ignore this
1603       // WM_LBUTTONUP, so we set a flag in WM_NCLBUTTONDBLCLK and look for the
1604       // flag on a WM_LBUTTONUP.  -bchristi
1605       case WM_NCLBUTTONDBLCLK:
1606           mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON | DBL_CLICK);
1607           if (mr == mrDoDefault) {
1608               ignoreNextLBTNUP = TRUE;
1609           }
1610           break;
1611       case WM_NCLBUTTONDOWN:
1612           mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON);
1613           ignoreNextLBTNUP = FALSE;
1614           break;
1615       case WM_NCLBUTTONUP:
1616           mr = WmNcMouseUp(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON);
1617           break;
1618       case WM_NCRBUTTONDOWN:
1619            mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RIGHT_BUTTON);
1620            break;
1621       case WM_LBUTTONUP:
1622           if (ignoreNextLBTNUP) {
1623               ignoreNextLBTNUP = FALSE;
1624               return mrDoDefault;
1625           }
1626           //fall-through
1627       case WM_LBUTTONDOWN:
1628           ignoreNextLBTNUP = FALSE;
1629           //fall-through
1630       case WM_LBUTTONDBLCLK:
1631       case WM_RBUTTONDOWN:
1632       case WM_RBUTTONDBLCLK:
1633       case WM_RBUTTONUP:
1634       case WM_MBUTTONDOWN:
1635       case WM_MBUTTONDBLCLK:
1636       case WM_MBUTTONUP:
1637       case WM_XBUTTONDBLCLK:
1638       case WM_XBUTTONDOWN:
1639       case WM_XBUTTONUP:
1640       case WM_MOUSEMOVE:
1641       case WM_MOUSEWHEEL:
1642       case WM_AWT_MOUSEENTER:
1643       case WM_AWT_MOUSEEXIT:
1644           curPos = ::GetMessagePos();
1645           POINT myPos;
1646           myPos.x = GET_X_LPARAM(curPos);
1647           myPos.y = GET_Y_LPARAM(curPos);
1648           ::ScreenToClient(GetHWnd(), &myPos);
1649           switch(switchMessage) {
1650           case WM_AWT_MOUSEENTER:
1651               mr = WmMouseEnter(static_cast<UINT>(wParam), myPos.x, myPos.y);
1652               break;
1653           case WM_LBUTTONDOWN:
1654           case WM_LBUTTONDBLCLK:
1655               mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1656                                LEFT_BUTTON);
1657               break;
1658           case WM_LBUTTONUP:
1659               mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1660                              LEFT_BUTTON);
1661               break;
1662           case WM_MOUSEMOVE:
1663               mr = WmMouseMove(static_cast<UINT>(wParam), myPos.x, myPos.y);
1664               break;
1665           case WM_MBUTTONDOWN:
1666           case WM_MBUTTONDBLCLK:
1667               mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1668                                MIDDLE_BUTTON);
1669               break;
1670           case WM_XBUTTONDOWN:
1671           case WM_XBUTTONDBLCLK:
1672               if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) {
1673                   if (HIWORD(wParam) == 1) {
1674                       mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1675                                        X1_BUTTON);
1676                   }
1677                   if (HIWORD(wParam) == 2) {
1678                       mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1679                                        X2_BUTTON);
1680                   }
1681               }
1682               break;
1683           case WM_XBUTTONUP:
1684               if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) {
1685                   if (HIWORD(wParam) == 1) {
1686                       mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1687                                      X1_BUTTON);
1688                   }
1689                   if (HIWORD(wParam) == 2) {
1690                       mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1691                                      X2_BUTTON);
1692                   }
1693               }
1694               break;
1695           case WM_RBUTTONDOWN:
1696           case WM_RBUTTONDBLCLK:
1697               mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1698                                RIGHT_BUTTON);
1699               break;
1700           case WM_RBUTTONUP:
1701               mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1702                              RIGHT_BUTTON);
1703               break;
1704           case WM_MBUTTONUP:
1705               mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1706                              MIDDLE_BUTTON);
1707               break;
1708           case WM_AWT_MOUSEEXIT:
1709               mr = WmMouseExit(static_cast<UINT>(wParam), myPos.x, myPos.y);
1710               break;
1711           case  WM_MOUSEWHEEL:
1712               mr = WmMouseWheel(GET_KEYSTATE_WPARAM(wParam),
1713                                 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
1714                                 GET_WHEEL_DELTA_WPARAM(wParam));
1715               break;
1716           }
1717           break;
1718       case WM_SETCURSOR:
1719           mr = mrDoDefault;
1720           if (LOWORD(lParam) == HTCLIENT) {
1721               if (AwtComponent* comp =
1722                                     AwtComponent::GetComponent((HWND)wParam)) {
1723                   AwtCursor::UpdateCursor(comp);
1724                   mr = mrConsume;
1725               }
1726           }
1727           break;
1728 
1729       case WM_KEYDOWN:
1730           mr = WmKeyDown(static_cast<UINT>(wParam),
1731                          LOWORD(lParam), HIWORD(lParam), FALSE);
1732           break;
1733       case WM_KEYUP:
1734           mr = WmKeyUp(static_cast<UINT>(wParam),
1735                        LOWORD(lParam), HIWORD(lParam), FALSE);
1736           break;
1737       case WM_SYSKEYDOWN:
1738           mr = WmKeyDown(static_cast<UINT>(wParam),
1739                          LOWORD(lParam), HIWORD(lParam), TRUE);
1740           break;
1741       case WM_SYSKEYUP:
1742           mr = WmKeyUp(static_cast<UINT>(wParam),
1743                        LOWORD(lParam), HIWORD(lParam), TRUE);
1744           break;
1745       case WM_IME_SETCONTEXT:
1746           // lParam is passed as pointer and it can be modified.
1747           mr = WmImeSetContext(static_cast<BOOL>(wParam), &lParam);
1748           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1749           break;
1750       case WM_IME_NOTIFY:
1751           mr = WmImeNotify(wParam, lParam);
1752           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1753           break;
1754       case WM_IME_STARTCOMPOSITION:
1755           mr = WmImeStartComposition();
1756           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1757           break;
1758       case WM_IME_ENDCOMPOSITION:
1759           mr = WmImeEndComposition();
1760           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1761           break;
1762       case WM_IME_COMPOSITION: {
1763           WORD dbcschar = static_cast<WORD>(wParam);
1764           mr = WmImeComposition(dbcschar, lParam);
1765           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1766           break;
1767       }
1768       case WM_IME_CONTROL:
1769       case WM_IME_COMPOSITIONFULL:
1770       case WM_IME_SELECT:
1771       case WM_IME_KEYUP:
1772       case WM_IME_KEYDOWN:
1773       case WM_IME_REQUEST:
1774           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1775           break;
1776       case WM_CHAR:
1777           mr = WmChar(static_cast<UINT>(wParam),
1778                       LOWORD(lParam), HIWORD(lParam), FALSE);
1779           break;
1780       case WM_SYSCHAR:
1781           mr = WmChar(static_cast<UINT>(wParam),
1782                       LOWORD(lParam), HIWORD(lParam), TRUE);
1783           break;
1784       case WM_IME_CHAR:
1785           mr = WmIMEChar(static_cast<UINT>(wParam),
1786                          LOWORD(lParam), HIWORD(lParam), FALSE);
1787           break;
1788 
1789       case WM_INPUTLANGCHANGEREQUEST: {
1790           DTRACE_PRINTLN4("WM_INPUTLANGCHANGEREQUEST: hwnd = 0x%X (%s);"//
1791                           "0x%08X -> 0x%08X",
1792                           GetHWnd(), GetClassName(),
1793                           (UINT_PTR)GetKeyboardLayout(), (UINT_PTR)lParam);
1794           // 4267428: make sure keyboard layout is turned undead.
1795           static BYTE keyboardState[AwtToolkit::KB_STATE_SIZE];
1796           AwtToolkit::GetKeyboardState(keyboardState);
1797           WORD ignored;
1798           ::ToAsciiEx(VK_SPACE, ::MapVirtualKey(VK_SPACE, 0),
1799                       keyboardState, &ignored, 0, GetKeyboardLayout());
1800 
1801           // Set this flag to block ActivateKeyboardLayout from
1802           // WInputMethod.activate()
1803           g_bUserHasChangedInputLang = TRUE;
1804           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1805           break;
1806       }
1807       case WM_INPUTLANGCHANGE:
1808           DTRACE_PRINTLN3("WM_INPUTLANGCHANGE: hwnd = 0x%X (%s);"//
1809                           "new = 0x%08X",
1810                           GetHWnd(), GetClassName(), (UINT)lParam);
1811           mr = WmInputLangChange(static_cast<UINT>(wParam), reinterpret_cast<HKL>(lParam));
1812           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1813           // should return non-zero if we process this message
1814           retValue = 1;
1815           break;
1816 
1817       case WM_AWT_FORWARD_CHAR:
1818           mr = WmForwardChar(LOWORD(wParam), lParam, HIWORD(wParam));
1819           break;
1820 
1821       case WM_AWT_FORWARD_BYTE:
1822           mr = HandleEvent( (MSG *) lParam, (BOOL) wParam);
1823           break;
1824 
1825       case WM_PASTE:
1826           mr = WmPaste();
1827           break;
1828       case WM_TIMER:
1829           mr = WmTimer(wParam);
1830           break;
1831 
1832       case WM_COMMAND:
1833           mr = WmCommand(LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
1834           break;
1835       case WM_COMPAREITEM:
1836           mr = WmCompareItem(static_cast<UINT>(wParam),
1837                              *(COMPAREITEMSTRUCT*)lParam, retValue);
1838           break;
1839       case WM_DELETEITEM:
1840           mr = WmDeleteItem(static_cast<UINT>(wParam),
1841                             *(DELETEITEMSTRUCT*)lParam);
1842           break;
1843       case WM_DRAWITEM:
1844           mr = WmDrawItem(static_cast<UINT>(wParam),
1845                           *(DRAWITEMSTRUCT*)lParam);
1846           break;
1847       case WM_MEASUREITEM:
1848           mr = WmMeasureItem(static_cast<UINT>(wParam),
1849                              *(MEASUREITEMSTRUCT*)lParam);
1850           break;
1851 
1852       case WM_AWT_HANDLE_EVENT:
1853           mr = HandleEvent( (MSG *) lParam, (BOOL) wParam);
1854           break;
1855 
1856       case WM_PRINT:
1857           mr = WmPrint((HDC)wParam, lParam);
1858           break;
1859       case WM_PRINTCLIENT:
1860           mr = WmPrintClient((HDC)wParam, lParam);
1861           break;
1862 
1863       case WM_NCCALCSIZE:
1864           mr = WmNcCalcSize((BOOL)wParam, (LPNCCALCSIZE_PARAMS)lParam,
1865                             retValue);
1866           break;
1867       case WM_NCPAINT:
1868           mr = WmNcPaint((HRGN)wParam);
1869           break;
1870       case WM_NCHITTEST:
1871           mr = WmNcHitTest(LOWORD(lParam), HIWORD(lParam), retValue);
1872           break;
1873 
1874       case WM_AWT_RESHAPE_COMPONENT: {
1875           RECT* r = (RECT*)lParam;
1876           WPARAM checkEmbedded = wParam;
1877           if (checkEmbedded == CHECK_EMBEDDED && IsEmbeddedFrame()) {
1878               ::OffsetRect(r, -r->left, -r->top);
1879           }
1880           Reshape(r->left, r->top, r->right - r->left, r->bottom - r->top);
1881           delete r;
1882           mr = mrConsume;
1883           break;
1884       }
1885 
1886       case WM_AWT_SETALWAYSONTOP: {
1887         AwtWindow* w = (AwtWindow*)lParam;
1888         BOOL value = (BOOL)wParam;
1889         UINT flags = SWP_NOMOVE | SWP_NOSIZE;
1890         // transient windows shouldn't change the owner window's position in the z-order
1891         if (w->IsRetainingHierarchyZOrder()) {
1892             flags |= SWP_NOOWNERZORDER;
1893         }
1894         ::SetWindowPos(w->GetHWnd(), (value != 0 ? HWND_TOPMOST : HWND_NOTOPMOST),
1895                        0,0,0,0, flags);
1896         break;
1897       }
1898 
1899       case WM_AWT_BEGIN_VALIDATE:
1900           BeginValidate();
1901           mr = mrConsume;
1902           break;
1903       case WM_AWT_END_VALIDATE:
1904           EndValidate();
1905           mr = mrConsume;
1906           break;
1907 
1908       case WM_PALETTEISCHANGING:
1909           mr = WmPaletteIsChanging((HWND)wParam);
1910           mr = mrDoDefault;
1911           break;
1912       case WM_QUERYNEWPALETTE:
1913           mr = WmQueryNewPalette(retValue);
1914           break;
1915       case WM_PALETTECHANGED:
1916           mr = WmPaletteChanged((HWND)wParam);
1917           break;
1918       case WM_STYLECHANGED:
1919           mr = WmStyleChanged(static_cast<int>(wParam), (LPSTYLESTRUCT)lParam);
1920           break;
1921       case WM_SETTINGCHANGE:
1922           CheckFontSmoothingSettings(NULL);
1923           mr = WmSettingChange(static_cast<UINT>(wParam), (LPCTSTR)lParam);
1924           break;
1925       case WM_CONTEXTMENU:
1926           mr = WmContextMenu((HWND)wParam,
1927                              GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1928           break;
1929 
1930           /*
1931            * These messages are used to route Win32 calls to the
1932            * creating thread, since these calls fail unless executed
1933            * there.
1934            */
1935       case WM_AWT_COMPONENT_SHOW:
1936           Show();
1937           mr = mrConsume;
1938           break;
1939       case WM_AWT_COMPONENT_HIDE:
1940           Hide();
1941           mr = mrConsume;
1942           break;
1943 
1944       case WM_AWT_COMPONENT_SETFOCUS:
1945           if ((BOOL)wParam) {
1946               retValue = SynthesizeWmSetFocus(GetHWnd(), NULL);
1947           } else {
1948               retValue = SynthesizeWmKillFocus(GetHWnd(), NULL);
1949           }
1950           mr = mrConsume;
1951           break;
1952       case WM_AWT_WINDOW_SETACTIVE:
1953           retValue = (LRESULT)((AwtWindow*)this)->AwtSetActiveWindow((BOOL)wParam);
1954           mr = mrConsume;
1955           break;
1956 
1957       case WM_AWT_SET_SCROLL_INFO: {
1958           SCROLLINFO *si = (SCROLLINFO *) lParam;
1959           ::SetScrollInfo(GetHWnd(), (int) wParam, si, TRUE);
1960           delete si;
1961           mr = mrConsume;
1962           break;
1963       }
1964       case WM_AWT_CREATE_PRINTED_PIXELS: {
1965           CreatePrintedPixelsStruct* cpps = (CreatePrintedPixelsStruct*)wParam;
1966           SIZE loc = { cpps->srcx, cpps->srcy };
1967           SIZE size = { cpps->srcw, cpps->srch };
1968           retValue = (LRESULT)CreatePrintedPixels(loc, size, cpps->alpha);
1969           mr = mrConsume;
1970           break;
1971       }
1972       case WM_UNDOCUMENTED_CLICKMENUBAR:
1973       {
1974           if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) {
1975               mr = mrConsume;
1976           }
1977       }
1978     }
1979 
1980     /*
1981      * If not a specific Consume, it was a specific DoDefault, or a
1982      * PassAlong (since the default is the next in chain), then call the
1983      * default proc.
1984      */
1985     if (mr != mrConsume) {
1986         retValue = DefWindowProc(message, wParam, lParam);
1987     }
1988 
1989     return retValue;
1990 }
1991 /*
1992  * Call this instance's default window proc, or if none set, call the stock
1993  * Window's one.
1994  */
1995 LRESULT AwtComponent::DefWindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
1996 {
1997     return ComCtl32Util::GetInstance().DefWindowProc(m_DefWindowProc, GetHWnd(), msg, wParam, lParam);
1998 }
1999 
2000 /*
2001  * This message should only be received when a window is destroyed by
2002  * Windows, and not Java.  Window termination has been reworked so
2003  * this method should never be called during termination.
2004  */
2005 MsgRouting AwtComponent::WmDestroy()
2006 {
2007     return mrConsume;
2008 }
2009 
2010 /*
2011  * This message should only be received when a window is destroyed by
2012  * Windows, and not Java. It is sent only after child windows were destroyed.
2013  */
2014 MsgRouting AwtComponent::WmNcDestroy()
2015 {
2016     if (m_peerObject != NULL) { // is not being terminating
2017         // Stay in this handler until AwtComponent::Dispose is called.
2018         m_bPauseDestroy = TRUE;
2019 
2020         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2021         // Post invocation event for WObjectPeer.dispose to EDT
2022         env->CallVoidMethod(m_peerObject, AwtComponent::disposeLaterMID);
2023         // Wait until AwtComponent::Dispose is called
2024         AwtToolkit::GetInstance().PumpToDestroy(this);
2025     }
2026 
2027     return mrConsume;
2028 }
2029 
2030 MsgRouting AwtComponent::WmGetMinMaxInfo(LPMINMAXINFO lpmmi)
2031 {
2032     return mrDoDefault;
2033 }
2034 
2035 MsgRouting AwtComponent::WmMove(int x, int y)
2036 {
2037     SetDrawState(GetDrawState() | static_cast<jint>(JAWT_LOCK_BOUNDS_CHANGED)
2038         | static_cast<jint>(JAWT_LOCK_CLIP_CHANGED));
2039     return mrDoDefault;
2040 }
2041 
2042 MsgRouting AwtComponent::WmSize(UINT type, int w, int h)
2043 {
2044     SetDrawState(GetDrawState() | static_cast<jint>(JAWT_LOCK_BOUNDS_CHANGED)
2045         | static_cast<jint>(JAWT_LOCK_CLIP_CHANGED));
2046     return mrDoDefault;
2047 }
2048 
2049 MsgRouting AwtComponent::WmSizing()
2050 {
2051     return mrDoDefault;
2052 }
2053 
2054 MsgRouting AwtComponent::WmSysCommand(UINT uCmdType, int xPos, int yPos)
2055 {
2056     return mrDoDefault;
2057 }
2058 
2059 MsgRouting AwtComponent::WmExitSizeMove()
2060 {
2061     return mrDoDefault;
2062 }
2063 
2064 MsgRouting AwtComponent::WmEnterMenuLoop(BOOL isTrackPopupMenu)
2065 {
2066     return mrDoDefault;
2067 }
2068 
2069 MsgRouting AwtComponent::WmExitMenuLoop(BOOL isTrackPopupMenu)
2070 {
2071     return mrDoDefault;
2072 }
2073 
2074 MsgRouting AwtComponent::WmShowWindow(BOOL show, UINT status)
2075 {
2076     return mrDoDefault;
2077 }
2078 
2079 MsgRouting AwtComponent::WmSetFocus(HWND hWndLostFocus)
2080 {
2081     m_wheelRotationAmount = 0;
2082     return mrDoDefault;
2083 }
2084 
2085 MsgRouting AwtComponent::WmKillFocus(HWND hWndGotFocus)
2086 {
2087     m_wheelRotationAmount = 0;
2088     return mrDoDefault;
2089 }
2090 
2091 MsgRouting AwtComponent::WmCtlColor(HDC hDC, HWND hCtrl,
2092                                     UINT ctlColor, HBRUSH& retBrush)
2093 {
2094     AwtComponent* child = AwtComponent::GetComponent(hCtrl);
2095     if (child) {
2096         ::SetBkColor(hDC, child->GetBackgroundColor());
2097         ::SetTextColor(hDC, child->GetColor());
2098         retBrush = child->GetBackgroundBrush();
2099         return mrConsume;
2100     }
2101     return mrDoDefault;
2102 /*
2103     switch (ctlColor) {
2104         case CTLCOLOR_MSGBOX:
2105         case CTLCOLOR_EDIT:
2106         case CTLCOLOR_LISTBOX:
2107         case CTLCOLOR_BTN:
2108         case CTLCOLOR_DLG:
2109         case CTLCOLOR_SCROLLBAR:
2110         case CTLCOLOR_STATIC:
2111     }
2112 */
2113 }
2114 
2115 MsgRouting AwtComponent::WmHScroll(UINT scrollCode, UINT pos,
2116                                    HWND hScrollbar) {
2117     if (hScrollbar && hScrollbar != GetHWnd()) {
2118         /* the last test should never happen */
2119         AwtComponent* sb = GetComponent(hScrollbar);
2120         if (sb) {
2121             sb->WmHScroll(scrollCode, pos, hScrollbar);
2122         }
2123     }
2124     return mrDoDefault;
2125 }
2126 
2127 MsgRouting AwtComponent::WmVScroll(UINT scrollCode, UINT pos, HWND hScrollbar)
2128 {
2129     if (hScrollbar && hScrollbar != GetHWnd()) {
2130         /* the last test should never happen */
2131         AwtComponent* sb = GetComponent(hScrollbar);
2132         if (sb) {
2133             sb->WmVScroll(scrollCode, pos, hScrollbar);
2134         }
2135     }
2136     return mrDoDefault;
2137 }
2138 
2139 
2140 MsgRouting AwtComponent::WmPaint(HDC)
2141 {
2142     /* Get the rectangle that covers all update regions, if any exist. */
2143     RECT r;
2144     if (::GetUpdateRect(GetHWnd(), &r, FALSE)) {
2145         if ((r.right-r.left) > 0 && (r.bottom-r.top) > 0 &&
2146             m_peerObject != NULL && m_callbacksEnabled) {
2147             /*
2148              * Always call handlePaint, because the underlying control
2149              * will have painted itself (the "background") before any
2150              * paint method is called.
2151              */
2152             DoCallback("handlePaint", "(IIII)V",
2153                        r.left, r.top, r.right-r.left, r.bottom-r.top);
2154         }
2155     }
2156     return mrDoDefault;
2157 }
2158 
2159 void AwtComponent::PaintUpdateRgn(const RECT *insets)
2160 {
2161     // Fix 4530093: Don't Validate if can't actually paint
2162     if (m_peerObject == NULL || !m_callbacksEnabled) {
2163 
2164         // Fix 4745222: If we don't ValidateRgn,  windows will keep sending
2165         // WM_PAINT messages until we do. This causes java to go into
2166         // a tight loop that increases CPU to 100% and starves main
2167         // thread which needs to complete initialization, but cant.
2168         ::ValidateRgn(GetHWnd(), NULL);
2169 
2170         return;
2171     }
2172 
2173     HRGN rgn = ::CreateRectRgn(0,0,1,1);
2174     int updated = ::GetUpdateRgn(GetHWnd(), rgn, FALSE);
2175     /*
2176      * Now remove all update regions from this window -- do it
2177      * here instead of after the Java upcall, in case any new
2178      * updating is requested.
2179      */
2180     ::ValidateRgn(GetHWnd(), NULL);
2181 
2182     if (updated == COMPLEXREGION || updated == SIMPLEREGION) {
2183         if (insets != NULL) {
2184             ::OffsetRgn(rgn, insets->left, insets->top);
2185         }
2186         DWORD size = ::GetRegionData(rgn, 0, NULL);
2187         if (size == 0) {
2188             ::DeleteObject((HGDIOBJ)rgn);
2189             return;
2190         }
2191         char* buffer = new char[size]; // safe because sizeof(char)==1
2192         memset(buffer, 0, size);
2193         LPRGNDATA rgndata = (LPRGNDATA)buffer;
2194         rgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
2195         rgndata->rdh.iType = RDH_RECTANGLES;
2196         int retCode = ::GetRegionData(rgn, size, rgndata);
2197         VERIFY(retCode);
2198         if (retCode == 0) {
2199             delete [] buffer;
2200             ::DeleteObject((HGDIOBJ)rgn);
2201             return;
2202         }
2203         /*
2204          * Updating rects are divided into mostly vertical and mostly horizontal
2205          * Each group is united together and if not empty painted separately
2206          */
2207         RECT* r = (RECT*)(buffer + rgndata->rdh.dwSize);
2208         RECT* un[2] = {0, 0};
2209     DWORD i;
2210     for (i = 0; i < rgndata->rdh.nCount; i++, r++) {
2211             int width = r->right-r->left;
2212             int height = r->bottom-r->top;
2213             if (width > 0 && height > 0) {
2214                 int toAdd = (width > height) ? 0: 1;
2215                 if (un[toAdd] != 0) {
2216                     ::UnionRect(un[toAdd], un[toAdd], r);
2217                 } else {
2218                     un[toAdd] = r;
2219                 }
2220             }
2221         }
2222         for(i = 0; i < 2; i++) {
2223             if (un[i] != 0) {
2224                 DoCallback("handleExpose", "(IIII)V",
2225                            ScaleDownX(un[i]->left),
2226                            ScaleDownY(un[i]->top),
2227                            ScaleDownX(un[i]->right - un[i]->left),
2228                            ScaleDownY(un[i]->bottom - un[i]->top));
2229             }
2230         }
2231         delete [] buffer;
2232     }
2233     ::DeleteObject((HGDIOBJ)rgn);
2234 }
2235 
2236 MsgRouting AwtComponent::WmMouseEnter(UINT flags, int x, int y)
2237 {
2238     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_ENTERED,
2239                    ::JVM_CurrentTimeMillis(NULL, 0), x, y, GetJavaModifiers(), 0, JNI_FALSE);
2240     if ((flags & ALL_MK_BUTTONS) == 0) {
2241         AwtCursor::UpdateCursor(this);
2242     }
2243     sm_cursorOn = GetHWnd();
2244     return mrConsume;   /* Don't pass our synthetic event on! */
2245 }
2246 
2247 MSG*
2248 AwtComponent::CreateMessage(UINT message, WPARAM wParam, LPARAM lParam,
2249                             int x = 0, int y = 0)
2250 {
2251     MSG* pMsg = new MSG;
2252     InitMessage(pMsg, message, wParam, lParam, x, y);
2253     return pMsg;
2254 }
2255 
2256 
2257 jint
2258 AwtComponent::GetDrawState(HWND hwnd) {
2259     return (jint)(INT_PTR)(::GetProp(hwnd, DrawingStateProp));
2260 }
2261 
2262 void
2263 AwtComponent::SetDrawState(HWND hwnd, jint state) {
2264     ::SetProp(hwnd, DrawingStateProp, (HANDLE)(INT_PTR)state);
2265 }
2266 
2267 void
2268 AwtComponent::InitMessage(MSG* msg, UINT message, WPARAM wParam, LPARAM lParam,
2269                             int x = 0, int y = 0)
2270 {
2271     msg->message = message;
2272     msg->wParam = wParam;
2273     msg->lParam = lParam;
2274     msg->time = ::GetMessageTime();
2275     msg->pt.x = x;
2276     msg->pt.y = y;
2277 }
2278 
2279 MsgRouting AwtComponent::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
2280     return mrDoDefault;
2281 }
2282 MsgRouting AwtComponent::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) {
2283     return mrDoDefault;
2284 }
2285 
2286 MsgRouting AwtComponent::WmWindowPosChanging(LPARAM windowPos) {
2287     return mrDoDefault;
2288 }
2289 MsgRouting AwtComponent::WmWindowPosChanged(LPARAM windowPos) {
2290     return mrDoDefault;
2291 }
2292 
2293 /* Double-click variables. */
2294 static jlong multiClickTime = ::GetDoubleClickTime();
2295 static int multiClickMaxX = ::GetSystemMetrics(SM_CXDOUBLECLK);
2296 static int multiClickMaxY = ::GetSystemMetrics(SM_CYDOUBLECLK);
2297 static AwtComponent* lastClickWnd = NULL;
2298 static jlong lastTime = 0;
2299 static int lastClickX = 0;
2300 static int lastClickY = 0;
2301 static int lastButton = 0;
2302 static int clickCount = 0;
2303 
2304 // A static method that makes the clickCount available in the derived classes
2305 // overriding WmMouseDown().
2306 int AwtComponent::GetClickCount()
2307 {
2308     return clickCount;
2309 }
2310 
2311 MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button)
2312 {
2313     jlong now = ::JVM_CurrentTimeMillis(NULL, 0);
2314 
2315     if (lastClickWnd == this &&
2316         lastButton == button &&
2317         (now - lastTime) <= multiClickTime &&
2318         abs(x - lastClickX) <= multiClickMaxX &&
2319         abs(y - lastClickY) <= multiClickMaxY)
2320     {
2321         clickCount++;
2322     } else {
2323         clickCount = 1;
2324         lastClickWnd = this;
2325         lastButton = button;
2326         lastClickX = x;
2327         lastClickY = y;
2328     }
2329     /*
2330      *Set appropriate bit of the mask on WM_MOUSE_DOWN message.
2331      */
2332     m_mouseButtonClickAllowed |= GetButtonMK(button);
2333     lastTime = now;
2334 
2335     MSG msg;
2336     InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2337 
2338     AwtWindow *toplevel = GetContainer();
2339     if (toplevel && !toplevel->IsSimpleWindow()) {
2340         /*
2341          * The frame should be focused by click in case it is
2342          * the active window but not the focused window. See 6886678.
2343          */
2344         if (toplevel->GetHWnd() == ::GetActiveWindow() &&
2345             toplevel->GetHWnd() != AwtComponent::GetFocusedWindow())
2346         {
2347             toplevel->AwtSetActiveWindow();
2348         }
2349     }
2350 
2351     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y,
2352                    GetJavaModifiers(), clickCount, JNI_FALSE,
2353                    GetButton(button), &msg);
2354     /*
2355      * NOTE: this call is intentionally placed after all other code,
2356      * since AwtComponent::WmMouseDown() assumes that the cached id of the
2357      * latest retrieved message (see lastMessage in awt_Component.cpp)
2358      * matches the mouse message being processed.
2359      * SetCapture() sends WM_CAPTURECHANGED and breaks that
2360      * assumption.
2361      */
2362     SetDragCapture(flags);
2363 
2364     AwtWindow * owner = (AwtWindow*)GetComponent(GetTopLevelParentForWindow(GetHWnd()));
2365     if (AwtWindow::GetGrabbedWindow() != NULL && owner != NULL) {
2366         if (!AwtWindow::GetGrabbedWindow()->IsOneOfOwnersOf(owner)) {
2367             AwtWindow::GetGrabbedWindow()->Ungrab();
2368         }
2369     }
2370     return mrConsume;
2371 }
2372 
2373 MsgRouting AwtComponent::WmMouseUp(UINT flags, int x, int y, int button)
2374 {
2375     MSG msg;
2376     InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2377 
2378     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, ::JVM_CurrentTimeMillis(NULL, 0),
2379                    x, y, GetJavaModifiers(), clickCount,
2380                    (GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
2381                     TRUE : FALSE), GetButton(button), &msg);
2382     /*
2383      * If no movement, then report a click following the button release.
2384      * When WM_MOUSEUP comes to a window without previous WM_MOUSEDOWN,
2385      * spurous MOUSE_CLICK is about to happen. See 6430553.
2386      */
2387     if ((m_mouseButtonClickAllowed & GetButtonMK(button)) != 0) { //CLICK allowed
2388         SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
2389                        ::JVM_CurrentTimeMillis(NULL, 0), x, y, GetJavaModifiers(),
2390                        clickCount, JNI_FALSE, GetButton(button));
2391     }
2392     // Exclude button from allowed to generate CLICK messages
2393     m_mouseButtonClickAllowed &= ~GetButtonMK(button);
2394 
2395     if ((flags & ALL_MK_BUTTONS) == 0) {
2396         // only update if all buttons have been released
2397         AwtCursor::UpdateCursor(this);
2398     }
2399     /*
2400      * NOTE: this call is intentionally placed after all other code,
2401      * since AwtComponent::WmMouseUp() assumes that the cached id of the
2402      * latest retrieved message (see lastMessage in awt_Component.cpp)
2403      * matches the mouse message being processed.
2404      * ReleaseCapture() sends WM_CAPTURECHANGED and breaks that
2405      * assumption.
2406      */
2407     ReleaseDragCapture(flags);
2408 
2409     return mrConsume;
2410 }
2411 
2412 MsgRouting AwtComponent::WmMouseMove(UINT flags, int x, int y)
2413 {
2414     static AwtComponent* lastComp = NULL;
2415     static int lastX = 0;
2416     static int lastY = 0;
2417 
2418     /*
2419      * Only report mouse move and drag events if a move or drag
2420      * actually happened -- Windows sends a WM_MOUSEMOVE in case the
2421      * app wants to modify the cursor.
2422      */
2423     if (lastComp != this || x != lastX || y != lastY) {
2424         lastComp = this;
2425         lastX = x;
2426         lastY = y;
2427         BOOL extraButtonsEnabled = AwtToolkit::GetInstance().areExtraMouseButtonsEnabled();
2428         if (((flags & (ALL_MK_BUTTONS)) != 0) ||
2429             (extraButtonsEnabled && (flags & (X_BUTTONS)) != 0))
2430 //        if (( extraButtonsEnabled && ( (flags & (ALL_MK_BUTTONS | X_BUTTONS)) != 0 )) ||
2431 //            ( !extraButtonsEnabled && (((flags & (ALL_MK_BUTTONS)) != 0 )) && ((flags & (X_BUTTONS)) == 0) ))
2432         {
2433             // 6404008 : if Dragged event fired we shouldn't fire
2434             // Clicked event: m_firstDragSent set to TRUE.
2435             // This is a partial backout of 5039416 fix.
2436             MSG msg;
2437             InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2438             SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, ::JVM_CurrentTimeMillis(NULL, 0), x, y,
2439                            GetJavaModifiers(), 0, JNI_FALSE,
2440                            java_awt_event_MouseEvent_NOBUTTON, &msg);
2441             //dragging means no more CLICKs until next WM_MOUSE_DOWN/WM_MOUSE_UP message sequence
2442             m_mouseButtonClickAllowed = 0;
2443         } else {
2444             MSG msg;
2445             InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2446             SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, ::JVM_CurrentTimeMillis(NULL, 0), x, y,
2447                            GetJavaModifiers(), 0, JNI_FALSE,
2448                            java_awt_event_MouseEvent_NOBUTTON, &msg);
2449         }
2450     }
2451 
2452     return mrConsume;
2453 }
2454 
2455 MsgRouting AwtComponent::WmMouseExit(UINT flags, int x, int y)
2456 {
2457     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_EXITED, ::JVM_CurrentTimeMillis(NULL, 0), x,
2458                    y, GetJavaModifiers(), 0, JNI_FALSE);
2459     sm_cursorOn = NULL;
2460     return mrConsume;   /* Don't pass our synthetic event on! */
2461 }
2462 
2463 MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y,
2464                                       int wheelRotation)
2465 {
2466     // convert coordinates to be Component-relative, not screen relative
2467     // for wheeling when outside the window, this works similar to
2468     // coordinates during a drag
2469     POINT eventPt;
2470     eventPt.x = x;
2471     eventPt.y = y;
2472     DTRACE_PRINT2("  original coords: %i,%i\n", x, y);
2473     ::ScreenToClient(GetHWnd(), &eventPt);
2474     DTRACE_PRINT2("  new coords: %i,%i\n\n", eventPt.x, eventPt.y);
2475 
2476     // set some defaults
2477     jint scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL;
2478     jint scrollLines = 3;
2479 
2480     BOOL result;
2481     UINT platformLines;
2482 
2483     m_wheelRotationAmount += wheelRotation;
2484 
2485     // AWT interprets wheel rotation differently than win32, so we need to
2486     // decode wheel amount.
2487     jint roundedWheelRotation = m_wheelRotationAmount / (-1 * WHEEL_DELTA);
2488     jdouble preciseWheelRotation = (jdouble) wheelRotation / (-1 * WHEEL_DELTA);
2489 
2490     MSG msg;
2491     result = ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
2492                                     &platformLines, 0);
2493     InitMessage(&msg, lastMessage, MAKEWPARAM(flags, wheelRotation),
2494                 MAKELPARAM(x, y));
2495 
2496     if (result) {
2497         if (platformLines == WHEEL_PAGESCROLL) {
2498             scrollType = java_awt_event_MouseWheelEvent_WHEEL_BLOCK_SCROLL;
2499             scrollLines = 1;
2500         }
2501         else {
2502             scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL;
2503             scrollLines = platformLines;
2504         }
2505     }
2506 
2507     DTRACE_PRINTLN("calling SendMouseWheelEvent");
2508 
2509     SendMouseWheelEvent(java_awt_event_MouseEvent_MOUSE_WHEEL, ::JVM_CurrentTimeMillis(NULL, 0),
2510                         eventPt.x, eventPt.y, GetJavaModifiers(), 0, 0, scrollType,
2511                         scrollLines, roundedWheelRotation, preciseWheelRotation, &msg);
2512 
2513     m_wheelRotationAmount %= WHEEL_DELTA;
2514     // this message could be propagated up to the parent chain
2515     // by the mouse message post processors
2516     return mrConsume;
2517 }
2518 
2519 jint AwtComponent::GetKeyLocation(UINT wkey, UINT flags) {
2520     // Rector+Newcomer page 413
2521     // The extended keys are the Alt and Control on the right of
2522     // the space bar, the non-Numpad arrow keys, the non-Numpad
2523     // Insert, PageUp, etc. keys, and the Numpad Divide and Enter keys.
2524     // Note that neither Shift key is extended.
2525     // Although not listed in Rector+Newcomer, both Windows keys
2526     // (91 and 92) are extended keys, the Context Menu key
2527     // (property key or application key - 93) is extended,
2528     // and so is the NumLock key.
2529 
2530     // wkey is the wParam, flags is the HIWORD of the lParam
2531 
2532     // "Extended" bit is 24th in lParam, so it's 8th in flags = HIWORD(lParam)
2533     BOOL extended = ((1<<8) & flags);
2534 
2535     if (IsNumPadKey(wkey, extended)) {
2536         return java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD;
2537     }
2538 
2539     switch (wkey) {
2540       case VK_SHIFT:
2541         return AwtComponent::GetShiftKeyLocation(wkey, flags);
2542       case VK_CONTROL: // fall through
2543       case VK_MENU:
2544         if (extended) {
2545             return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
2546         } else {
2547             return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2548         }
2549       case VK_LWIN:
2550         return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2551       case VK_RWIN:
2552         return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
2553       default:
2554         break;
2555     }
2556 
2557     // REMIND: if we add keycodes for the windows keys, we'll have to
2558     // include left/right discrimination code for them.
2559 
2560     return java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
2561 }
2562 
2563 jint AwtComponent::GetShiftKeyLocation(UINT vkey, UINT flags)
2564 {
2565     // init scancodes to safe values
2566     UINT leftShiftScancode = 0;
2567     UINT rightShiftScancode = 0;
2568 
2569     // First 8 bits of flags is the scancode
2570     UINT keyScanCode = flags & 0xFF;
2571 
2572     DTRACE_PRINTLN3(
2573       "AwtComponent::GetShiftKeyLocation  vkey = %d = 0x%x  scan = %d",
2574       vkey, vkey, keyScanCode);
2575 
2576     leftShiftScancode = ::MapVirtualKey(VK_LSHIFT, 0);
2577     rightShiftScancode = ::MapVirtualKey(VK_RSHIFT, 0);
2578 
2579     if (keyScanCode == leftShiftScancode) {
2580         return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2581     }
2582     if (keyScanCode == rightShiftScancode) {
2583         return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
2584     }
2585 
2586     DASSERT(false);
2587     // Note: the above should not fail on NT (or 2000)
2588 
2589     // default value
2590     return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2591 }
2592 
2593 /* Returns Java ActionEvent modifieres.
2594  * When creating ActionEvent, modifiers provided by ActionEvent
2595  * class should be set.
2596  */
2597 jint
2598 AwtComponent::GetActionModifiers()
2599 {
2600     jint modifiers = GetJavaModifiers();
2601 
2602     if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
2603         modifiers |= java_awt_event_ActionEvent_CTRL_MASK;
2604     }
2605     if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
2606         modifiers |= java_awt_event_ActionEvent_SHIFT_MASK;
2607     }
2608     if (modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) {
2609         modifiers |= java_awt_event_ActionEvent_ALT_MASK;
2610     }
2611     return modifiers;
2612 }
2613 
2614 /* Returns Java extended InputEvent modifieres.
2615  * Since ::GetKeyState returns current state and Java modifiers represent
2616  * state before event, modifier on changed key are inverted.
2617  */
2618 jint
2619 AwtComponent::GetJavaModifiers()
2620 {
2621     jint modifiers = 0;
2622 
2623     if (HIBYTE(::GetKeyState(VK_CONTROL)) != 0) {
2624         modifiers |= java_awt_event_InputEvent_CTRL_DOWN_MASK;
2625     }
2626     if (HIBYTE(::GetKeyState(VK_SHIFT)) != 0) {
2627         modifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK;
2628     }
2629     if (HIBYTE(::GetKeyState(VK_MENU)) != 0) {
2630         modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK;
2631     }
2632     if (HIBYTE(::GetKeyState(VK_RMENU)) != 0) {
2633         modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK;
2634     }
2635     if (HIBYTE(::GetKeyState(VK_MBUTTON)) != 0) {
2636        modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK;
2637     }
2638     if (HIBYTE(::GetKeyState(VK_RBUTTON)) != 0) {
2639         modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK;
2640     }
2641     if (HIBYTE(::GetKeyState(VK_LBUTTON)) != 0) {
2642         modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK;
2643     }
2644 
2645     if (HIBYTE(::GetKeyState(VK_XBUTTON1)) != 0) {
2646         modifiers |= masks[3];
2647     }
2648     if (HIBYTE(::GetKeyState(VK_XBUTTON2)) != 0) {
2649         modifiers |= masks[4];
2650     }
2651     return modifiers;
2652 }
2653 
2654 jint
2655 AwtComponent::GetButton(int mouseButton)
2656 {
2657     /* Mouse buttons are already set correctly for left/right handedness */
2658     switch(mouseButton) {
2659     case LEFT_BUTTON:
2660         return java_awt_event_MouseEvent_BUTTON1;
2661     case MIDDLE_BUTTON:
2662         return java_awt_event_MouseEvent_BUTTON2;
2663     case RIGHT_BUTTON:
2664         return java_awt_event_MouseEvent_BUTTON3;
2665     case X1_BUTTON: //16 :
2666         //just assign 4 and 5 numbers because MouseEvent class doesn't contain const identifier for them now
2667         return 4;
2668     case X2_BUTTON: //32
2669         return 5;
2670     }
2671     return java_awt_event_MouseEvent_NOBUTTON;
2672 }
2673 
2674 UINT
2675 AwtComponent::GetButtonMK(int mouseButton)
2676 {
2677     switch(mouseButton) {
2678     case LEFT_BUTTON:
2679         return MK_LBUTTON;
2680     case MIDDLE_BUTTON:
2681         return MK_MBUTTON;
2682     case RIGHT_BUTTON:
2683         return MK_RBUTTON;
2684     case X1_BUTTON:
2685         return MK_XBUTTON1;
2686     case X2_BUTTON:
2687         return MK_XBUTTON2;
2688     }
2689     return 0;
2690 }
2691 
2692 // FIXME: Keyboard related stuff has grown so big and hairy that we
2693 // really need to move it into a class of its own.  And, since
2694 // keyboard is a shared resource, AwtComponent is a bad place for it.
2695 
2696 // These constants are defined in the Japanese version of VC++5.0,
2697 // but not the US version
2698 #ifndef VK_CONVERT
2699 #define VK_KANA           0x15
2700 #define VK_KANJI          0x19
2701 #define VK_CONVERT        0x1C
2702 #define VK_NONCONVERT     0x1D
2703 #endif
2704 
2705 #ifndef VK_XBUTTON1
2706 #define VK_XBUTTON1      0x05
2707 #endif
2708 
2709 #ifndef VK_XBUTTON2
2710 #define VK_XBUTTON2      0x06
2711 #endif
2712 
2713 typedef struct {
2714     UINT javaKey;
2715     UINT windowsKey;
2716 } KeyMapEntry;
2717 
2718 // Static table, arranged more or less spatially.
2719 KeyMapEntry keyMapTable[] = {
2720     // Modifier keys
2721     {java_awt_event_KeyEvent_VK_CAPS_LOCK,        VK_CAPITAL},
2722     {java_awt_event_KeyEvent_VK_SHIFT,            VK_SHIFT},
2723     {java_awt_event_KeyEvent_VK_CONTROL,          VK_CONTROL},
2724     {java_awt_event_KeyEvent_VK_ALT,              VK_MENU},
2725     {java_awt_event_KeyEvent_VK_ALT_GRAPH,        VK_RMENU},
2726     {java_awt_event_KeyEvent_VK_NUM_LOCK,         VK_NUMLOCK},
2727 
2728     // Miscellaneous Windows keys
2729     {java_awt_event_KeyEvent_VK_WINDOWS,          VK_LWIN},
2730     {java_awt_event_KeyEvent_VK_WINDOWS,          VK_RWIN},
2731     {java_awt_event_KeyEvent_VK_CONTEXT_MENU,     VK_APPS},
2732 
2733     // Alphabet
2734     {java_awt_event_KeyEvent_VK_A,                'A'},
2735     {java_awt_event_KeyEvent_VK_B,                'B'},
2736     {java_awt_event_KeyEvent_VK_C,                'C'},
2737     {java_awt_event_KeyEvent_VK_D,                'D'},
2738     {java_awt_event_KeyEvent_VK_E,                'E'},
2739     {java_awt_event_KeyEvent_VK_F,                'F'},
2740     {java_awt_event_KeyEvent_VK_G,                'G'},
2741     {java_awt_event_KeyEvent_VK_H,                'H'},
2742     {java_awt_event_KeyEvent_VK_I,                'I'},
2743     {java_awt_event_KeyEvent_VK_J,                'J'},
2744     {java_awt_event_KeyEvent_VK_K,                'K'},
2745     {java_awt_event_KeyEvent_VK_L,                'L'},
2746     {java_awt_event_KeyEvent_VK_M,                'M'},
2747     {java_awt_event_KeyEvent_VK_N,                'N'},
2748     {java_awt_event_KeyEvent_VK_O,                'O'},
2749     {java_awt_event_KeyEvent_VK_P,                'P'},
2750     {java_awt_event_KeyEvent_VK_Q,                'Q'},
2751     {java_awt_event_KeyEvent_VK_R,                'R'},
2752     {java_awt_event_KeyEvent_VK_S,                'S'},
2753     {java_awt_event_KeyEvent_VK_T,                'T'},
2754     {java_awt_event_KeyEvent_VK_U,                'U'},
2755     {java_awt_event_KeyEvent_VK_V,                'V'},
2756     {java_awt_event_KeyEvent_VK_W,                'W'},
2757     {java_awt_event_KeyEvent_VK_X,                'X'},
2758     {java_awt_event_KeyEvent_VK_Y,                'Y'},
2759     {java_awt_event_KeyEvent_VK_Z,                'Z'},
2760 
2761     // Standard numeric row
2762     {java_awt_event_KeyEvent_VK_0,                '0'},
2763     {java_awt_event_KeyEvent_VK_1,                '1'},
2764     {java_awt_event_KeyEvent_VK_2,                '2'},
2765     {java_awt_event_KeyEvent_VK_3,                '3'},
2766     {java_awt_event_KeyEvent_VK_4,                '4'},
2767     {java_awt_event_KeyEvent_VK_5,                '5'},
2768     {java_awt_event_KeyEvent_VK_6,                '6'},
2769     {java_awt_event_KeyEvent_VK_7,                '7'},
2770     {java_awt_event_KeyEvent_VK_8,                '8'},
2771     {java_awt_event_KeyEvent_VK_9,                '9'},
2772 
2773     // Misc key from main block
2774     {java_awt_event_KeyEvent_VK_ENTER,            VK_RETURN},
2775     {java_awt_event_KeyEvent_VK_SPACE,            VK_SPACE},
2776     {java_awt_event_KeyEvent_VK_BACK_SPACE,       VK_BACK},
2777     {java_awt_event_KeyEvent_VK_TAB,              VK_TAB},
2778     {java_awt_event_KeyEvent_VK_ESCAPE,           VK_ESCAPE},
2779 
2780     // NumPad with NumLock off & extended block (rectangular)
2781     {java_awt_event_KeyEvent_VK_INSERT,           VK_INSERT},
2782     {java_awt_event_KeyEvent_VK_DELETE,           VK_DELETE},
2783     {java_awt_event_KeyEvent_VK_HOME,             VK_HOME},
2784     {java_awt_event_KeyEvent_VK_END,              VK_END},
2785     {java_awt_event_KeyEvent_VK_PAGE_UP,          VK_PRIOR},
2786     {java_awt_event_KeyEvent_VK_PAGE_DOWN,        VK_NEXT},
2787     {java_awt_event_KeyEvent_VK_CLEAR,            VK_CLEAR}, // NumPad 5
2788 
2789     // NumPad with NumLock off & extended arrows block (triangular)
2790     {java_awt_event_KeyEvent_VK_LEFT,             VK_LEFT},
2791     {java_awt_event_KeyEvent_VK_RIGHT,            VK_RIGHT},
2792     {java_awt_event_KeyEvent_VK_UP,               VK_UP},
2793     {java_awt_event_KeyEvent_VK_DOWN,             VK_DOWN},
2794 
2795     // NumPad with NumLock on: numbers
2796     {java_awt_event_KeyEvent_VK_NUMPAD0,          VK_NUMPAD0},
2797     {java_awt_event_KeyEvent_VK_NUMPAD1,          VK_NUMPAD1},
2798     {java_awt_event_KeyEvent_VK_NUMPAD2,          VK_NUMPAD2},
2799     {java_awt_event_KeyEvent_VK_NUMPAD3,          VK_NUMPAD3},
2800     {java_awt_event_KeyEvent_VK_NUMPAD4,          VK_NUMPAD4},
2801     {java_awt_event_KeyEvent_VK_NUMPAD5,          VK_NUMPAD5},
2802     {java_awt_event_KeyEvent_VK_NUMPAD6,          VK_NUMPAD6},
2803     {java_awt_event_KeyEvent_VK_NUMPAD7,          VK_NUMPAD7},
2804     {java_awt_event_KeyEvent_VK_NUMPAD8,          VK_NUMPAD8},
2805     {java_awt_event_KeyEvent_VK_NUMPAD9,          VK_NUMPAD9},
2806 
2807     // NumPad with NumLock on
2808     {java_awt_event_KeyEvent_VK_MULTIPLY,         VK_MULTIPLY},
2809     {java_awt_event_KeyEvent_VK_ADD,              VK_ADD},
2810     {java_awt_event_KeyEvent_VK_SEPARATOR,        VK_SEPARATOR},
2811     {java_awt_event_KeyEvent_VK_SUBTRACT,         VK_SUBTRACT},
2812     {java_awt_event_KeyEvent_VK_DECIMAL,          VK_DECIMAL},
2813     {java_awt_event_KeyEvent_VK_DIVIDE,           VK_DIVIDE},
2814 
2815     // Functional keys
2816     {java_awt_event_KeyEvent_VK_F1,               VK_F1},
2817     {java_awt_event_KeyEvent_VK_F2,               VK_F2},
2818     {java_awt_event_KeyEvent_VK_F3,               VK_F3},
2819     {java_awt_event_KeyEvent_VK_F4,               VK_F4},
2820     {java_awt_event_KeyEvent_VK_F5,               VK_F5},
2821     {java_awt_event_KeyEvent_VK_F6,               VK_F6},
2822     {java_awt_event_KeyEvent_VK_F7,               VK_F7},
2823     {java_awt_event_KeyEvent_VK_F8,               VK_F8},
2824     {java_awt_event_KeyEvent_VK_F9,               VK_F9},
2825     {java_awt_event_KeyEvent_VK_F10,              VK_F10},
2826     {java_awt_event_KeyEvent_VK_F11,              VK_F11},
2827     {java_awt_event_KeyEvent_VK_F12,              VK_F12},
2828     {java_awt_event_KeyEvent_VK_F13,              VK_F13},
2829     {java_awt_event_KeyEvent_VK_F14,              VK_F14},
2830     {java_awt_event_KeyEvent_VK_F15,              VK_F15},
2831     {java_awt_event_KeyEvent_VK_F16,              VK_F16},
2832     {java_awt_event_KeyEvent_VK_F17,              VK_F17},
2833     {java_awt_event_KeyEvent_VK_F18,              VK_F18},
2834     {java_awt_event_KeyEvent_VK_F19,              VK_F19},
2835     {java_awt_event_KeyEvent_VK_F20,              VK_F20},
2836     {java_awt_event_KeyEvent_VK_F21,              VK_F21},
2837     {java_awt_event_KeyEvent_VK_F22,              VK_F22},
2838     {java_awt_event_KeyEvent_VK_F23,              VK_F23},
2839     {java_awt_event_KeyEvent_VK_F24,              VK_F24},
2840 
2841     {java_awt_event_KeyEvent_VK_PRINTSCREEN,      VK_SNAPSHOT},
2842     {java_awt_event_KeyEvent_VK_SCROLL_LOCK,      VK_SCROLL},
2843     {java_awt_event_KeyEvent_VK_PAUSE,            VK_PAUSE},
2844     {java_awt_event_KeyEvent_VK_CANCEL,           VK_CANCEL},
2845     {java_awt_event_KeyEvent_VK_HELP,             VK_HELP},
2846 
2847     // Japanese
2848     {java_awt_event_KeyEvent_VK_CONVERT,          VK_CONVERT},
2849     {java_awt_event_KeyEvent_VK_NONCONVERT,       VK_NONCONVERT},
2850     {java_awt_event_KeyEvent_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
2851     {java_awt_event_KeyEvent_VK_ALPHANUMERIC,     VK_DBE_ALPHANUMERIC},
2852     {java_awt_event_KeyEvent_VK_KATAKANA,         VK_DBE_KATAKANA},
2853     {java_awt_event_KeyEvent_VK_HIRAGANA,         VK_DBE_HIRAGANA},
2854     {java_awt_event_KeyEvent_VK_FULL_WIDTH,       VK_DBE_DBCSCHAR},
2855     {java_awt_event_KeyEvent_VK_HALF_WIDTH,       VK_DBE_SBCSCHAR},
2856     {java_awt_event_KeyEvent_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},
2857 
2858     {java_awt_event_KeyEvent_VK_UNDEFINED,        0}
2859 };
2860 
2861 
2862 // Dynamic mapping table for OEM VK codes.  This table is refilled
2863 // by BuildDynamicKeyMapTable when keyboard layout is switched.
2864 // (see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
2865 struct DynamicKeyMapEntry {
2866     UINT windowsKey;            // OEM VK codes known in advance
2867     UINT javaKey;               // depends on input langauge (kbd layout)
2868 };
2869 
2870 static DynamicKeyMapEntry dynamicKeyMapTable[] = {
2871     {0x00BA,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_1
2872     {0x00BB,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PLUS
2873     {0x00BC,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_COMMA
2874     {0x00BD,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_MINUS
2875     {0x00BE,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PERIOD
2876     {0x00BF,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_2
2877     {0x00C0,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_3
2878     {0x00DB,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_4
2879     {0x00DC,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_5
2880     {0x00DD,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_6
2881     {0x00DE,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_7
2882     {0x00DF,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_8
2883     {0x00E2,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_102
2884     {0, 0}
2885 };
2886 
2887 
2888 
2889 // Auxiliary tables used to fill the above dynamic table.  We first
2890 // find the character for the OEM VK code using ::MapVirtualKey and
2891 // then go through these auxiliary tables to map it to Java VK code.
2892 
2893 struct CharToVKEntry {
2894     WCHAR c;
2895     UINT  javaKey;
2896 };
2897 
2898 static const CharToVKEntry charToVKTable[] = {
2899     {L'!',   java_awt_event_KeyEvent_VK_EXCLAMATION_MARK},
2900     {L'"',   java_awt_event_KeyEvent_VK_QUOTEDBL},
2901     {L'#',   java_awt_event_KeyEvent_VK_NUMBER_SIGN},
2902     {L'$',   java_awt_event_KeyEvent_VK_DOLLAR},
2903     {L'&',   java_awt_event_KeyEvent_VK_AMPERSAND},
2904     {L'\'',  java_awt_event_KeyEvent_VK_QUOTE},
2905     {L'(',   java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS},
2906     {L')',   java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS},
2907     {L'*',   java_awt_event_KeyEvent_VK_ASTERISK},
2908     {L'+',   java_awt_event_KeyEvent_VK_PLUS},
2909     {L',',   java_awt_event_KeyEvent_VK_COMMA},
2910     {L'-',   java_awt_event_KeyEvent_VK_MINUS},
2911     {L'.',   java_awt_event_KeyEvent_VK_PERIOD},
2912     {L'/',   java_awt_event_KeyEvent_VK_SLASH},
2913     {L':',   java_awt_event_KeyEvent_VK_COLON},
2914     {L';',   java_awt_event_KeyEvent_VK_SEMICOLON},
2915     {L'<',   java_awt_event_KeyEvent_VK_LESS},
2916     {L'=',   java_awt_event_KeyEvent_VK_EQUALS},
2917     {L'>',   java_awt_event_KeyEvent_VK_GREATER},
2918     {L'@',   java_awt_event_KeyEvent_VK_AT},
2919     {L'[',   java_awt_event_KeyEvent_VK_OPEN_BRACKET},
2920     {L'\\',  java_awt_event_KeyEvent_VK_BACK_SLASH},
2921     {L']',   java_awt_event_KeyEvent_VK_CLOSE_BRACKET},
2922     {L'^',   java_awt_event_KeyEvent_VK_CIRCUMFLEX},
2923     {L'_',   java_awt_event_KeyEvent_VK_UNDERSCORE},
2924     {L'`',   java_awt_event_KeyEvent_VK_BACK_QUOTE},
2925     {L'{',   java_awt_event_KeyEvent_VK_BRACELEFT},
2926     {L'}',   java_awt_event_KeyEvent_VK_BRACERIGHT},
2927     {0x00A1, java_awt_event_KeyEvent_VK_INVERTED_EXCLAMATION_MARK},
2928     {0x20A0, java_awt_event_KeyEvent_VK_EURO_SIGN}, // ????
2929     {0,0}
2930 };
2931 
2932 // For dead accents some layouts return ASCII punctuation, while some
2933 // return spacing accent chars, so both should be listed.  NB: MS docs
2934 // say that conversion routings return spacing accent character, not
2935 // combining.
2936 static const CharToVKEntry charToDeadVKTable[] = {
2937     {L'`',   java_awt_event_KeyEvent_VK_DEAD_GRAVE},
2938     {L'\'',  java_awt_event_KeyEvent_VK_DEAD_ACUTE},
2939     {0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE},
2940     {L'^',   java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX},
2941     {L'~',   java_awt_event_KeyEvent_VK_DEAD_TILDE},
2942     {0x02DC, java_awt_event_KeyEvent_VK_DEAD_TILDE},
2943     {0x00AF, java_awt_event_KeyEvent_VK_DEAD_MACRON},
2944     {0x02D8, java_awt_event_KeyEvent_VK_DEAD_BREVE},
2945     {0x02D9, java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT},
2946     {L'"',   java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
2947     {0x00A8, java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
2948     {0x02DA, java_awt_event_KeyEvent_VK_DEAD_ABOVERING},
2949     {0x02DD, java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE},
2950     {0x02C7, java_awt_event_KeyEvent_VK_DEAD_CARON},            // aka hacek
2951     {L',',   java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
2952     {0x00B8, java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
2953     {0x02DB, java_awt_event_KeyEvent_VK_DEAD_OGONEK},
2954     {0x037A, java_awt_event_KeyEvent_VK_DEAD_IOTA},             // ASCII ???
2955     {0x309B, java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND},
2956     {0x309C, java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND},
2957     {0x0004, java_awt_event_KeyEvent_VK_COMPOSE},
2958     {0,0}
2959 };
2960 
2961 // The full map of the current keyboard state including
2962 // windows virtual key, scancode, java virtual key, and unicode
2963 // for this key sans modifiers.
2964 // All but first element may be 0.
2965 // XXX in the update releases this is an addition to the unchanged existing code
2966 struct DynPrimaryKeymapEntry {
2967     UINT wkey;
2968     UINT scancode;
2969     UINT jkey;
2970     WCHAR unicode;
2971 };
2972 
2973 static DynPrimaryKeymapEntry dynPrimaryKeymap[256];
2974 
2975 void
2976 AwtComponent::InitDynamicKeyMapTable()
2977 {
2978     static BOOL kbdinited = FALSE;
2979 
2980     if (!kbdinited) {
2981         AwtComponent::BuildDynamicKeyMapTable();
2982         // We cannot build it here since JNI is not available yet:
2983         //AwtComponent::BuildPrimaryDynamicTable();
2984         kbdinited = TRUE;
2985     }
2986 }
2987 
2988 void
2989 AwtComponent::BuildDynamicKeyMapTable()
2990 {
2991     HKL hkl = GetKeyboardLayout();
2992 
2993     DTRACE_PRINTLN2("Building dynamic VK mapping tables: HKL = %08X (CP%d)",
2994                     hkl, AwtComponent::GetCodePage());
2995 
2996     // Will need this to reset layout after dead keys.
2997     UINT spaceScanCode = ::MapVirtualKeyEx(VK_SPACE, 0, hkl);
2998 
2999     // Entries in dynamic table that maps between Java VK and Windows
3000     // VK are built in three steps:
3001     //   1. Map windows VK to ANSI character (cannot map to unicode
3002     //      directly, since ::ToUnicode is not implemented on win9x)
3003     //   2. Convert ANSI char to Unicode char
3004     //   3. Map Unicode char to Java VK via two auxilary tables.
3005 
3006     for (DynamicKeyMapEntry *dynamic = dynamicKeyMapTable;
3007          dynamic->windowsKey != 0;
3008          ++dynamic)
3009     {
3010         // Defaults to VK_UNDEFINED
3011         dynamic->javaKey = java_awt_event_KeyEvent_VK_UNDEFINED;
3012 
3013         BYTE kbdState[AwtToolkit::KB_STATE_SIZE];
3014         AwtToolkit::GetKeyboardState(kbdState);
3015 
3016         kbdState[dynamic->windowsKey] |=  0x80; // Press the key.
3017 
3018         // Unpress modifiers, since they are most likely pressed as
3019         // part of the keyboard switching shortcut.
3020         kbdState[VK_CONTROL] &= ~0x80;
3021         kbdState[VK_SHIFT]   &= ~0x80;
3022         kbdState[VK_MENU]    &= ~0x80;
3023 
3024         char cbuf[2] = { '\0', '\0'};
3025         UINT scancode = ::MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
3026         int nchars = ::ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
3027                                  (WORD*)cbuf, 0, hkl);
3028 
3029         // Auxiliary table used to map Unicode character to Java VK.
3030         // Will assign a different table for dead keys (below).
3031         const CharToVKEntry *charMap = charToVKTable;
3032 
3033         if (nchars < 0) { // Dead key
3034             // Use a different table for dead chars since different layouts
3035             // return different characters for the same dead key.
3036             charMap = charToDeadVKTable;
3037 
3038             // We also need to reset layout so that next translation
3039             // is unaffected by the dead status.  We do this by
3040             // translating <SPACE> key.
3041             kbdState[dynamic->windowsKey] &= ~0x80;
3042             kbdState[VK_SPACE] |= 0x80;
3043 
3044             char junkbuf[2] = { '\0', '\0'};
3045             ::ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
3046                         (WORD*)junkbuf, 0, hkl);
3047         }
3048 
3049 #ifdef DEBUG
3050         if (nchars == 0) {
3051             DTRACE_PRINTLN1("VK 0x%02X -> cannot convert to ANSI char",
3052                             dynamic->windowsKey);
3053             continue;
3054         }
3055         else if (nchars > 1) {  // can't happen, see reset code below
3056             DTRACE_PRINTLN3("VK 0x%02X -> converted to <0x%02X,0x%02X>",
3057                             dynamic->windowsKey,
3058                             (UCHAR)cbuf[0], (UCHAR)cbuf[1]);
3059             continue;
3060         }
3061 #endif
3062 
3063         WCHAR ucbuf[2] = { L'\0', L'\0' };
3064         int nconverted = ::MultiByteToWideChar(AwtComponent::GetCodePage(), 0,
3065                                                cbuf, 1, ucbuf, 2);
3066 #ifdef DEBUG
3067         if (nconverted < 0) {
3068             DTRACE_PRINTLN3("VK 0x%02X -> ANSI 0x%02X -> MultiByteToWideChar failed (0x%X)",
3069                             dynamic->windowsKey, (UCHAR)cbuf[0],
3070                             ::GetLastError());
3071             continue;
3072         }
3073 #endif
3074 
3075         WCHAR uc = ucbuf[0];
3076         for (const CharToVKEntry *map = charMap;  map->c != 0;  ++map) {
3077             if (uc == map->c) {
3078                 dynamic->javaKey = map->javaKey;
3079                 break;
3080             }
3081         }
3082 
3083         DTRACE_PRINTLN4("VK 0x%02X -> ANSI 0x%02X -> U+%04X -> Java VK 0x%X",
3084                         dynamic->windowsKey, (UCHAR)cbuf[0], (UINT)ucbuf[0],
3085                         dynamic->javaKey);
3086     } // for each VK_OEM_*
3087 }
3088 
3089 
3090 static BOOL isKanaLockAvailable()
3091 {
3092     // This method is to determine whether the Kana Lock feature is
3093     // available on the attached keyboard.  Kana Lock feature does not
3094     // necessarily require that the real KANA keytop is available on
3095     // keyboard, so using MapVirtualKey(VK_KANA) is not sufficient for testing.
3096     // Instead of that we regard it as Japanese keyboard (w/ Kana Lock) if :-
3097     //
3098     // - the keyboard layout is Japanese (VK_KANA has the same value as VK_HANGUL)
3099     // - the keyboard is Japanese keyboard (keyboard type == 7).
3100     return (LOWORD(GetKeyboardLayout(0)) == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
3101         && (GetKeyboardType(0) == 7);
3102 }
3103 
3104 void AwtComponent::JavaKeyToWindowsKey(UINT javaKey,
3105                                        UINT *windowsKey, UINT *modifiers, UINT originalWindowsKey)
3106 {
3107     // Handle the few cases where a Java VK code corresponds to a Windows
3108     // key/modifier combination or applies only to specific keyboard layouts
3109     switch (javaKey) {
3110         case java_awt_event_KeyEvent_VK_ALL_CANDIDATES:
3111             *windowsKey = VK_CONVERT;
3112             *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK;
3113             return;
3114         case java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE:
3115             *windowsKey = VK_CONVERT;
3116             *modifiers = java_awt_event_InputEvent_SHIFT_DOWN_MASK;
3117             return;
3118         case java_awt_event_KeyEvent_VK_CODE_INPUT:
3119             *windowsKey = VK_DBE_ALPHANUMERIC;
3120             *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK;
3121             return;
3122         case java_awt_event_KeyEvent_VK_KANA_LOCK:
3123             if (isKanaLockAvailable()) {
3124                 *windowsKey = VK_KANA;
3125                 *modifiers = java_awt_event_InputEvent_CTRL_DOWN_MASK;
3126                 return;
3127             }
3128     }
3129 
3130     // for the general case, use a bi-directional table
3131     for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
3132         if (keyMapTable[i].javaKey == javaKey) {
3133             *windowsKey = keyMapTable[i].windowsKey;
3134             *modifiers = 0;
3135             return;
3136         }
3137     }
3138 
3139     // Bug 4766655
3140     // Two Windows keys could map to the same Java key, so
3141     // give preference to the originalWindowsKey if it is
3142     // specified (not IGNORE_KEY).
3143     if (originalWindowsKey == IGNORE_KEY) {
3144         for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3145             if (dynamicKeyMapTable[j].javaKey == javaKey) {
3146                 *windowsKey = dynamicKeyMapTable[j].windowsKey;
3147                 *modifiers = 0;
3148                 return;
3149             }
3150         }
3151     } else {
3152         BOOL found = false;
3153         for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3154             if (dynamicKeyMapTable[j].javaKey == javaKey) {
3155                 *windowsKey = dynamicKeyMapTable[j].windowsKey;
3156                 *modifiers = 0;
3157                 found = true;
3158                 if (*windowsKey == originalWindowsKey) {
3159                     return;   /* if ideal case found return, else keep looking */
3160                 }
3161             }
3162         }
3163         if (found) {
3164             return;
3165         }
3166     }
3167 
3168     *windowsKey = 0;
3169     *modifiers = 0;
3170     return;
3171 }
3172 
3173 UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey)
3174 
3175 {
3176     // Handle the few cases where we need to take the modifier into
3177     // consideration for the Java VK code or where we have to take the keyboard
3178     // layout into consideration so that function keys can get
3179     // recognized in a platform-independent way.
3180     switch (windowsKey) {
3181         case VK_CONVERT:
3182             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3183                 return java_awt_event_KeyEvent_VK_ALL_CANDIDATES;
3184             }
3185             if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0) {
3186                 return java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE;
3187             }
3188             break;
3189         case VK_DBE_ALPHANUMERIC:
3190             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3191                 return java_awt_event_KeyEvent_VK_CODE_INPUT;
3192             }
3193             break;
3194         case VK_KANA:
3195             if (isKanaLockAvailable()) {
3196                 return java_awt_event_KeyEvent_VK_KANA_LOCK;
3197             }
3198             break;
3199     };
3200 
3201     // check dead key
3202     if (isDeadKey) {
3203       for (int i = 0; charToDeadVKTable[i].c != 0; i++) {
3204         if (charToDeadVKTable[i].c == character) {
3205             return charToDeadVKTable[i].javaKey;
3206         }
3207       }
3208     }
3209 
3210     // for the general case, use a bi-directional table
3211     for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
3212         if (keyMapTable[i].windowsKey == windowsKey) {
3213             return keyMapTable[i].javaKey;
3214         }
3215     }
3216 
3217     for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3218         if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
3219             if (dynamicKeyMapTable[j].javaKey != java_awt_event_KeyEvent_VK_UNDEFINED) {
3220                 return dynamicKeyMapTable[j].javaKey;
3221             }else{
3222                 break;
3223             }
3224         }
3225     }
3226 
3227     return java_awt_event_KeyEvent_VK_UNDEFINED;
3228 }
3229 
3230 BOOL AwtComponent::IsNavigationKey(UINT wkey) {
3231     switch (wkey) {
3232       case VK_END:
3233       case VK_PRIOR:  // PageUp
3234       case VK_NEXT:  // PageDown
3235       case VK_HOME:
3236       case VK_LEFT:
3237       case VK_UP:
3238       case VK_RIGHT:
3239       case VK_DOWN:
3240           return TRUE;
3241     }
3242     return FALSE;
3243 }
3244 
3245 // determine if a key is a numpad key (distinguishes the numpad
3246 // arrow keys from the non-numpad arrow keys, for example).
3247 BOOL AwtComponent::IsNumPadKey(UINT vkey, BOOL extended)
3248 {
3249     // Note: scancodes are the same for the numpad arrow keys and
3250     // the non-numpad arrow keys (also for PageUp, etc.).
3251     // The scancodes for the numpad divide and the non-numpad slash
3252     // are the same, but the wparams are different
3253 
3254     DTRACE_PRINTLN3("AwtComponent::IsNumPadKey  vkey = %d = 0x%x  extended = %d",
3255       vkey, vkey, extended);
3256 
3257     switch (vkey) {
3258       case VK_CLEAR:  // numpad 5 with numlock off
3259       case VK_NUMPAD0:
3260       case VK_NUMPAD1:
3261       case VK_NUMPAD2:
3262       case VK_NUMPAD3:
3263       case VK_NUMPAD4:
3264       case VK_NUMPAD5:
3265       case VK_NUMPAD6:
3266       case VK_NUMPAD7:
3267       case VK_NUMPAD8:
3268       case VK_NUMPAD9:
3269       case VK_MULTIPLY:
3270       case VK_ADD:
3271       case VK_SEPARATOR:  // numpad ,  not on US kbds
3272       case VK_SUBTRACT:
3273       case VK_DECIMAL:
3274       case VK_DIVIDE:
3275       case VK_NUMLOCK:
3276         return TRUE;
3277         break;
3278       case VK_END:
3279       case VK_PRIOR:  // PageUp
3280       case VK_NEXT:  // PageDown
3281       case VK_HOME:
3282       case VK_LEFT:
3283       case VK_UP:
3284       case VK_RIGHT:
3285       case VK_DOWN:
3286       case VK_INSERT:
3287       case VK_DELETE:
3288         // extended if non-numpad
3289         return (!extended);
3290         break;
3291       case VK_RETURN:  // extended if on numpad
3292         return (extended);
3293         break;
3294       default:
3295         break;
3296     }
3297 
3298     return FALSE;
3299 }
3300 static void
3301 resetKbdState( BYTE kstate[256]) {
3302     BYTE tmpState[256];
3303     WCHAR wc[2];
3304     memmove(tmpState, kstate, sizeof(kstate));
3305     tmpState[VK_SHIFT] = 0;
3306     tmpState[VK_CONTROL] = 0;
3307     tmpState[VK_MENU] = 0;
3308 
3309     ::ToUnicodeEx(VK_SPACE,::MapVirtualKey(VK_SPACE, 0), tmpState, wc, 2, 0,  GetKeyboardLayout(0));
3310 }
3311 
3312 // XXX in the update releases this is an addition to the unchanged existing code
3313 // After the call, a table will have a unicode associated with a windows virtual keycode
3314 // sans modifiers. With some further simplification, one can
3315 // derive java keycode from it, and anyway we will pass this unicode value
3316 // all the way up in a comment to a KeyEvent.
3317 void
3318 AwtComponent::BuildPrimaryDynamicTable() {
3319     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3320     // XXX: how about that?
3321     //CriticalSection::Lock l(GetLock());
3322     //if (GetPeer(env) == NULL) {
3323     //    /* event received during termination. */
3324     //    return;
3325     //}
3326 
3327     HKL hkl = GetKeyboardLayout();
3328     UINT sc = 0;
3329     BYTE kbdState[AwtToolkit::KB_STATE_SIZE];
3330     memset(kbdState, 0, sizeof (kbdState));
3331 
3332     // Use JNI call to obtain java key code. We should keep a list
3333     // of currently available keycodes in a single place.
3334     static jclass extKeyCodesCls;
3335     if( extKeyCodesCls == NULL) {
3336         jclass extKeyCodesClsLocal = env->FindClass("sun/awt/ExtendedKeyCodes");
3337         DASSERT(extKeyCodesClsLocal);
3338         CHECK_NULL(extKeyCodesClsLocal);
3339         extKeyCodesCls = (jclass)env->NewGlobalRef(extKeyCodesClsLocal);
3340         env->DeleteLocalRef(extKeyCodesClsLocal);
3341     }
3342     static jmethodID getExtendedKeyCodeForChar;
3343     if (getExtendedKeyCodeForChar == NULL) {
3344         getExtendedKeyCodeForChar =
3345                   env->GetStaticMethodID(extKeyCodesCls, "getExtendedKeyCodeForChar", "(I)I");
3346         DASSERT(getExtendedKeyCodeForChar);
3347         CHECK_NULL(getExtendedKeyCodeForChar);
3348     }
3349     jint extJKC; //extended Java key code
3350 
3351     for (UINT i = 0; i < 256; i++) {
3352         dynPrimaryKeymap[i].wkey = i;
3353         dynPrimaryKeymap[i].jkey = java_awt_event_KeyEvent_VK_UNDEFINED;
3354         dynPrimaryKeymap[i].unicode = 0;
3355 
3356         if ((sc = MapVirtualKey (i, 0)) == 0) {
3357             dynPrimaryKeymap[i].scancode = 0;
3358             continue;
3359         }
3360         dynPrimaryKeymap[i].scancode = sc;
3361 
3362         // XXX process cases like VK_SHIFT etc.
3363         kbdState[i] = 0x80; // "key pressed".
3364         WCHAR wc[16];
3365         int k = ::ToUnicodeEx(i, sc, kbdState, wc, 16, 0, hkl);
3366         if (k == 1) {
3367             // unicode
3368             dynPrimaryKeymap[i].unicode = wc[0];
3369             if (dynPrimaryKeymap[i].jkey == java_awt_event_KeyEvent_VK_UNDEFINED) {
3370             // Convert unicode to java keycode.
3371                 //dynPrimaryKeymap[i].jkey = ((UINT)(wc[0]) + 0x01000000);
3372                 //
3373                 //XXX If this key in on the keypad, we should force a special value equal to
3374                 //XXX an old java keycode: but how to say if it is a keypad key?
3375                 //XXX We'll do it in WmKeyUp/Down.
3376                 extJKC = env->CallStaticIntMethod(extKeyCodesCls,
3377                                                   getExtendedKeyCodeForChar, (jint)(wc[0]));
3378                 dynPrimaryKeymap[i].jkey = extJKC;
3379             }
3380         }else if (k == -1) {
3381             // dead key: use charToDeadVKTable
3382             dynPrimaryKeymap[i].unicode = wc[0];
3383             resetKbdState( kbdState );
3384             for (const CharToVKEntry *map = charToDeadVKTable;  map->c != 0;  ++map) {
3385                 if (wc[0] == map->c) {
3386                     dynPrimaryKeymap[i].jkey = map->javaKey;
3387                     break;
3388                 }
3389             }
3390         } else if (k == 0) {
3391             // reset
3392             resetKbdState( kbdState );
3393         }else {
3394             // k > 1: this key does generate multiple characters. Ignore it.
3395             // An example: Arabic Lam and Alef ligature.
3396             // There will be no extended keycode and thus shortcuts for this  key.
3397             // XXX shouldn't we reset the kbd state?
3398 #ifdef DEBUG
3399             DTRACE_PRINTLN2("wkey 0x%02X (%d)", i,i);
3400 #endif
3401         }
3402         kbdState[i] = 0; // "key unpressed"
3403     }
3404 }
3405 void
3406 AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers)
3407 {
3408     if( wkey && wkey < 256 ) {
3409         if(keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD) {
3410             // At the creation time,
3411             // dynPrimaryKeymap cannot distinguish between e.g. "/" and "NumPad /"
3412             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3413         }
3414         if(dynPrimaryKeymap[wkey].jkey ==  java_awt_event_KeyEvent_VK_UNDEFINED) {
3415             // E.g. it is non-unicode key
3416             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3417         }
3418     }
3419 }
3420 
3421 UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, BOOL &isDeadKey)
3422 {
3423     static Hashtable transTable("VKEY translations");
3424     static Hashtable deadKeyFlagTable("Dead Key Flags");
3425     isDeadKey = FALSE;
3426 
3427     // Try to translate using last saved translation
3428     if (ops == LOAD) {
3429        void* deadKeyFlag = deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3430        void* value = transTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3431        if (value != NULL) {
3432            isDeadKey = static_cast<BOOL>(reinterpret_cast<INT_PTR>(deadKeyFlag));
3433            return static_cast<UINT>(reinterpret_cast<INT_PTR>(value));
3434        }
3435     }
3436 
3437     // If the windows key is a return, wkey will equal 13 ('\r')
3438     // In this case, we want to return 10 ('\n')
3439     // Since ToAscii would convert VK_RETURN to '\r', we need
3440     // to have a special case here.
3441     if (wkey == VK_RETURN)
3442         return '\n';
3443 
3444     // high order bit in keyboardState indicates whether the key is down
3445     static const BYTE KEY_STATE_DOWN = 0x80;
3446     BYTE    keyboardState[AwtToolkit::KB_STATE_SIZE];
3447     AwtToolkit::GetKeyboardState(keyboardState);
3448 
3449     // apply modifiers to keyboard state if necessary
3450     BOOL shiftIsDown = FALSE;
3451     if (modifiers) {
3452         shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK;
3453         BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK;
3454         BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK;
3455 
3456         // Windows treats AltGr as Ctrl+Alt
3457         if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
3458             altIsDown = TRUE;
3459             ctrlIsDown = TRUE;
3460         }
3461 
3462         if (shiftIsDown) {
3463             keyboardState[VK_SHIFT] |= KEY_STATE_DOWN;
3464         }
3465 
3466         // fix for 4623376,4737679,4501485,4740906,4708221 (4173679/4122715)
3467         // Here we try to resolve a conflict with ::ToAsciiEx's translating
3468         // ALT+number key combinations. kdm@sarc.spb.su
3469         // yan: Do it for navigation keys only, otherwise some AltGr deadkeys fail.
3470         if( IsNavigationKey(wkey) ) {
3471             keyboardState[VK_MENU] &= ~KEY_STATE_DOWN;
3472         }
3473 
3474         if (ctrlIsDown)
3475         {
3476             if (altIsDown) {
3477                 // bugid 4215009: don't mess with AltGr == Ctrl + Alt
3478                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3479             }
3480             else {
3481                 // bugid 4098210: old event model doesn't have KEY_TYPED
3482                 // events, so try to provide a meaningful character for
3483                 // Ctrl+<key>.  Take Ctrl into account only when we know
3484                 // that Ctrl+<key> will be an ASCII control.  Ignore by
3485                 // default.
3486                 keyboardState[VK_CONTROL] &= ~KEY_STATE_DOWN;
3487 
3488                 // Letters have Ctrl+<letter> counterparts.  According to
3489                 // <winuser.h> VK_A through VK_Z are the same as ASCII
3490                 // 'A' through 'Z'.
3491                 if (wkey >= 'A' && wkey <= 'Z') {
3492                     keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3493                 }
3494                 else {
3495                     // Non-letter controls 033 to 037 are:
3496                     // ^[ (ESC), ^\ (FS), ^] (GS), ^^ (RS), and ^_ (US)
3497 
3498                     // Shift state bits returned by ::VkKeyScan in HIBYTE
3499                     static const UINT _VKS_SHIFT_MASK = 0x01;
3500                     static const UINT _VKS_CTRL_MASK = 0x02;
3501                     static const UINT _VKS_ALT_MASK = 0x04;
3502 
3503                     // Check to see whether there is a meaningful translation
3504                     TCHAR ch;
3505                     short vk;
3506                     for (ch = _T('\033'); ch < _T('\040'); ch++) {
3507                         vk = ::VkKeyScan(ch);
3508                         if (wkey == LOBYTE(vk)) {
3509                             UINT shiftState = HIBYTE(vk);
3510                             if ((shiftState & _VKS_CTRL_MASK) ||
3511                                 (!(shiftState & _VKS_SHIFT_MASK)
3512                                 == !shiftIsDown))
3513                             {
3514                                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3515                             }
3516                             break;
3517                         }
3518                     }
3519                 }
3520             } // ctrlIsDown && altIsDown
3521         } // ctrlIsDown
3522     } // modifiers
3523 
3524     WORD wChar[2];
3525     int converted = 1;
3526     UINT ch = ::MapVirtualKey(wkey, 2);
3527     if (ch & 0x80000000) {
3528         // Dead key which is handled as a normal key
3529         isDeadKey = deadKeyActive = TRUE;
3530     } else if (deadKeyActive) {
3531         // We cannot use ::ToUnicodeEx if dead key is active because this will
3532         // break dead key function
3533         wChar[0] = shiftIsDown ? ch : tolower(ch);
3534     } else {
3535         UINT scancode = ::MapVirtualKey(wkey, 0);
3536         converted = ::ToUnicodeEx(wkey, scancode, keyboardState,
3537                                               wChar, 2, 0, GetKeyboardLayout());
3538     }
3539 
3540     UINT translation;
3541     BOOL deadKeyFlag = (converted == 2);
3542 
3543     // Dead Key
3544     if (converted < 0 || isDeadKey) {
3545         translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3546     } else
3547     // No translation available -- try known conversions or else punt.
3548     if (converted == 0) {
3549         if (wkey == VK_DELETE) {
3550             translation = '\177';
3551         } else
3552         if (wkey >= VK_NUMPAD0 && wkey <= VK_NUMPAD9) {
3553             translation = '0' + wkey - VK_NUMPAD0;
3554         } else {
3555             translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3556         }
3557     } else
3558     // the caller expects a Unicode character.
3559     if (converted > 0) {
3560         translation = wChar[0];
3561     }
3562     if (ops == SAVE) {
3563         transTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3564                        reinterpret_cast<void*>(static_cast<INT_PTR>(translation)));
3565         if (deadKeyFlag) {
3566             deadKeyFlagTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3567                          reinterpret_cast<void*>(static_cast<INT_PTR>(deadKeyFlag)));
3568         } else {
3569             deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3570         }
3571     }
3572 
3573     isDeadKey = deadKeyFlag;
3574     return translation;
3575 }
3576 
3577 MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt,
3578                                    UINT flags, BOOL system)
3579 {
3580     // VK_PROCESSKEY is a special value which means
3581     //          "Current IME wants to consume this KeyEvent"
3582     // Real key code is saved by IMM32.DLL and can be retrieved by
3583     // calling ImmGetVirtualKey();
3584     if (wkey == VK_PROCESSKEY) {
3585         return mrDoDefault;
3586     }
3587     MSG msg;
3588     InitMessage(&msg, (system ? WM_SYSKEYDOWN : WM_KEYDOWN),
3589                              wkey, MAKELPARAM(repCnt, flags));
3590 
3591     UINT modifiers = GetJavaModifiers();
3592     jint keyLocation = GetKeyLocation(wkey, flags);
3593     BOOL isDeadKey = FALSE;
3594     UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE, isDeadKey);
3595     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3596     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3597 
3598 
3599     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
3600                              ::JVM_CurrentTimeMillis(NULL, 0), jkey, character,
3601                              modifiers, keyLocation, (jlong)wkey, &msg);
3602 
3603     // bugid 4724007: Windows does not create a WM_CHAR for the Del key
3604     // for some reason, so we need to create the KEY_TYPED event on the
3605     // WM_KEYDOWN.  Use null msg so the character doesn't get sent back
3606     // to the native window for processing (this event is synthesized
3607     // for Java - we don't want Windows trying to process it).
3608     if (jkey == java_awt_event_KeyEvent_VK_DELETE) {
3609         SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3610                                  ::JVM_CurrentTimeMillis(NULL, 0),
3611                                  java_awt_event_KeyEvent_VK_UNDEFINED,
3612                                  character, modifiers,
3613                                  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
3614     }
3615 
3616     return mrConsume;
3617 }
3618 
3619 MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt,
3620                                  UINT flags, BOOL system)
3621 {
3622 
3623     // VK_PROCESSKEY is a special value which means
3624     //          "Current IME wants to consume this KeyEvent"
3625     // Real key code is saved by IMM32.DLL and can be retrieved by
3626     // calling ImmGetVirtualKey();
3627     if (wkey == VK_PROCESSKEY) {
3628         return mrDoDefault;
3629     }
3630     MSG msg;
3631     InitMessage(&msg, (system ? WM_SYSKEYUP : WM_KEYUP),
3632                              wkey, MAKELPARAM(repCnt, flags));
3633 
3634     UINT modifiers = GetJavaModifiers();
3635     jint keyLocation = GetKeyLocation(wkey, flags);
3636     BOOL isDeadKey = FALSE;
3637     UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD, isDeadKey);
3638     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3639     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3640 
3641     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
3642                              ::JVM_CurrentTimeMillis(NULL, 0), jkey, character,
3643                              modifiers, keyLocation, (jlong)wkey, &msg);
3644     return mrConsume;
3645 }
3646 
3647 MsgRouting AwtComponent::WmInputLangChange(UINT charset, HKL hKeyboardLayout)
3648 {
3649     // Normally we would be able to use charset and TranslateCharSetInfo
3650     // to get a code page that should be associated with this keyboard
3651     // layout change. However, there seems to be an NT 4.0 bug associated
3652     // with the WM_INPUTLANGCHANGE message, which makes the charset parameter
3653     // unreliable, especially on Asian systems. Our workaround uses the
3654     // keyboard layout handle instead.
3655     m_hkl = hKeyboardLayout;
3656     m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID
3657     m_CodePage = LangToCodePage(m_idLang);
3658     BuildDynamicKeyMapTable();  // compute new mappings for VK_OEM
3659     BuildPrimaryDynamicTable();
3660     return mrConsume;           // do not propagate to children
3661 }
3662 
3663 // Convert Language ID to CodePage
3664 UINT AwtComponent::LangToCodePage(LANGID idLang)
3665 {
3666     TCHAR strCodePage[MAX_ACP_STR_LEN];
3667     // use the LANGID to create a LCID
3668     LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
3669     // get the ANSI code page associated with this locale
3670     if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE, strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
3671         return _ttoi(strCodePage);
3672     else
3673         return GetACP();
3674 }
3675 
3676 
3677 MsgRouting AwtComponent::WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL system)
3678 {
3679     // We will simply create Java events here.
3680     WCHAR unicodeChar = character;
3681     MSG msg;
3682     InitMessage(&msg, WM_IME_CHAR, character,
3683                               MAKELPARAM(repCnt, flags));
3684 
3685     jint modifiers = GetJavaModifiers();
3686     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3687                              ::JVM_CurrentTimeMillis(NULL, 0),
3688                              java_awt_event_KeyEvent_VK_UNDEFINED,
3689                              unicodeChar, modifiers,
3690                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
3691                              &msg);
3692     return mrConsume;
3693 }
3694 
3695 MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags,
3696                                 BOOL system)
3697 {
3698     deadKeyActive = FALSE;
3699 
3700     // Will only get WmChar messages with DBCS if we create them for
3701     // an Edit class in the WmForwardChar method. These synthesized
3702     // DBCS chars are ok to pass on directly to the default window
3703     // procedure. They've already been filtered through the Java key
3704     // event queue. We will never get the trail byte since the edit
3705     // class will PeekMessage(&msg, hwnd, WM_CHAR, WM_CHAR,
3706     // PM_REMOVE).  I would like to be able to pass this character off
3707     // via WM_AWT_FORWARD_BYTE, but the Edit classes don't seem to
3708     // like that.
3709 
3710     // We will simply create Java events here.
3711     UINT message = system ? WM_SYSCHAR : WM_CHAR;
3712 
3713     // The Alt modifier is reported in the 29th bit of the lParam,
3714     // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
3715     bool alt_is_down = (flags & (1<<13)) != 0;
3716 
3717     // Fix for bug 4141621, corrected by fix for bug 6223726: Alt+space doesn't invoke system menu
3718     // We should not pass this particular combination to Java.
3719 
3720     if (system && alt_is_down) {
3721         if (character == VK_SPACE) {
3722             return mrDoDefault;
3723         }
3724     }
3725 
3726     // If this is a WM_CHAR (non-system) message, then the Alt flag
3727     // indicates that the character was typed using an AltGr key
3728     // (which Windows treats as Ctrl+Alt), so in this case we do NOT
3729     // pass the Ctrl and Alt modifiers to Java, but instead we
3730     // replace them with Java's AltGraph modifier.  Note: the AltGraph
3731     // modifier does not exist in 1.1.x releases.
3732     jint modifiers = GetJavaModifiers();
3733     if (!system && alt_is_down) {
3734         // character typed with AltGraph
3735         modifiers &= ~(java_awt_event_InputEvent_ALT_DOWN_MASK
3736                        | java_awt_event_InputEvent_CTRL_DOWN_MASK);
3737         modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK;
3738     }
3739 
3740     WCHAR unicodeChar = character;
3741 
3742     // Kludge: Combine pending single byte with this char for some Chinese IMEs
3743     if (m_PendingLeadByte != 0) {
3744         character = (m_PendingLeadByte & 0x00ff) | (character << 8);
3745         m_PendingLeadByte = 0;
3746         ::MultiByteToWideChar(GetCodePage(), 0, (CHAR*)&character, 2,
3747                           &unicodeChar, 1);
3748     }
3749 
3750     if (unicodeChar == VK_RETURN) {
3751         // Enter key generates \r in windows, but \n is required in java
3752         unicodeChar = java_awt_event_KeyEvent_VK_ENTER;
3753     }
3754     MSG msg;
3755     InitMessage(&msg, message, character,
3756                               MAKELPARAM(repCnt, flags));
3757     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3758                              ::JVM_CurrentTimeMillis(NULL, 0),
3759                              java_awt_event_KeyEvent_VK_UNDEFINED,
3760                              unicodeChar, modifiers,
3761                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
3762                              &msg);
3763     return mrConsume;
3764 }
3765 
3766 MsgRouting AwtComponent::WmForwardChar(WCHAR character, LPARAM lParam,
3767                                        BOOL synthetic)
3768 {
3769     // just post WM_CHAR with unicode key value
3770     DefWindowProc(WM_CHAR, (WPARAM)character, lParam);
3771     return mrConsume;
3772 }
3773 
3774 MsgRouting AwtComponent::WmPaste()
3775 {
3776     return mrDoDefault;
3777 }
3778 
3779 // support IME Composition messages
3780 void AwtComponent::SetCompositionWindow(RECT& r)
3781 {
3782     HWND hwnd = ImmGetHWnd();
3783     HIMC hIMC = ImmGetContext(hwnd);
3784     if (hIMC == NULL) {
3785         return;
3786     }
3787     COMPOSITIONFORM cf = {CFS_DEFAULT, {0, 0}, {0, 0, 0, 0}};
3788     ImmSetCompositionWindow(hIMC, &cf);
3789     ImmReleaseContext(hwnd, hIMC);
3790 }
3791 
3792 void AwtComponent::OpenCandidateWindow(int x, int y)
3793 {
3794     UINT bits = 1;
3795     POINT p = {0, 0}; // upper left corner of the client area
3796     HWND hWnd = GetHWnd();
3797     HWND hTop = GetTopLevelParentForWindow(hWnd);
3798     ::ClientToScreen(hTop, &p);
3799     if (!m_bitsCandType) {
3800         SetCandidateWindow(m_bitsCandType, x - p.x, y - p.y);
3801         return;
3802     }
3803     for (int iCandType=0; iCandType<32; iCandType++, bits<<=1) {
3804         if ( m_bitsCandType & bits )
3805             SetCandidateWindow(iCandType, x - p.x, y - p.y);
3806     }
3807     if (m_bitsCandType != 0) {
3808         // REMIND: is there any chance GetProxyFocusOwner() returns NULL here?
3809         ::DefWindowProc(ImmGetHWnd(),
3810                         WM_IME_NOTIFY, IMN_OPENCANDIDATE, m_bitsCandType);
3811     }
3812 }
3813 
3814 void AwtComponent::SetCandidateWindow(int iCandType, int x, int y)
3815 {
3816     HWND hwnd = ImmGetHWnd();
3817     HIMC hIMC = ImmGetContext(hwnd);
3818     CANDIDATEFORM cf;
3819     cf.dwIndex = iCandType;
3820     cf.dwStyle = CFS_POINT;
3821     cf.ptCurrentPos.x = x;
3822     cf.ptCurrentPos.y = y;
3823 
3824     ImmSetCandidateWindow(hIMC, &cf);
3825     ImmReleaseContext(hwnd, hIMC);
3826 }
3827 
3828 MsgRouting AwtComponent::WmImeSetContext(BOOL fSet, LPARAM *lplParam)
3829 {
3830     // If the Windows input context is disabled, do not let Windows
3831     // display any UIs.
3832     HWND hwnd = ImmGetHWnd();
3833     HIMC hIMC = ImmGetContext(hwnd);
3834     if (hIMC == NULL) {
3835         *lplParam = 0;
3836         return mrDoDefault;
3837     }
3838     ImmReleaseContext(hwnd, hIMC);
3839 
3840     if (fSet) {
3841         LPARAM lParam = *lplParam;
3842         if (!m_useNativeCompWindow) {
3843             // stop to draw native composing window.
3844             *lplParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
3845         }
3846     }
3847     return mrDoDefault;
3848 }
3849 
3850 MsgRouting AwtComponent::WmImeNotify(WPARAM subMsg, LPARAM bitsCandType)
3851 {
3852     if (!m_useNativeCompWindow) {
3853         if (subMsg == IMN_OPENCANDIDATE) {
3854             m_bitsCandType = subMsg;
3855             InquireCandidatePosition();
3856         } else if (subMsg == IMN_OPENSTATUSWINDOW ||
3857                    subMsg == WM_IME_STARTCOMPOSITION) {
3858             m_bitsCandType = 0;
3859             InquireCandidatePosition();
3860         }
3861         return mrConsume;
3862     }
3863     return mrDoDefault;
3864 }
3865 
3866 MsgRouting AwtComponent::WmImeStartComposition()
3867 {
3868     if (m_useNativeCompWindow) {
3869         RECT rc;
3870         ::GetClientRect(GetHWnd(), &rc);
3871         SetCompositionWindow(rc);
3872         return mrDoDefault;
3873     } else
3874         return mrConsume;
3875 }
3876 
3877 MsgRouting AwtComponent::WmImeEndComposition()
3878 {
3879     if (m_useNativeCompWindow)   return mrDoDefault;
3880 
3881     SendInputMethodEvent(
3882         java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3883         NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0 );
3884     return mrConsume;
3885 }
3886 
3887 MsgRouting AwtComponent::WmImeComposition(WORD wChar, LPARAM flags)
3888 {
3889     if (m_useNativeCompWindow)   return mrDoDefault;
3890 
3891     int*      bndClauseW = NULL;
3892     jstring*  readingClauseW = NULL;
3893     int*      bndAttrW = NULL;
3894     BYTE*     valAttrW = NULL;
3895     int       cClauseW = 0;
3896     AwtInputTextInfor* textInfor = NULL;
3897 
3898     try {
3899         HWND hwnd = ImmGetHWnd();
3900         HIMC hIMC = ImmGetContext(hwnd);
3901         DASSERT(hIMC!=0);
3902 
3903         textInfor = new AwtInputTextInfor;
3904         textInfor->GetContextData(hIMC, flags);
3905         ImmReleaseContext(hwnd, hIMC);
3906 
3907         jstring jtextString = textInfor->GetText();
3908         /* The conditions to send the input method event to AWT EDT are:
3909            1. Whenever there is a composition message sent regarding whether
3910            the composition text is NULL or not. See details at bug 6222692.
3911            2. When there is a committed message sent, in which case, we have to
3912            check whether the committed string is NULL or not. If the committed string
3913            is NULL, there is no need to send any input method event.
3914            (Minor note: 'jtextString' returned is the merged string in the case of
3915            partial commit.)
3916         */
3917         if ((flags & GCS_RESULTSTR && jtextString != NULL) ||
3918             (flags & GCS_COMPSTR)) {
3919             int       cursorPosW = textInfor->GetCursorPosition();
3920             // In order not to delete the readingClauseW in the catch clause,
3921             // calling GetAttributeInfor before GetClauseInfor.
3922             int       cAttrW = textInfor->GetAttributeInfor(bndAttrW, valAttrW);
3923             cClauseW = textInfor->GetClauseInfor(bndClauseW, readingClauseW);
3924 
3925             /* Send INPUT_METHOD_TEXT_CHANGED event to the WInputMethod which in turn sends
3926                the event to AWT EDT.
3927 
3928                The last two paremeters are set to equal since we don't have recommendations for
3929                the visible position within the current composed text. See details at
3930                java.awt.event.InputMethodEvent.
3931             */
3932             SendInputMethodEvent(java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3933                                  jtextString,
3934                                  cClauseW, bndClauseW, readingClauseW,
3935                                  cAttrW, bndAttrW, valAttrW,
3936                                  textInfor->GetCommittedTextLength(),
3937                                  cursorPosW, cursorPosW);
3938         }
3939     } catch (...) {
3940         // since GetClauseInfor and GetAttributeInfor could throw exception, we have to release
3941         // the pointer here.
3942         delete [] bndClauseW;
3943         delete [] readingClauseW;
3944         delete [] bndAttrW;
3945         delete [] valAttrW;
3946         throw;
3947     }
3948 
3949     /* Free the storage allocated. Since jtextString won't be passed from threads
3950      *  to threads, we just use the local ref and it will be deleted within the destructor
3951      *  of AwtInputTextInfor object.
3952      */
3953     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3954     if (cClauseW && readingClauseW) {
3955         for (int i = 0; i < cClauseW; i ++) {
3956             if (readingClauseW[i]) {
3957                 env->DeleteLocalRef(readingClauseW[i]);
3958             }
3959         }
3960     }
3961     delete [] bndClauseW;
3962     delete [] readingClauseW;
3963     delete [] bndAttrW;
3964     delete [] valAttrW;
3965     delete textInfor;
3966 
3967     return mrConsume;
3968 }
3969 
3970 //
3971 // generate and post InputMethodEvent
3972 //
3973 void AwtComponent::SendInputMethodEvent(jint id, jstring text,
3974                                         int cClause, int* rgClauseBoundary, jstring* rgClauseReading,
3975                                         int cAttrBlock, int* rgAttrBoundary, BYTE *rgAttrValue,
3976                                         int commitedTextLength, int caretPos, int visiblePos)
3977 {
3978     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3979 
3980     // assumption for array type casting
3981     DASSERT(sizeof(int)==sizeof(jint));
3982     DASSERT(sizeof(BYTE)==sizeof(jbyte));
3983 
3984     // caluse information
3985     jintArray clauseBoundary = NULL;
3986     jobjectArray clauseReading = NULL;
3987     if (cClause && rgClauseBoundary && rgClauseReading) {
3988         // convert clause boundary offset array to java array
3989         clauseBoundary = env->NewIntArray(cClause+1);
3990         DASSERT(clauseBoundary);
3991         CHECK_NULL(clauseBoundary);
3992         env->SetIntArrayRegion(clauseBoundary, 0, cClause+1, (jint *)rgClauseBoundary);
3993         DASSERT(!safe_ExceptionOccurred(env));
3994 
3995         // convert clause reading string array to java array
3996         jclass stringCls = JNU_ClassString(env);
3997         DASSERT(stringCls);
3998         CHECK_NULL(stringCls);
3999         clauseReading = env->NewObjectArray(cClause, stringCls, NULL);
4000         DASSERT(clauseReading);
4001         CHECK_NULL(clauseReading);
4002         for (int i=0; i<cClause; i++)   env->SetObjectArrayElement(clauseReading, i, rgClauseReading[i]);
4003         DASSERT(!safe_ExceptionOccurred(env));
4004     }
4005 
4006 
4007     // attrubute value definition in WInputMethod.java must be equal to that in IMM.H
4008     DASSERT(ATTR_INPUT==sun_awt_windows_WInputMethod_ATTR_INPUT);
4009     DASSERT(ATTR_TARGET_CONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_CONVERTED);
4010     DASSERT(ATTR_CONVERTED==sun_awt_windows_WInputMethod_ATTR_CONVERTED);
4011     DASSERT(ATTR_TARGET_NOTCONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_NOTCONVERTED);
4012     DASSERT(ATTR_INPUT_ERROR==sun_awt_windows_WInputMethod_ATTR_INPUT_ERROR);
4013 
4014     // attribute information
4015     jintArray attrBoundary = NULL;
4016     jbyteArray attrValue = NULL;
4017     if (cAttrBlock && rgAttrBoundary && rgAttrValue) {
4018         // convert attribute boundary offset array to java array
4019         attrBoundary = env->NewIntArray(cAttrBlock+1);
4020         DASSERT(attrBoundary);
4021         CHECK_NULL(attrBoundary);
4022         env->SetIntArrayRegion(attrBoundary, 0, cAttrBlock+1, (jint *)rgAttrBoundary);
4023         DASSERT(!safe_ExceptionOccurred(env));
4024 
4025         // convert attribute value byte array to java array
4026         attrValue = env->NewByteArray(cAttrBlock);
4027         DASSERT(attrValue);
4028         CHECK_NULL(attrValue);
4029         env->SetByteArrayRegion(attrValue, 0, cAttrBlock, (jbyte *)rgAttrValue);
4030         DASSERT(!safe_ExceptionOccurred(env));
4031     }
4032 
4033 
4034     // get global reference of WInputMethod class (run only once)
4035     static jclass wInputMethodCls = NULL;
4036     if (wInputMethodCls == NULL) {
4037         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
4038         DASSERT(wInputMethodClsLocal);
4039         CHECK_NULL(wInputMethodClsLocal);
4040         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
4041         env->DeleteLocalRef(wInputMethodClsLocal);
4042     }
4043 
4044     // get method ID of sendInputMethodEvent() (run only once)
4045     static jmethodID sendIMEventMid = 0;
4046     if (sendIMEventMid == 0) {
4047         sendIMEventMid =  env->GetMethodID(wInputMethodCls, "sendInputMethodEvent",
4048                                            "(IJLjava/lang/String;[I[Ljava/lang/String;[I[BIII)V");
4049         DASSERT(sendIMEventMid);
4050         CHECK_NULL(sendIMEventMid);
4051     }
4052 
4053     // call m_InputMethod.sendInputMethod()
4054     env->CallVoidMethod(m_InputMethod, sendIMEventMid, id, ::JVM_CurrentTimeMillis(NULL, 0),
4055                         text, clauseBoundary, clauseReading, attrBoundary,
4056                         attrValue, commitedTextLength, caretPos, visiblePos);
4057     if (safe_ExceptionOccurred(env))   env->ExceptionDescribe();
4058     DASSERT(!safe_ExceptionOccurred(env));
4059 
4060 }
4061 
4062 
4063 
4064 //
4065 // Inquires candidate position according to the composed text
4066 //
4067 void AwtComponent::InquireCandidatePosition()
4068 {
4069     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4070 
4071     // get global reference of WInputMethod class (run only once)
4072     static jclass wInputMethodCls = NULL;
4073     if (wInputMethodCls == NULL) {
4074         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
4075         DASSERT(wInputMethodClsLocal);
4076         CHECK_NULL(wInputMethodClsLocal);
4077         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
4078         env->DeleteLocalRef(wInputMethodClsLocal);
4079     }
4080 
4081     // get method ID of sendInputMethodEvent() (run only once)
4082     static jmethodID inqCandPosMid = 0;
4083     if (inqCandPosMid == 0) {
4084         inqCandPosMid =  env->GetMethodID(wInputMethodCls, "inquireCandidatePosition", "()V");
4085         DASSERT(!safe_ExceptionOccurred(env));
4086         DASSERT(inqCandPosMid);
4087         CHECK_NULL(inqCandPosMid);
4088     }
4089 
4090     // call m_InputMethod.sendInputMethod()
4091     jobject candPos = env->CallObjectMethod(m_InputMethod, inqCandPosMid);
4092     DASSERT(!safe_ExceptionOccurred(env));
4093 }
4094 
4095 HWND AwtComponent::ImmGetHWnd()
4096 {
4097     HWND proxy = GetProxyFocusOwner();
4098     return (proxy != NULL) ? proxy : GetHWnd();
4099 }
4100 
4101 HIMC AwtComponent::ImmAssociateContext(HIMC himc)
4102 {
4103     return ::ImmAssociateContext(ImmGetHWnd(), himc);
4104 }
4105 
4106 HWND AwtComponent::GetProxyFocusOwner()
4107 {
4108     AwtWindow *window = GetContainer();
4109     if (window != 0) {
4110         AwtFrame *owner = window->GetOwningFrameOrDialog();
4111         if (owner != 0) {
4112             return owner->GetProxyFocusOwner();
4113         } else if (!window->IsSimpleWindow()) { // isn't an owned simple window
4114             return ((AwtFrame*)window)->GetProxyFocusOwner();
4115         }
4116     }
4117     return (HWND)NULL;
4118 }
4119 
4120 /* Redirects message to the focus proxy, if any */
4121 void AwtComponent::CallProxyDefWindowProc(UINT message, WPARAM wParam,
4122     LPARAM lParam, LRESULT &retVal, MsgRouting &mr)
4123 {
4124     if (mr != mrConsume)  {
4125         HWND proxy = GetProxyFocusOwner();
4126         if (proxy != NULL && ::IsWindowEnabled(proxy)) {
4127             retVal = ::DefWindowProc(proxy, message, wParam, lParam);
4128             mr = mrConsume;
4129         }
4130     }
4131 }
4132 
4133 MsgRouting AwtComponent::WmCommand(UINT id, HWND hWndChild, UINT notifyCode)
4134 {
4135     /* Menu/Accelerator */
4136     if (hWndChild == 0) {
4137         AwtObject* obj = AwtToolkit::GetInstance().LookupCmdID(id);
4138         if (obj == NULL) {
4139             return mrConsume;
4140         }
4141         DASSERT(((AwtMenuItem*)obj)->GetID() == id);
4142         obj->DoCommand();
4143         return mrConsume;
4144     }
4145     /* Child id notification */
4146     else {
4147         AwtComponent* child = AwtComponent::GetComponent(hWndChild);
4148         if (child) {
4149             child->WmNotify(notifyCode);
4150         }
4151     }
4152     return mrDoDefault;
4153 }
4154 
4155 MsgRouting AwtComponent::WmNotify(UINT notifyCode)
4156 {
4157     return mrDoDefault;
4158 }
4159 
4160 MsgRouting AwtComponent::WmCompareItem(UINT ctrlId,
4161                                        COMPAREITEMSTRUCT &compareInfo,
4162                                        LRESULT &result)
4163 {
4164     AwtComponent* child = AwtComponent::GetComponent(compareInfo.hwndItem);
4165     if (child == this) {
4166         /* DoCallback("handleItemDelete", */
4167     }
4168     else if (child) {
4169         return child->WmCompareItem(ctrlId, compareInfo, result);
4170     }
4171     return mrConsume;
4172 }
4173 
4174 MsgRouting AwtComponent::WmDeleteItem(UINT ctrlId,
4175                                       DELETEITEMSTRUCT &deleteInfo)
4176 {
4177     /*
4178      * Workaround for NT 4.0 bug -- if SetWindowPos is called on a AwtList
4179      * window, a WM_DELETEITEM message is sent to its parent with a window
4180      * handle of one of the list's child windows.  The property lookup
4181      * succeeds, but the HWNDs don't match.
4182      */
4183     if (deleteInfo.hwndItem == NULL) {
4184         return mrConsume;
4185     }
4186     AwtComponent* child = (AwtComponent *)AwtComponent::GetComponent(deleteInfo.hwndItem);
4187 
4188     if (child && child->GetHWnd() != deleteInfo.hwndItem) {
4189         return mrConsume;
4190     }
4191 
4192     if (child == this) {
4193         /*DoCallback("handleItemDelete", */
4194     }
4195     else if (child) {
4196         return child->WmDeleteItem(ctrlId, deleteInfo);
4197     }
4198     return mrConsume;
4199 }
4200 
4201 MsgRouting AwtComponent::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT &drawInfo)
4202 {
4203     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4204 
4205     if (drawInfo.CtlType == ODT_MENU) {
4206         if (drawInfo.itemData != 0) {
4207             AwtMenu* menu = (AwtMenu*)(drawInfo.itemData);
4208             menu->DrawItem(drawInfo);
4209         }
4210     } else {
4211         return OwnerDrawItem(ctrlId, drawInfo);
4212     }
4213     return mrConsume;
4214 }
4215 
4216 MsgRouting AwtComponent::WmMeasureItem(UINT ctrlId,
4217                                        MEASUREITEMSTRUCT &measureInfo)
4218 {
4219     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4220 
4221     if (measureInfo.CtlType == ODT_MENU) {
4222         if (measureInfo.itemData != 0) {
4223             AwtMenu* menu = (AwtMenu*)(measureInfo.itemData);
4224             HDC hDC = ::GetDC(GetHWnd());
4225             /* menu->MeasureItem(env, hDC, measureInfo); */
4226             menu->MeasureItem(hDC, measureInfo);
4227             ::ReleaseDC(GetHWnd(), hDC);
4228         }
4229     } else {
4230         return OwnerMeasureItem(ctrlId, measureInfo);
4231     }
4232     return mrConsume;
4233 }
4234 
4235 MsgRouting AwtComponent::OwnerDrawItem(UINT ctrlId,
4236     DRAWITEMSTRUCT &drawInfo)
4237 {
4238     AwtComponent* child = AwtComponent::GetComponent(drawInfo.hwndItem);
4239     if (child == this) {
4240         /* DoCallback("handleItemDelete", */
4241     } else if (child != NULL) {
4242         return child->WmDrawItem(ctrlId, drawInfo);
4243     }
4244     return mrConsume;
4245 }
4246 
4247 MsgRouting AwtComponent::OwnerMeasureItem(UINT ctrlId,
4248     MEASUREITEMSTRUCT &measureInfo)
4249 {
4250     HWND  hChild = ::GetDlgItem(GetHWnd(), measureInfo.CtlID);
4251     AwtComponent* child = AwtComponent::GetComponent(hChild);
4252     /*
4253      * If the parent cannot find the child's instance from its handle,
4254      * maybe the child is in its creation.  So the child must be searched
4255      * from the list linked before the child's creation.
4256      */
4257     if (child == NULL) {
4258         child = SearchChild((UINT)ctrlId);
4259     }
4260 
4261     if (child == this) {
4262     /* DoCallback("handleItemDelete",  */
4263     }
4264     else if (child) {
4265         return child->WmMeasureItem(ctrlId, measureInfo);
4266     }
4267     return mrConsume;
4268 }
4269 
4270 /* for WmDrawItem method of Label, Button and Checkbox */
4271 void AwtComponent::DrawWindowText(HDC hDC, jobject font, jstring text,
4272                                   int x, int y)
4273 {
4274     int nOldBkMode = ::SetBkMode(hDC,TRANSPARENT);
4275     DASSERT(nOldBkMode != 0);
4276     AwtFont::drawMFString(hDC, font, text, x, y, GetCodePage());
4277     VERIFY(::SetBkMode(hDC,nOldBkMode));
4278 }
4279 
4280 /*
4281  * Draw text in gray (the color being set to COLOR_GRAYTEXT) when the
4282  * component is disabled.  Used only for label, checkbox and button in
4283  * OWNER_DRAW.  It draws the text in emboss.
4284  */
4285 void AwtComponent::DrawGrayText(HDC hDC, jobject font, jstring text,
4286                                 int x, int y)
4287 {
4288     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHILIGHT));
4289     AwtComponent::DrawWindowText(hDC, font, text, x+1, y+1);
4290     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
4291     AwtComponent::DrawWindowText(hDC, font, text, x, y);
4292 }
4293 
4294 /* for WmMeasureItem method of List and Choice */
4295 jstring AwtComponent::GetItemString(JNIEnv *env, jobject target, jint index)
4296 {
4297     jstring str = (jstring)JNU_CallMethodByName(env, NULL, target, "getItemImpl",
4298                                                 "(I)Ljava/lang/String;",
4299                                                 index).l;
4300     DASSERT(!safe_ExceptionOccurred(env));
4301     return str;
4302 }
4303 
4304 /* for WmMeasureItem method of List and Choice */
4305 void AwtComponent::MeasureListItem(JNIEnv *env,
4306                                    MEASUREITEMSTRUCT &measureInfo)
4307 {
4308     if (env->EnsureLocalCapacity(1) < 0) {
4309         return;
4310     }
4311     jobject dimension = PreferredItemSize(env);
4312     DASSERT(dimension);
4313     measureInfo.itemWidth =
4314       env->GetIntField(dimension, AwtDimension::widthID);
4315     measureInfo.itemHeight =
4316       env->GetIntField(dimension, AwtDimension::heightID);
4317     env->DeleteLocalRef(dimension);
4318 }
4319 
4320 /* for WmDrawItem method of List and Choice */
4321 void AwtComponent::DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo)
4322 {
4323     if (env->EnsureLocalCapacity(3) < 0) {
4324         return;
4325     }
4326     jobject peer = GetPeer(env);
4327     jobject target = env->GetObjectField(peer, AwtObject::targetID);
4328 
4329     HDC hDC = drawInfo.hDC;
4330     RECT rect = drawInfo.rcItem;
4331 
4332     BOOL bEnabled = isEnabled();
4333     BOOL unfocusableChoice = (drawInfo.itemState & ODS_COMBOBOXEDIT) && !IsFocusable();
4334     DWORD crBack, crText;
4335     if (drawInfo.itemState & ODS_SELECTED){
4336         /* Set background and text colors for selected item */
4337         crBack = ::GetSysColor (COLOR_HIGHLIGHT);
4338         crText = ::GetSysColor (COLOR_HIGHLIGHTTEXT);
4339     } else {
4340         /* Set background and text colors for unselected item */
4341         crBack = GetBackgroundColor();
4342         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4343     }
4344     if (unfocusableChoice) {
4345         //6190728. Shouldn't draw selection field (edit control) of an owner-drawn combo box.
4346         crBack = GetBackgroundColor();
4347         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4348     }
4349 
4350     /* Fill item rectangle with background color */
4351     HBRUSH hbrBack = ::CreateSolidBrush (crBack);
4352     DASSERT(hbrBack);
4353     /* 6190728. Shouldn't draw any kind of rectangle around selection field
4354      * (edit control) of an owner-drawn combo box while unfocusable
4355      */
4356     if (!unfocusableChoice){
4357         VERIFY(::FillRect (hDC, &rect, hbrBack));
4358     }
4359     VERIFY(::DeleteObject (hbrBack));
4360 
4361     /* Set current background and text colors */
4362     ::SetBkColor (hDC, crBack);
4363     ::SetTextColor (hDC, crText);
4364 
4365     /*draw string (with left margin of 1 point) */
4366     if ((int) (drawInfo.itemID) >= 0) {
4367             jobject font = GET_FONT(target, peer);
4368             jstring text = GetItemString(env, target, drawInfo.itemID);
4369             if (env->ExceptionCheck()) {
4370                 env->DeleteLocalRef(font);
4371                 env->DeleteLocalRef(target);
4372                 return;
4373             }
4374             SIZE size = AwtFont::getMFStringSize(hDC, font, text);
4375             AwtFont::drawMFString(hDC, font, text,
4376                                   (GetRTL()) ? rect.right - size.cx - 1
4377                                              : rect.left + 1,
4378                                   (rect.top + rect.bottom - size.cy) / 2,
4379                                   GetCodePage());
4380             env->DeleteLocalRef(font);
4381             env->DeleteLocalRef(text);
4382     }
4383     if ((drawInfo.itemState & ODS_FOCUS)  &&
4384         (drawInfo.itemAction & (ODA_FOCUS | ODA_DRAWENTIRE))) {
4385       if (!unfocusableChoice){
4386           if(::DrawFocusRect(hDC, &rect) == 0)
4387               VERIFY(::GetLastError() == 0);
4388       }
4389     }
4390     env->DeleteLocalRef(target);
4391 }
4392 
4393 /* for MeasureListItem method and WmDrawItem method of Checkbox */
4394 jint AwtComponent::GetFontHeight(JNIEnv *env)
4395 {
4396     if (env->EnsureLocalCapacity(4) < 0) {
4397         return NULL;
4398     }
4399     jobject self = GetPeer(env);
4400     jobject target = env->GetObjectField(self, AwtObject::targetID);
4401 
4402     jobject font = GET_FONT(target, self);
4403     jobject toolkit = env->CallObjectMethod(target,
4404                                             AwtComponent::getToolkitMID);
4405 
4406     DASSERT(!safe_ExceptionOccurred(env));
4407 
4408     jobject fontMetrics =
4409         env->CallObjectMethod(toolkit, AwtToolkit::getFontMetricsMID, font);
4410 
4411     DASSERT(!safe_ExceptionOccurred(env));
4412 
4413     jint height = env->CallIntMethod(fontMetrics, AwtFont::getHeightMID);
4414     DASSERT(!safe_ExceptionOccurred(env));
4415 
4416     env->DeleteLocalRef(target);
4417     env->DeleteLocalRef(font);
4418     env->DeleteLocalRef(toolkit);
4419     env->DeleteLocalRef(fontMetrics);
4420 
4421     return height;
4422 }
4423 
4424 // If you override WmPrint, make sure to save a copy of the DC on the GDI
4425 // stack to be restored in WmPrintClient. Windows mangles the DC in
4426 // ::DefWindowProc.
4427 MsgRouting AwtComponent::WmPrint(HDC hDC, LPARAM flags)
4428 {
4429     /*
4430      * DefWindowProc for WM_PRINT changes DC parameters, so we have
4431      * to restore it ourselves. Otherwise it will cause problems
4432      * when several components are printed to the same DC.
4433      */
4434     int nOriginalDC = ::SaveDC(hDC);
4435     DASSERT(nOriginalDC != 0);
4436 
4437     if (flags & PRF_NONCLIENT) {
4438 
4439         VERIFY(::SaveDC(hDC));
4440 
4441         DefWindowProc(WM_PRINT, (WPARAM)hDC,
4442                       (flags & (PRF_NONCLIENT
4443                                 | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4444 
4445         VERIFY(::RestoreDC(hDC, -1));
4446 
4447         // Special case for components with a sunken border. Windows does not
4448         // print the border correctly on PCL printers, so we have to do it ourselves.
4449         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4450             RECT r;
4451             VERIFY(::GetWindowRect(GetHWnd(), &r));
4452             VERIFY(::OffsetRect(&r, -r.left, -r.top));
4453             VERIFY(::DrawEdge(hDC, &r, EDGE_SUNKEN, BF_RECT));
4454         }
4455     }
4456 
4457     if (flags & PRF_CLIENT) {
4458 
4459         /*
4460          * Special case for components with a sunken border.
4461          * Windows prints a client area without offset to a border width.
4462          * We will first print the non-client area with the original offset,
4463          * then the client area with a corrected offset.
4464          */
4465         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4466 
4467             int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE);
4468             int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE);
4469 
4470             VERIFY(::OffsetWindowOrgEx(hDC, -nEdgeWidth, -nEdgeHeight, NULL));
4471 
4472             // Save a copy of the DC for WmPrintClient
4473             VERIFY(::SaveDC(hDC));
4474 
4475             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4476                           (flags & (PRF_CLIENT
4477                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4478 
4479             VERIFY(::OffsetWindowOrgEx(hDC, nEdgeWidth, nEdgeHeight, NULL));
4480 
4481         } else {
4482 
4483             // Save a copy of the DC for WmPrintClient
4484             VERIFY(::SaveDC(hDC));
4485             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4486                           (flags & (PRF_CLIENT
4487                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4488         }
4489     }
4490 
4491     if (flags & (PRF_CHILDREN | PRF_OWNED)) {
4492         DefWindowProc(WM_PRINT, (WPARAM) hDC,
4493                       (flags & ~PRF_CLIENT & ~PRF_NONCLIENT));
4494     }
4495 
4496     VERIFY(::RestoreDC(hDC, nOriginalDC));
4497 
4498     return mrConsume;
4499 }
4500 
4501 // If you override WmPrintClient, make sure to obtain a valid copy of
4502 // the DC from the GDI stack. The copy of the DC should have been placed
4503 // there by WmPrint. Windows mangles the DC in ::DefWindowProc.
4504 MsgRouting AwtComponent::WmPrintClient(HDC hDC, LPARAM)
4505 {
4506     // obtain valid DC from GDI stack
4507     ::RestoreDC(hDC, -1);
4508 
4509     return mrDoDefault;
4510 }
4511 
4512 MsgRouting AwtComponent::WmNcCalcSize(BOOL fCalcValidRects,
4513                                       LPNCCALCSIZE_PARAMS lpncsp,
4514                                       LRESULT &retVal)
4515 {
4516     return mrDoDefault;
4517 }
4518 
4519 MsgRouting AwtComponent::WmNcPaint(HRGN hrgn)
4520 {
4521     return mrDoDefault;
4522 }
4523 
4524 MsgRouting AwtComponent::WmNcHitTest(UINT x, UINT y, LRESULT &retVal)
4525 {
4526     return mrDoDefault;
4527 }
4528 
4529 /**
4530  * WmQueryNewPalette is called whenever our component is coming to
4531  * the foreground; this gives us an opportunity to install our
4532  * custom palette.  If this install actually changes entries in
4533  * the system palette, then we get a further call to WmPaletteChanged
4534  * (but note that we only need to realize our palette once).
4535  */
4536 MsgRouting AwtComponent::WmQueryNewPalette(LRESULT &retVal)
4537 {
4538     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4539     m_QueryNewPaletteCalled = TRUE;
4540     HDC hDC = ::GetDC(GetHWnd());
4541     DASSERT(hDC);
4542     AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4543     AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4544     ::ReleaseDC(GetHWnd(), hDC);
4545     // We must realize the palettes of all of our DC's
4546     // There is sometimes a problem where the realization of
4547     // our temporary hDC here does not actually do what
4548     // we want.  Not clear why, but presumably fallout from
4549     // our use of several simultaneous hDC's.
4550     activeDCList.RealizePalettes(screen);
4551     // Do not invalidate here; if the palette
4552     // has not changed we will get an extra repaint
4553     retVal = TRUE;
4554 
4555     return mrDoDefault;
4556 }
4557 
4558 /**
4559  * We should not need to track this event since we handle our
4560  * palette management effectively in the WmQueryNewPalette and
4561  * WmPaletteChanged methods.  However, there seems to be a bug
4562  * on some win32 systems (e.g., NT4) whereby the palette
4563  * immediately after a displayChange is not yet updated to its
4564  * final post-display-change values (hence we adjust our palette
4565  * using the wrong system palette entries), then the palette is
4566  * updated, but a WM_PALETTECHANGED message is never sent.
4567  * By tracking the ISCHANGING message as well (and by tracking
4568  * displayChange events in the AwtToolkit object), we can account
4569  * for this error by forcing our WmPaletteChanged method to be
4570  * called and thereby realizing our logical palette and updating
4571  * our dynamic colorModel object.
4572  */
4573 MsgRouting AwtComponent::WmPaletteIsChanging(HWND hwndPalChg)
4574 {
4575     if (AwtToolkit::GetInstance().HasDisplayChanged()) {
4576         WmPaletteChanged(hwndPalChg);
4577         AwtToolkit::GetInstance().ResetDisplayChanged();
4578     }
4579     return mrDoDefault;
4580 }
4581 
4582 MsgRouting AwtComponent::WmPaletteChanged(HWND hwndPalChg)
4583 {
4584     // We need to re-realize our palette here (unless we're the one
4585     // that was realizing it in the first place).  That will let us match the
4586     // remaining colors in the system palette as best we can.  We always
4587     // invalidate because the palette will have changed when we receive this
4588     // message.
4589 
4590     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4591     if (hwndPalChg != GetHWnd()) {
4592         HDC hDC = ::GetDC(GetHWnd());
4593         DASSERT(hDC);
4594         AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4595         AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4596         ::ReleaseDC(GetHWnd(), hDC);
4597         // We must realize the palettes of all of our DC's
4598         activeDCList.RealizePalettes(screen);
4599     }
4600     if (AwtWin32GraphicsDevice::UpdateSystemPalette(screen)) {
4601         AwtWin32GraphicsDevice::UpdateDynamicColorModel(screen);
4602     }
4603     Invalidate(NULL);
4604     return mrDoDefault;
4605 }
4606 
4607 MsgRouting AwtComponent::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss)
4608 {
4609     DASSERT(!IsBadReadPtr(lpss, sizeof(STYLESTRUCT)));
4610     return mrDoDefault;
4611 }
4612 
4613 MsgRouting AwtComponent::WmSettingChange(UINT wFlag, LPCTSTR pszSection)
4614 {
4615     DASSERT(!IsBadStringPtr(pszSection, 20));
4616     DTRACE_PRINTLN2("WM_SETTINGCHANGE: wFlag=%d pszSection=%s", (int)wFlag, pszSection);
4617     return mrDoDefault;
4618 }
4619 
4620 HDC AwtComponent::GetDCFromComponent()
4621 {
4622     GetDCReturnStruct *hdcStruct =
4623         (GetDCReturnStruct*)SendMessage(WM_AWT_GETDC);
4624     HDC hdc;
4625     if (hdcStruct) {
4626         if (hdcStruct->gdiLimitReached) {
4627             if (jvm != NULL) {
4628                 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4629                 if (env != NULL && !safe_ExceptionOccurred(env)) {
4630                     JNU_ThrowByName(env, "java/awt/AWTError",
4631                         "HDC creation failure - " \
4632                         "exceeded maximum GDI resources");
4633                 }
4634             }
4635         }
4636         hdc = hdcStruct->hDC;
4637         delete hdcStruct;
4638     } else {
4639         hdc = NULL;
4640     }
4641     return hdc;
4642 }
4643 
4644 void AwtComponent::FillBackground(HDC hMemoryDC, SIZE &size)
4645 {
4646     RECT eraseR = { 0, 0, size.cx, size.cy };
4647     VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush()));
4648 }
4649 
4650 void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
4651 {
4652     if (!bitmapBits) {
4653         return;
4654     }
4655 
4656     DWORD* dest = (DWORD*)bitmapBits;
4657     //XXX: might be optimized to use one loop (cy*cx -> 0)
4658     for (int i = 0; i < size.cy; i++ ) {
4659         for (int j = 0; j < size.cx; j++ ) {
4660             ((BYTE*)(dest++))[3] = alpha;
4661         }
4662     }
4663 }
4664 
4665 int AwtComponent::ScaleUpX(int x) {
4666     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4667     Devices::InstanceAccess devices;
4668     AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
4669     return device == NULL ? x : device->ScaleUpX(x);
4670 }
4671 
4672 int AwtComponent::ScaleUpY(int y) {
4673     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4674     Devices::InstanceAccess devices;
4675     AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
4676     return device == NULL ? y : device->ScaleUpY(y);
4677 }
4678 
4679 int AwtComponent::ScaleDownX(int x) {
4680     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4681     Devices::InstanceAccess devices;
4682     AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
4683     return device == NULL ? x : device->ScaleDownX(x);
4684 }
4685 
4686 int AwtComponent::ScaleDownY(int y) {
4687     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4688     Devices::InstanceAccess devices;
4689     AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
4690     return device == NULL ? y : device->ScaleDownY(y);
4691 }
4692 
4693 jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
4694     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4695 
4696     if (!::IsWindowVisible(GetHWnd())) {
4697         return NULL;
4698     }
4699 
4700     HDC hdc = GetDCFromComponent();
4701     if (!hdc) {
4702         return NULL;
4703     }
4704     HDC hMemoryDC = ::CreateCompatibleDC(hdc);
4705     void *bitmapBits = NULL;
4706     HBITMAP hBitmap = BitmapUtil::CreateARGBBitmap(size.cx, size.cy, &bitmapBits);
4707     HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemoryDC, hBitmap);
4708     SendMessage(WM_AWT_RELEASEDC, (WPARAM)hdc);
4709 
4710     FillBackground(hMemoryDC, size);
4711 
4712     VERIFY(::SetWindowOrgEx(hMemoryDC, loc.cx, loc.cy, NULL));
4713 
4714     // Don't bother with PRF_CHECKVISIBLE because we called IsWindowVisible
4715     // above.
4716     SendMessage(WM_PRINT, (WPARAM)hMemoryDC, PRF_CLIENT | PRF_NONCLIENT);
4717 
4718     // First make sure the system completed any drawing to the bitmap.
4719     ::GdiFlush();
4720 
4721     // WM_PRINT does not fill the alpha-channel of the ARGB bitmap
4722     // leaving it equal to zero. Hence we need to fill it manually. Otherwise
4723     // the pixels will be considered transparent when interpreting the data.
4724     FillAlpha(bitmapBits, size, alpha);
4725 
4726     ::SelectObject(hMemoryDC, hOldBitmap);
4727 
4728     BITMAPINFO bmi;
4729     memset(&bmi, 0, sizeof(BITMAPINFO));
4730     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
4731     bmi.bmiHeader.biWidth = size.cx;
4732     bmi.bmiHeader.biHeight = -size.cy;
4733     bmi.bmiHeader.biPlanes = 1;
4734     bmi.bmiHeader.biBitCount = 32;
4735     bmi.bmiHeader.biCompression = BI_RGB;
4736 
4737     jobject localPixelArray = env->NewIntArray(size.cx * size.cy);
4738     jintArray pixelArray = NULL;
4739     if (localPixelArray != NULL) {
4740         pixelArray = (jintArray)env->NewGlobalRef(localPixelArray);
4741         env->DeleteLocalRef(localPixelArray); localPixelArray = NULL;
4742 
4743         jboolean isCopy;
4744         jint *pixels = env->GetIntArrayElements(pixelArray, &isCopy);
4745 
4746         ::GetDIBits(hMemoryDC, hBitmap, 0, size.cy, (LPVOID)pixels, &bmi,
4747                     DIB_RGB_COLORS);
4748 
4749         env->ReleaseIntArrayElements(pixelArray, pixels, 0);
4750     }
4751 
4752     VERIFY(::DeleteObject(hBitmap));
4753     VERIFY(::DeleteDC(hMemoryDC));
4754 
4755     return pixelArray;
4756 }
4757 
4758 void* AwtComponent::SetNativeFocusOwner(void *self) {
4759     if (self == NULL) {
4760         // It means that the KFM wants to set focus to null
4761         sm_focusOwner = NULL;
4762         return NULL;
4763     }
4764 
4765     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4766 
4767     AwtComponent *c = NULL;
4768     jobject peer = (jobject)self;
4769 
4770     PDATA pData;
4771     JNI_CHECK_NULL_GOTO(peer, "peer", ret);
4772     pData = JNI_GET_PDATA(peer);
4773     if (pData == NULL) {
4774         goto ret;
4775     }
4776     c = (AwtComponent *)pData;
4777 
4778 ret:
4779     if (c && ::IsWindow(c->GetHWnd())) {
4780         sm_focusOwner = c->GetHWnd();
4781     } else {
4782         sm_focusOwner = NULL;
4783     }
4784     env->DeleteGlobalRef(peer);
4785     return NULL;
4786 }
4787 
4788 void* AwtComponent::GetNativeFocusedWindow() {
4789     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4790     AwtComponent *comp =
4791         AwtComponent::GetComponent(AwtComponent::GetFocusedWindow());
4792     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4793 }
4794 
4795 void* AwtComponent::GetNativeFocusOwner() {
4796     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4797     AwtComponent *comp =
4798         AwtComponent::GetComponent(AwtComponent::sm_focusOwner);
4799     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4800 }
4801 
4802 AwtComponent* AwtComponent::SearchChild(UINT id) {
4803     ChildListItem* child;
4804     for (child = m_childList; child != NULL;child = child->m_next) {
4805         if (child->m_ID == id)
4806             return child->m_Component;
4807     }
4808     /*
4809      * DASSERT(FALSE);
4810      * This should not be happend if all children are recorded
4811      */
4812     return NULL;        /* make compiler happy */
4813 }
4814 
4815 void AwtComponent::RemoveChild(UINT id) {
4816     ChildListItem* child = m_childList;
4817     ChildListItem* lastChild = NULL;
4818     while (child != NULL) {
4819         if (child->m_ID == id) {
4820             if (lastChild == NULL) {
4821                 m_childList = child->m_next;
4822             } else {
4823                 lastChild->m_next = child->m_next;
4824             }
4825             child->m_next = NULL;
4826             DASSERT(child != NULL);
4827             delete child;
4828             return;
4829         }
4830         lastChild = child;
4831         child = child->m_next;
4832     }
4833 }
4834 
4835 void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked,
4836                                 jint modifiers, jint keyLocation, jlong nativeCode, MSG *pMsg)
4837 {
4838     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4839     CriticalSection::Lock l(GetLock());
4840     if (GetPeer(env) == NULL) {
4841         /* event received during termination. */
4842         return;
4843     }
4844 
4845     static jclass keyEventCls;
4846     if (keyEventCls == NULL) {
4847         jclass keyEventClsLocal = env->FindClass("java/awt/event/KeyEvent");
4848         DASSERT(keyEventClsLocal);
4849         if (keyEventClsLocal == NULL) {
4850             /* exception already thrown */
4851             return;
4852         }
4853         keyEventCls = (jclass)env->NewGlobalRef(keyEventClsLocal);
4854         env->DeleteLocalRef(keyEventClsLocal);
4855     }
4856 
4857     static jmethodID keyEventConst;
4858     if (keyEventConst == NULL) {
4859         keyEventConst =  env->GetMethodID(keyEventCls, "<init>",
4860                                           "(Ljava/awt/Component;IJIICI)V");
4861         DASSERT(keyEventConst);
4862         CHECK_NULL(keyEventConst);
4863     }
4864     if (env->EnsureLocalCapacity(2) < 0) {
4865         return;
4866     }
4867     jobject target = GetTarget(env);
4868     jobject keyEvent = env->NewObject(keyEventCls, keyEventConst, target,
4869                                       id, when, modifiers, raw, cooked,
4870                                       keyLocation);
4871     if (safe_ExceptionOccurred(env)) env->ExceptionDescribe();
4872     DASSERT(!safe_ExceptionOccurred(env));
4873     DASSERT(keyEvent != NULL);
4874     if (keyEvent == NULL) {
4875         env->DeleteLocalRef(target);
4876         return;
4877     }
4878     env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode);
4879     if( nativeCode && nativeCode < 256 ) {
4880         env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode));
4881         env->SetLongField(keyEvent, AwtKeyEvent::extendedKeyCodeID, (jlong)(dynPrimaryKeymap[nativeCode].jkey));
4882         if( nativeCode < 255 ) {
4883             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(dynPrimaryKeymap[nativeCode].scancode));
4884         }else if( pMsg != NULL ) {
4885             // unknown key with virtual keycode 0xFF.
4886             // Its scancode is not in the table, pickup it from the message.
4887             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(HIWORD(pMsg->lParam) & 0xFF));
4888         }
4889     }
4890     if (pMsg != NULL) {
4891         AwtAWTEvent::saveMSG(env, pMsg, keyEvent);
4892     }
4893     SendEvent(keyEvent);
4894 
4895     env->DeleteLocalRef(keyEvent);
4896     env->DeleteLocalRef(target);
4897 }
4898 
4899 void
4900 AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when,
4901                                        jint raw, jint cooked,
4902                                        jint modifiers, jint keyLocation,
4903                                        jlong nativeCode,
4904                                        MSG *msg)
4905 {
4906     /*
4907      * if focus owner is null, but focused window isn't
4908      * we will send key event to focused window
4909      */
4910     HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : AwtComponent::GetFocusedWindow());
4911 
4912     if (hwndTarget == GetHWnd()) {
4913         SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, nativeCode, msg);
4914     } else {
4915         AwtComponent *target = NULL;
4916         if (hwndTarget != NULL) {
4917             target = AwtComponent::GetComponent(hwndTarget);
4918             if (target == NULL) {
4919                 target = this;
4920             }
4921         }
4922         if (target != NULL) {
4923             target->SendKeyEvent(id, when, raw, cooked, modifiers,
4924               keyLocation, nativeCode, msg);
4925         }
4926     }
4927 }
4928 
4929 void AwtComponent::SetDragCapture(UINT flags)
4930 {
4931     // don't want to interfere with other controls
4932     if (::GetCapture() == NULL) {
4933         ::SetCapture(GetHWnd());
4934     }
4935 }
4936 
4937 void AwtComponent::ReleaseDragCapture(UINT flags)
4938 {
4939     if ((::GetCapture() == GetHWnd()) && ((flags & ALL_MK_BUTTONS) == 0)) {
4940         // user has released all buttons, so release the capture
4941         ::ReleaseCapture();
4942     }
4943 }
4944 
4945 void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y,
4946                                   jint modifiers, jint clickCount,
4947                                   jboolean popupTrigger, jint button,
4948                                   MSG *pMsg)
4949 {
4950     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4951     CriticalSection::Lock l(GetLock());
4952     if (GetPeer(env) == NULL) {
4953         /* event received during termination. */
4954         return;
4955     }
4956 
4957     static jclass mouseEventCls;
4958     if (mouseEventCls == NULL) {
4959         jclass mouseEventClsLocal =
4960             env->FindClass("java/awt/event/MouseEvent");
4961         CHECK_NULL(mouseEventClsLocal);
4962         mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal);
4963         env->DeleteLocalRef(mouseEventClsLocal);
4964     }
4965     RECT insets;
4966     GetInsets(&insets);
4967 
4968     static jmethodID mouseEventConst;
4969     if (mouseEventConst == NULL) {
4970         mouseEventConst =
4971             env->GetMethodID(mouseEventCls, "<init>",
4972                  "(Ljava/awt/Component;IJIIIIIIZI)V");
4973         DASSERT(mouseEventConst);
4974         CHECK_NULL(mouseEventConst);
4975     }
4976     if (env->EnsureLocalCapacity(2) < 0) {
4977         return;
4978     }
4979     jobject target = GetTarget(env);
4980     DWORD curMousePos = ::GetMessagePos();
4981     int xAbs = GET_X_LPARAM(curMousePos);
4982     int yAbs = GET_Y_LPARAM(curMousePos);
4983     jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
4984                                         target,
4985                                         id, when, modifiers,
4986                                         ScaleDownX(x + insets.left),
4987                                         ScaleDownY(y + insets.top),
4988                                         ScaleDownX(xAbs), ScaleDownY(yAbs),
4989                                         clickCount, popupTrigger, button);
4990 
4991     if (safe_ExceptionOccurred(env)) {
4992         env->ExceptionDescribe();
4993         env->ExceptionClear();
4994     }
4995 
4996     DASSERT(mouseEvent != NULL);
4997     CHECK_NULL(mouseEvent);
4998     if (pMsg != 0) {
4999         AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
5000     }
5001     SendEvent(mouseEvent);
5002 
5003     env->DeleteLocalRef(mouseEvent);
5004     env->DeleteLocalRef(target);
5005 }
5006 
5007 void
5008 AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
5009                                   jint modifiers, jint clickCount,
5010                                   jboolean popupTrigger, jint scrollType,
5011                                   jint scrollAmount, jint roundedWheelRotation,
5012                                   jdouble preciseWheelRotation, MSG *pMsg)
5013 {
5014     /* Code based not so loosely on AwtComponent::SendMouseEvent */
5015     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5016     CriticalSection::Lock l(GetLock());
5017     if (GetPeer(env) == NULL) {
5018         /* event received during termination. */
5019         return;
5020     }
5021 
5022     static jclass mouseWheelEventCls;
5023     if (mouseWheelEventCls == NULL) {
5024         jclass mouseWheelEventClsLocal =
5025             env->FindClass("java/awt/event/MouseWheelEvent");
5026         CHECK_NULL(mouseWheelEventClsLocal);
5027         mouseWheelEventCls = (jclass)env->NewGlobalRef(mouseWheelEventClsLocal);
5028         env->DeleteLocalRef(mouseWheelEventClsLocal);
5029     }
5030     RECT insets;
5031     GetInsets(&insets);
5032 
5033     static jmethodID mouseWheelEventConst;
5034     if (mouseWheelEventConst == NULL) {
5035         mouseWheelEventConst =
5036             env->GetMethodID(mouseWheelEventCls, "<init>",
5037                            "(Ljava/awt/Component;IJIIIIIIZIIID)V");
5038         DASSERT(mouseWheelEventConst);
5039         CHECK_NULL(mouseWheelEventConst);
5040     }
5041     if (env->EnsureLocalCapacity(2) < 0) {
5042         return;
5043     }
5044     jobject target = GetTarget(env);
5045     DWORD curMousePos = ::GetMessagePos();
5046     int xAbs = GET_X_LPARAM(curMousePos);
5047     int yAbs = GET_Y_LPARAM(curMousePos);
5048 
5049     DTRACE_PRINTLN("creating MWE in JNI");
5050 
5051     jobject mouseWheelEvent = env->NewObject(mouseWheelEventCls,
5052                                              mouseWheelEventConst,
5053                                              target,
5054                                              id, when, modifiers,
5055                                              ScaleDownX(x + insets.left),
5056                                              ScaleDownY(y + insets.top),
5057                                              ScaleDownX(xAbs),
5058                                              ScaleDownY(yAbs),
5059                                              clickCount, popupTrigger,
5060                                              scrollType, scrollAmount,
5061                                              roundedWheelRotation, preciseWheelRotation);
5062 
5063     DASSERT(mouseWheelEvent != NULL);
5064     if (mouseWheelEvent == NULL || safe_ExceptionOccurred(env)) {
5065         env->ExceptionDescribe();
5066         env->ExceptionClear();
5067         env->DeleteLocalRef(target);
5068         return;
5069     }
5070     if (pMsg != NULL) {
5071         AwtAWTEvent::saveMSG(env, pMsg, mouseWheelEvent);
5072     }
5073     SendEvent(mouseWheelEvent);
5074 
5075     env->DeleteLocalRef(mouseWheelEvent);
5076     env->DeleteLocalRef(target);
5077 }
5078 
5079 void AwtComponent::SendFocusEvent(jint id, HWND opposite)
5080 {
5081     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5082 
5083     CriticalSection::Lock l(GetLock());
5084     if (GetPeer(env) == NULL) {
5085         /* event received during termination. */
5086         return;
5087     }
5088 
5089     static jclass focusEventCls;
5090     if (focusEventCls == NULL) {
5091         jclass focusEventClsLocal
5092             = env->FindClass("java/awt/event/FocusEvent");
5093         DASSERT(focusEventClsLocal);
5094         CHECK_NULL(focusEventClsLocal);
5095         focusEventCls = (jclass)env->NewGlobalRef(focusEventClsLocal);
5096         env->DeleteLocalRef(focusEventClsLocal);
5097     }
5098 
5099     static jmethodID focusEventConst;
5100     if (focusEventConst == NULL) {
5101         focusEventConst =
5102             env->GetMethodID(focusEventCls, "<init>",
5103                              "(Ljava/awt/Component;IZLjava/awt/Component;)V");
5104         DASSERT(focusEventConst);
5105         CHECK_NULL(focusEventConst);
5106     }
5107 
5108     static jclass sequencedEventCls;
5109     if (sequencedEventCls == NULL) {
5110         jclass sequencedEventClsLocal =
5111             env->FindClass("java/awt/SequencedEvent");
5112         DASSERT(sequencedEventClsLocal);
5113         CHECK_NULL(sequencedEventClsLocal);
5114         sequencedEventCls =
5115             (jclass)env->NewGlobalRef(sequencedEventClsLocal);
5116         env->DeleteLocalRef(sequencedEventClsLocal);
5117     }
5118 
5119     static jmethodID sequencedEventConst;
5120     if (sequencedEventConst == NULL) {
5121         sequencedEventConst =
5122             env->GetMethodID(sequencedEventCls, "<init>",
5123                              "(Ljava/awt/AWTEvent;)V");
5124         DASSERT(sequencedEventConst);
5125         CHECK_NULL(sequencedEventConst);
5126     }
5127 
5128     if (env->EnsureLocalCapacity(3) < 0) {
5129         return;
5130     }
5131 
5132     jobject target = GetTarget(env);
5133     jobject jOpposite = NULL;
5134     if (opposite != NULL) {
5135         AwtComponent *awtOpposite = AwtComponent::GetComponent(opposite);
5136         if (awtOpposite != NULL) {
5137             jOpposite = awtOpposite->GetTarget(env);
5138         }
5139     }
5140     jobject focusEvent = env->NewObject(focusEventCls, focusEventConst,
5141                                         target, id, JNI_FALSE, jOpposite);
5142     DASSERT(!safe_ExceptionOccurred(env));
5143     DASSERT(focusEvent != NULL);
5144     if (jOpposite != NULL) {
5145         env->DeleteLocalRef(jOpposite); jOpposite = NULL;
5146     }
5147     env->DeleteLocalRef(target); target = NULL;
5148     CHECK_NULL(focusEvent);
5149 
5150     jobject sequencedEvent = env->NewObject(sequencedEventCls,
5151                                             sequencedEventConst,
5152                                             focusEvent);
5153     DASSERT(!safe_ExceptionOccurred(env));
5154     DASSERT(sequencedEvent != NULL);
5155     env->DeleteLocalRef(focusEvent); focusEvent = NULL;
5156     CHECK_NULL(sequencedEvent);
5157     SendEvent(sequencedEvent);
5158 
5159     env->DeleteLocalRef(sequencedEvent);
5160 }
5161 
5162 /*
5163  * Forward a filtered event directly to the subclassed window.
5164  * This method is needed so that DefWindowProc is invoked on the
5165  * component's owning thread.
5166  */
5167 MsgRouting AwtComponent::HandleEvent(MSG *msg, BOOL)
5168 {
5169     DefWindowProc(msg->message, msg->wParam, msg->lParam);
5170     delete msg;
5171     return mrConsume;
5172 }
5173 
5174 /* Post a WM_AWT_HANDLE_EVENT message which invokes HandleEvent
5175    on the toolkit thread. This method may pre-filter the messages. */
5176 BOOL AwtComponent::PostHandleEventMessage(MSG *msg, BOOL synthetic)
5177 {
5178     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5179     // We should cut off keyboard events to disabled components
5180     // to avoid the components responding visually to keystrokes when disabled.
5181     // we shouldn't cut off WM_SYS* messages as they aren't used for normal activity
5182     // but to activate menus, close windows, etc
5183     switch(msg->message) {
5184         case WM_KEYDOWN:
5185         case WM_KEYUP:
5186         case WM_CHAR:
5187         case WM_DEADCHAR:
5188             {
5189                 if (!isRecursivelyEnabled()) {
5190                     goto quit;
5191                 }
5192                 break;
5193             }
5194     }
5195     if (PostMessage(GetHWnd(), WM_AWT_HANDLE_EVENT,
5196         (WPARAM) synthetic, (LPARAM) msg)) {
5197             return TRUE;
5198     } else {
5199         JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5200     }
5201 quit:
5202     delete msg;
5203     return FALSE;
5204 }
5205 
5206 void AwtComponent::SynthesizeKeyMessage(JNIEnv *env, jobject keyEvent)
5207 {
5208     jint id = (env)->GetIntField(keyEvent, AwtAWTEvent::idID);
5209     UINT message;
5210     switch (id) {
5211       case java_awt_event_KeyEvent_KEY_PRESSED:
5212           message = WM_KEYDOWN;
5213           break;
5214       case java_awt_event_KeyEvent_KEY_RELEASED:
5215           message = WM_KEYUP;
5216           break;
5217       case java_awt_event_KeyEvent_KEY_TYPED:
5218           message = WM_CHAR;
5219           break;
5220       default:
5221           return;
5222     }
5223 
5224     /*
5225      * KeyEvent.modifiers aren't supported -- the Java apppwd must send separate
5226      * KEY_PRESSED and KEY_RELEASED events for the modifier virtual keys.
5227      */
5228     if (id == java_awt_event_KeyEvent_KEY_TYPED) {
5229         // WM_CHAR message must be posted using WM_AWT_FORWARD_CHAR
5230         // (for Edit control)
5231         jchar keyChar = (jchar)
5232           (env)->GetCharField(keyEvent, AwtKeyEvent::keyCharID);
5233 
5234         // Bugid 4724007.  If it is a Delete character, don't send the fake
5235         // KEY_TYPED we created back to the native window: Windows doesn't
5236         // expect a WM_CHAR for Delete in TextFields, so it tries to enter a
5237         // character after deleting.
5238         if (keyChar == '\177') { // the Delete character
5239             return;
5240         }
5241 
5242         // Disable forwarding WM_CHAR messages to disabled components
5243         if (isRecursivelyEnabled()) {
5244             if (!::PostMessage(GetHWnd(), WM_AWT_FORWARD_CHAR,
5245                 MAKEWPARAM(keyChar, TRUE), 0)) {
5246                 JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5247             }
5248         }
5249     } else {
5250         jint keyCode =
5251           (env)->GetIntField(keyEvent, AwtKeyEvent::keyCodeID);
5252         UINT key, modifiers;
5253         AwtComponent::JavaKeyToWindowsKey(keyCode, &key, &modifiers);
5254         MSG* msg = CreateMessage(message, key, 0);
5255         PostHandleEventMessage(msg, TRUE);
5256     }
5257 }
5258 
5259 void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent)
5260 {
5261     /*    DebugBreak(); */
5262     jint button = (env)->GetIntField(mouseEvent, AwtMouseEvent::buttonID);
5263     jint modifiers = (env)->GetIntField(mouseEvent, AwtInputEvent::modifiersID);
5264 
5265     WPARAM wParam = 0;
5266     WORD wLow = 0;
5267     jint wheelAmt = 0;
5268     jint id = (env)->GetIntField(mouseEvent, AwtAWTEvent::idID);
5269     UINT message;
5270     switch (id) {
5271       case java_awt_event_MouseEvent_MOUSE_PRESSED: {
5272           switch (button) {
5273             case java_awt_event_MouseEvent_BUTTON1:
5274                 message = WM_LBUTTONDOWN; break;
5275             case java_awt_event_MouseEvent_BUTTON3:
5276                 message = WM_MBUTTONDOWN; break;
5277             case java_awt_event_MouseEvent_BUTTON2:
5278                 message = WM_RBUTTONDOWN; break;
5279             default:
5280                 return;
5281           }
5282           break;
5283       }
5284       case java_awt_event_MouseEvent_MOUSE_RELEASED: {
5285           switch (button) {
5286             case java_awt_event_MouseEvent_BUTTON1:
5287                 message = WM_LBUTTONUP; break;
5288             case java_awt_event_MouseEvent_BUTTON3:
5289                 message = WM_MBUTTONUP; break;
5290             case java_awt_event_MouseEvent_BUTTON2:
5291                 message = WM_RBUTTONUP; break;
5292             default:
5293                 return;
5294           }
5295           break;
5296       }
5297       case java_awt_event_MouseEvent_MOUSE_MOVED:
5298           /* MOUSE_DRAGGED events must first have sent a MOUSE_PRESSED event. */
5299       case java_awt_event_MouseEvent_MOUSE_DRAGGED:
5300           message = WM_MOUSEMOVE;
5301           break;
5302       case java_awt_event_MouseEvent_MOUSE_WHEEL:
5303           if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
5304               wLow |= MK_CONTROL;
5305           }
5306           if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
5307               wLow |= MK_SHIFT;
5308           }
5309           if (modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
5310               wLow |= MK_LBUTTON;
5311           }
5312           if (modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) {
5313               wLow |= MK_RBUTTON;
5314           }
5315           if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) {
5316               wLow |= MK_MBUTTON;
5317           }
5318           if (modifiers & X1_BUTTON) {
5319               wLow |= GetButtonMK(X1_BUTTON);
5320           }
5321           if (modifiers & X2_BUTTON) {
5322               wLow |= GetButtonMK(X2_BUTTON);
5323           }
5324 
5325           wheelAmt = (jint)JNU_CallMethodByName(env,
5326                                                NULL,
5327                                                mouseEvent,
5328                                                "getWheelRotation",
5329                                                "()I").i;
5330           DASSERT(!safe_ExceptionOccurred(env));
5331           JNU_CHECK_EXCEPTION(env);
5332           DTRACE_PRINTLN1("wheelAmt = %i\n", wheelAmt);
5333 
5334           // convert Java wheel amount value to Win32
5335           wheelAmt *= -1 * WHEEL_DELTA;
5336 
5337           message = WM_MOUSEWHEEL;
5338           wParam = MAKEWPARAM(wLow, wheelAmt);
5339 
5340           break;
5341       default:
5342           return;
5343     }
5344     jint x = (env)->GetIntField(mouseEvent, AwtMouseEvent::xID);
5345     jint y = (env)->GetIntField(mouseEvent, AwtMouseEvent::yID);
5346     MSG* msg = CreateMessage(message, wParam, MAKELPARAM(x, y), x, y);
5347     PostHandleEventMessage(msg, TRUE);
5348 }
5349 
5350 BOOL AwtComponent::InheritsNativeMouseWheelBehavior() {return false;}
5351 
5352 void AwtComponent::Invalidate(RECT* r)
5353 {
5354     ::InvalidateRect(GetHWnd(), r, FALSE);
5355 }
5356 
5357 void AwtComponent::BeginValidate()
5358 {
5359     DASSERT(m_validationNestCount >= 0 &&
5360            m_validationNestCount < 1000); // sanity check
5361 
5362     if (m_validationNestCount == 0) {
5363     // begin deferred window positioning if we're not inside
5364     // another Begin/EndValidate pair
5365         DASSERT(m_hdwp == NULL);
5366         m_hdwp = ::BeginDeferWindowPos(32);
5367     }
5368 
5369     m_validationNestCount++;
5370 }
5371 
5372 void AwtComponent::EndValidate()
5373 {
5374     DASSERT(m_validationNestCount > 0 &&
5375            m_validationNestCount < 1000); // sanity check
5376     DASSERT(m_hdwp != NULL);
5377 
5378     m_validationNestCount--;
5379     if (m_validationNestCount == 0) {
5380     // if this call to EndValidate is not nested inside another
5381     // Begin/EndValidate pair, end deferred window positioning
5382         ::EndDeferWindowPos(m_hdwp);
5383         m_hdwp = NULL;
5384     }
5385 }
5386 
5387 /**
5388  * HWND, AwtComponent and Java Peer interaction
5389  */
5390 
5391 /*
5392  *Link the C++, Java peer, and HWNDs together.
5393  */
5394 void AwtComponent::LinkObjects(JNIEnv *env, jobject peer)
5395 {
5396     /*
5397      * Bind all three objects together thru this C++ object, two-way to each:
5398      *     JavaPeer <-> C++ <-> HWND
5399      *
5400      * C++ -> JavaPeer
5401      */
5402     if (m_peerObject == NULL) {
5403         // This may have already been set up by CreateHWnd
5404         // And we don't want to create two references so we
5405         // will leave the prior one alone
5406         m_peerObject = env->NewGlobalRef(peer);
5407     }
5408     /* JavaPeer -> HWND */
5409     env->SetLongField(peer, AwtComponent::hwndID, reinterpret_cast<jlong>(m_hwnd));
5410 
5411     /* JavaPeer -> C++ */
5412     JNI_SET_PDATA(peer, this);
5413 
5414     /* HWND -> C++ */
5415     SetComponentInHWND();
5416 }
5417 
5418 /* Cleanup above linking */
5419 void AwtComponent::UnlinkObjects()
5420 {
5421     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5422     if (m_peerObject) {
5423         env->SetLongField(m_peerObject, AwtComponent::hwndID, 0);
5424         JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL));
5425         JNI_SET_DESTROYED(m_peerObject);
5426         env->DeleteGlobalRef(m_peerObject);
5427         m_peerObject = NULL;
5428     }
5429 }
5430 
5431 void AwtComponent::Enable(BOOL bEnable)
5432 {
5433     if (bEnable && IsTopLevel()) {
5434         // we should not enable blocked toplevels
5435         bEnable = !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()));
5436     }
5437     // Shouldn't trigger native focus change
5438     // (only the proxy may be the native focus owner).
5439     ::EnableWindow(GetHWnd(), bEnable);
5440 
5441     CriticalSection::Lock l(GetLock());
5442     VerifyState();
5443 }
5444 
5445 /*
5446  * associate an AwtDropTarget with this AwtComponent
5447  */
5448 
5449 AwtDropTarget* AwtComponent::CreateDropTarget(JNIEnv* env) {
5450     m_dropTarget = new AwtDropTarget(env, this);
5451     m_dropTarget->RegisterTarget(TRUE);
5452     return m_dropTarget;
5453 }
5454 
5455 /*
5456  * disassociate an AwtDropTarget with this AwtComponent
5457  */
5458 
5459 void AwtComponent::DestroyDropTarget() {
5460     if (m_dropTarget != NULL) {
5461         m_dropTarget->RegisterTarget(FALSE);
5462         m_dropTarget->Release();
5463         m_dropTarget = NULL;
5464     }
5465 }
5466 
5467 BOOL AwtComponent::IsFocusingMouseMessage(MSG *pMsg) {
5468     return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
5469 }
5470 
5471 BOOL AwtComponent::IsFocusingKeyMessage(MSG *pMsg) {
5472     return pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_SPACE;
5473 }
5474 
5475 void AwtComponent::_Show(void *param)
5476 {
5477     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5478 
5479     jobject self = (jobject)param;
5480 
5481     AwtComponent *p;
5482 
5483     PDATA pData;
5484     JNI_CHECK_PEER_GOTO(self, ret);
5485     p = (AwtComponent *)pData;
5486     if (::IsWindow(p->GetHWnd()))
5487     {
5488         p->SendMessage(WM_AWT_COMPONENT_SHOW);
5489     }
5490 ret:
5491     env->DeleteGlobalRef(self);
5492 }
5493 
5494 void AwtComponent::_Hide(void *param)
5495 {
5496     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5497 
5498     jobject self = (jobject)param;
5499 
5500     AwtComponent *p;
5501 
5502     PDATA pData;
5503     JNI_CHECK_PEER_GOTO(self, ret);
5504     p = (AwtComponent *)pData;
5505     if (::IsWindow(p->GetHWnd()))
5506     {
5507         p->SendMessage(WM_AWT_COMPONENT_HIDE);
5508     }
5509 ret:
5510     env->DeleteGlobalRef(self);
5511 }
5512 
5513 void AwtComponent::_Enable(void *param)
5514 {
5515     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5516 
5517     jobject self = (jobject)param;
5518 
5519     AwtComponent *p;
5520 
5521     PDATA pData;
5522     JNI_CHECK_PEER_GOTO(self, ret);
5523     p = (AwtComponent *)pData;
5524     if (::IsWindow(p->GetHWnd()))
5525     {
5526         p->Enable(TRUE);
5527     }
5528 ret:
5529     env->DeleteGlobalRef(self);
5530 }
5531 
5532 void AwtComponent::_Disable(void *param)
5533 {
5534     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5535 
5536     jobject self = (jobject)param;
5537 
5538     AwtComponent *p;
5539 
5540     PDATA pData;
5541     JNI_CHECK_PEER_GOTO(self, ret);
5542     p = (AwtComponent *)pData;
5543     if (::IsWindow(p->GetHWnd()))
5544     {
5545         p->Enable(FALSE);
5546     }
5547 ret:
5548     env->DeleteGlobalRef(self);
5549 }
5550 
5551 jobject AwtComponent::_GetLocationOnScreen(void *param)
5552 {
5553     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5554 
5555     jobject self = (jobject)param;
5556 
5557     jobject result = NULL;
5558     AwtComponent *p;
5559 
5560     PDATA pData;
5561     JNI_CHECK_PEER_GOTO(self, ret);
5562     p = (AwtComponent *)pData;
5563     if (::IsWindow(p->GetHWnd()))
5564     {
5565         RECT rect;
5566         VERIFY(::GetWindowRect(p->GetHWnd(),&rect));
5567         result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
5568                                      p->ScaleDownX(rect.left),
5569                                      p->ScaleDownY(rect.top));
5570     }
5571 ret:
5572     env->DeleteGlobalRef(self);
5573 
5574     if (result != NULL)
5575     {
5576         jobject resultGlobalRef = env->NewGlobalRef(result);
5577         env->DeleteLocalRef(result);
5578         return resultGlobalRef;
5579     }
5580     else
5581     {
5582         return NULL;
5583     }
5584 }
5585 
5586 void AwtComponent::_Reshape(void *param)
5587 {
5588     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5589 
5590     ReshapeStruct *rs = (ReshapeStruct*)param;
5591     jobject self = rs->component;
5592     jint x = rs->x;
5593     jint y = rs->y;
5594     jint w = rs->w;
5595     jint h = rs->h;
5596 
5597     AwtComponent *p;
5598 
5599     PDATA pData;
5600     JNI_CHECK_PEER_GOTO(self, ret);
5601     p = (AwtComponent *)pData;
5602     if (::IsWindow(p->GetHWnd()))
5603     {
5604         RECT* r = new RECT;
5605         ::SetRect(r, x, y, x + w, y + h);
5606         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, CHECK_EMBEDDED, (LPARAM)r);
5607     }
5608 ret:
5609     env->DeleteGlobalRef(self);
5610 
5611     delete rs;
5612 }
5613 
5614 void AwtComponent::_ReshapeNoCheck(void *param)
5615 {
5616     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5617 
5618     ReshapeStruct *rs = (ReshapeStruct*)param;
5619     jobject self = rs->component;
5620     jint x = rs->x;
5621     jint y = rs->y;
5622     jint w = rs->w;
5623     jint h = rs->h;
5624 
5625     AwtComponent *p;
5626 
5627     PDATA pData;
5628     JNI_CHECK_PEER_GOTO(self, ret);
5629     p = (AwtComponent *)pData;
5630     if (::IsWindow(p->GetHWnd()))
5631     {
5632         RECT* r = new RECT;
5633         ::SetRect(r, x, y, x + w, y + h);
5634         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, DONT_CHECK_EMBEDDED, (LPARAM)r);
5635     }
5636 ret:
5637     env->DeleteGlobalRef(self);
5638 
5639     delete rs;
5640 }
5641 
5642 void AwtComponent::_NativeHandleEvent(void *param)
5643 {
5644     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5645 
5646     NativeHandleEventStruct *nhes = (NativeHandleEventStruct *)param;
5647     jobject self = nhes->component;
5648     jobject event = nhes->event;
5649 
5650     AwtComponent *p;
5651 
5652     PDATA pData;
5653     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5654     pData = JNI_GET_PDATA(self);
5655     if (pData == NULL) {
5656         env->DeleteGlobalRef(self);
5657         if (event != NULL) {
5658             env->DeleteGlobalRef(event);
5659         }
5660         delete nhes;
5661         return;
5662     }
5663     JNI_CHECK_NULL_GOTO(event, "null AWTEvent", ret);
5664 
5665     p = (AwtComponent *)pData;
5666     if (::IsWindow(p->GetHWnd()))
5667     {
5668         if (env->EnsureLocalCapacity(1) < 0) {
5669             env->DeleteGlobalRef(self);
5670             env->DeleteGlobalRef(event);
5671             delete nhes;
5672             return;
5673         }
5674         jbyteArray bdata = (jbyteArray)(env)->GetObjectField(event, AwtAWTEvent::bdataID);
5675         int id = (env)->GetIntField(event, AwtAWTEvent::idID);
5676         DASSERT(!safe_ExceptionOccurred(env));
5677         if (bdata != 0) {
5678             MSG msg;
5679             (env)->GetByteArrayRegion(bdata, 0, sizeof(MSG), (jbyte *)&msg);
5680             (env)->DeleteLocalRef(bdata);
5681             static BOOL keyDownConsumed = FALSE;
5682             static BOOL bCharChanged = FALSE;
5683             static WCHAR modifiedChar;
5684             WCHAR unicodeChar;
5685 
5686             /* Remember if a KEY_PRESSED event is consumed, as an old model
5687              * program won't consume a subsequent KEY_TYPED event.
5688              */
5689             jboolean consumed =
5690                 (env)->GetBooleanField(event, AwtAWTEvent::consumedID);
5691             DASSERT(!safe_ExceptionOccurred(env));
5692 
5693             if (consumed) {
5694                 keyDownConsumed = (id == java_awt_event_KeyEvent_KEY_PRESSED);
5695                 env->DeleteGlobalRef(self);
5696                 env->DeleteGlobalRef(event);
5697                 delete nhes;
5698                 return;
5699 
5700             } else if (id == java_awt_event_KeyEvent_KEY_PRESSED) {
5701                 // Fix for 6637607: reset consuming
5702                 keyDownConsumed = FALSE;
5703             }
5704 
5705             /* Consume a KEY_TYPED event if a KEY_PRESSED had been, to support
5706              * the old model.
5707              */
5708             if ((id == java_awt_event_KeyEvent_KEY_TYPED) && keyDownConsumed) {
5709                 keyDownConsumed = FALSE;
5710                 env->DeleteGlobalRef(self);
5711                 env->DeleteGlobalRef(event);
5712                 delete nhes;
5713                 return;
5714             }
5715 
5716             /* Modify any event parameters, if necessary. */
5717             if (self && pData &&
5718                 id >= java_awt_event_KeyEvent_KEY_FIRST &&
5719                 id <= java_awt_event_KeyEvent_KEY_LAST) {
5720 
5721                     AwtComponent* p = (AwtComponent*)pData;
5722 
5723                     jint keyCode =
5724                       (env)->GetIntField(event, AwtKeyEvent::keyCodeID);
5725                     jchar keyChar =
5726                       (env)->GetCharField(event, AwtKeyEvent::keyCharID);
5727                     jint modifiers =
5728                       (env)->GetIntField(event, AwtInputEvent::modifiersID);
5729 
5730                     DASSERT(!safe_ExceptionOccurred(env));
5731 
5732                 /* Check to see whether the keyCode or modifiers were changed
5733                    on the keyPressed event, and tweak the following keyTyped
5734                    event (if any) accodingly.  */
5735                 switch (id) {
5736                 case java_awt_event_KeyEvent_KEY_PRESSED:
5737                 {
5738                     UINT winKey = (UINT)msg.wParam;
5739                     bCharChanged = FALSE;
5740 
5741                     if (winKey == VK_PROCESSKEY) {
5742                         // Leave it up to IME
5743                         break;
5744                     }
5745 
5746                     if (keyCode != java_awt_event_KeyEvent_VK_UNDEFINED) {
5747                         UINT newWinKey, ignored;
5748                         p->JavaKeyToWindowsKey(keyCode, &newWinKey, &ignored, winKey);
5749                         if (newWinKey != 0) {
5750                             winKey = newWinKey;
5751                         }
5752                     }
5753 
5754                     BOOL isDeadKey = FALSE;
5755                     modifiedChar = p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE, isDeadKey);
5756                     bCharChanged = (keyChar != modifiedChar);
5757                 }
5758                 break;
5759 
5760                 case java_awt_event_KeyEvent_KEY_RELEASED:
5761                 {
5762                     keyDownConsumed = FALSE;
5763                     bCharChanged = FALSE;
5764                 }
5765                 break;
5766 
5767                 case java_awt_event_KeyEvent_KEY_TYPED:
5768                 {
5769                     if (bCharChanged)
5770                     {
5771                         unicodeChar = modifiedChar;
5772                     }
5773                     else
5774                     {
5775                         unicodeChar = keyChar;
5776                     }
5777                     bCharChanged = FALSE;
5778 
5779                     // Disable forwarding KEY_TYPED messages to peers of
5780                     // disabled components
5781                     if (p->isRecursivelyEnabled()) {
5782                         // send the character back to the native window for
5783                         // processing. The WM_AWT_FORWARD_CHAR handler will send
5784                         // this character to DefWindowProc
5785                         if (!::PostMessage(p->GetHWnd(), WM_AWT_FORWARD_CHAR,
5786                             MAKEWPARAM(unicodeChar, FALSE), msg.lParam)) {
5787                             JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5788                         }
5789                     }
5790                     env->DeleteGlobalRef(self);
5791                     env->DeleteGlobalRef(event);
5792                     delete nhes;
5793                     return;
5794                 }
5795                 break;
5796 
5797                 default:
5798                     break;
5799                 }
5800             }
5801 
5802             // ignore all InputMethodEvents
5803             if (self && (pData = JNI_GET_PDATA(self)) &&
5804                 id >= java_awt_event_InputMethodEvent_INPUT_METHOD_FIRST &&
5805                 id <= java_awt_event_InputMethodEvent_INPUT_METHOD_LAST) {
5806                 env->DeleteGlobalRef(self);
5807                 env->DeleteGlobalRef(event);
5808                 delete nhes;
5809                 return;
5810             }
5811 
5812             // Create copy for local msg
5813             MSG* pCopiedMsg = new MSG;
5814             memmove(pCopiedMsg, &msg, sizeof(MSG));
5815             // Event handler deletes msg
5816             p->PostHandleEventMessage(pCopiedMsg, FALSE);
5817 
5818             env->DeleteGlobalRef(self);
5819             env->DeleteGlobalRef(event);
5820             delete nhes;
5821             return;
5822         }
5823 
5824         /* Forward any valid synthesized events.  Currently only mouse and
5825          * key events are supported.
5826          */
5827         if (self == NULL || (pData = JNI_GET_PDATA(self)) == NULL) {
5828             env->DeleteGlobalRef(self);
5829             env->DeleteGlobalRef(event);
5830             delete nhes;
5831             return;
5832         }
5833 
5834         AwtComponent* p = (AwtComponent*)pData;
5835         if (id >= java_awt_event_KeyEvent_KEY_FIRST &&
5836             id <= java_awt_event_KeyEvent_KEY_LAST) {
5837             p->SynthesizeKeyMessage(env, event);
5838         } else if (id >= java_awt_event_MouseEvent_MOUSE_FIRST &&
5839                    id <= java_awt_event_MouseEvent_MOUSE_LAST) {
5840             p->SynthesizeMouseMessage(env, event);
5841         }
5842     }
5843 
5844 ret:
5845     if (self != NULL) {
5846         env->DeleteGlobalRef(self);
5847     }
5848     if (event != NULL) {
5849         env->DeleteGlobalRef(event);
5850     }
5851 
5852     delete nhes;
5853 }
5854 
5855 void AwtComponent::_SetForeground(void *param)
5856 {
5857     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5858 
5859     SetColorStruct *scs = (SetColorStruct *)param;
5860     jobject self = scs->component;
5861     jint rgb = scs->rgb;
5862 
5863     AwtComponent *c = NULL;
5864 
5865     PDATA pData;
5866     JNI_CHECK_PEER_GOTO(self, ret);
5867     c = (AwtComponent *)pData;
5868     if (::IsWindow(c->GetHWnd()))
5869     {
5870         c->SetColor(PALETTERGB((rgb>>16)&0xff,
5871                                (rgb>>8)&0xff,
5872                                (rgb)&0xff));
5873         c->VerifyState();
5874     }
5875 ret:
5876     env->DeleteGlobalRef(self);
5877 
5878     delete scs;
5879 }
5880 
5881 void AwtComponent::_SetBackground(void *param)
5882 {
5883     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5884 
5885     SetColorStruct *scs = (SetColorStruct *)param;
5886     jobject self = scs->component;
5887     jint rgb = scs->rgb;
5888 
5889     AwtComponent *c = NULL;
5890 
5891     PDATA pData;
5892     JNI_CHECK_PEER_GOTO(self, ret);
5893     c = (AwtComponent *)pData;
5894     if (::IsWindow(c->GetHWnd()))
5895     {
5896         c->SetBackgroundColor(PALETTERGB((rgb>>16)&0xff,
5897                                          (rgb>>8)&0xff,
5898                                          (rgb)&0xff));
5899         c->VerifyState();
5900     }
5901 ret:
5902     env->DeleteGlobalRef(self);
5903 
5904     delete scs;
5905 }
5906 
5907 void AwtComponent::_SetFont(void *param)
5908 {
5909     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5910 
5911     SetFontStruct *sfs = (SetFontStruct *)param;
5912     jobject self = sfs->component;
5913     jobject font = sfs->font;
5914 
5915     AwtComponent *c = NULL;
5916 
5917     PDATA pData;
5918     JNI_CHECK_PEER_GOTO(self, ret);
5919     JNI_CHECK_NULL_GOTO(font, "null font", ret);
5920     c = (AwtComponent *)pData;
5921     if (::IsWindow(c->GetHWnd()))
5922     {
5923         AwtFont *awtFont = (AwtFont *)env->GetLongField(font, AwtFont::pDataID);
5924         if (awtFont == NULL) {
5925             /*arguments of AwtFont::Create are changed for multifont component */
5926             awtFont = AwtFont::Create(env, font);
5927         }
5928         env->SetLongField(font, AwtFont::pDataID, (jlong)awtFont);
5929 
5930         c->SetFont(awtFont);
5931     }
5932 ret:
5933     env->DeleteGlobalRef(self);
5934     env->DeleteGlobalRef(font);
5935 
5936     delete sfs;
5937 }
5938 
5939 // Sets or kills focus for a component.
5940 void AwtComponent::_SetFocus(void *param)
5941 {
5942     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5943 
5944     SetFocusStruct *sfs = (SetFocusStruct *)param;
5945     jobject self = sfs->component;
5946     jboolean doSetFocus = sfs->doSetFocus;
5947 
5948     AwtComponent *c = NULL;
5949 
5950     PDATA pData;
5951     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5952     pData = JNI_GET_PDATA(self);
5953     if (pData == NULL) {
5954         // do nothing just return false
5955         goto ret;
5956     }
5957 
5958     c = (AwtComponent *)pData;
5959     if (::IsWindow(c->GetHWnd())) {
5960         c->SendMessage(WM_AWT_COMPONENT_SETFOCUS, (WPARAM)doSetFocus, 0);
5961     }
5962 ret:
5963     env->DeleteGlobalRef(self);
5964 
5965     delete sfs;
5966 }
5967 
5968 void AwtComponent::_Start(void *param)
5969 {
5970     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5971 
5972     jobject self = (jobject)param;
5973 
5974     AwtComponent *c = NULL;
5975 
5976     PDATA pData;
5977     JNI_CHECK_PEER_GOTO(self, ret);
5978     c = (AwtComponent *)pData;
5979     if (::IsWindow(c->GetHWnd()))
5980     {
5981         jobject target = c->GetTarget(env);
5982 
5983         /* Disable window if specified -- windows are enabled by default. */
5984         jboolean enabled = (jboolean)env->GetBooleanField(target,
5985                                                           AwtComponent::enabledID);
5986         if (!enabled) {
5987             ::EnableWindow(c->GetHWnd(), FALSE);
5988         }
5989 
5990         /* The peer is now ready for callbacks, since this is the last
5991          * initialization call
5992          */
5993         c->EnableCallbacks(TRUE);
5994 
5995         // Fix 4745222: we need to invalidate region since we validated it before initialization.
5996         ::InvalidateRgn(c->GetHWnd(), NULL, FALSE);
5997 
5998         // Fix 4530093: WM_PAINT after EnableCallbacks
5999         ::UpdateWindow(c->GetHWnd());
6000 
6001         env->DeleteLocalRef(target);
6002     }
6003 ret:
6004     env->DeleteGlobalRef(self);
6005 }
6006 
6007 void AwtComponent::_BeginValidate(void *param)
6008 {
6009     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6010     if (AwtToolkit::IsMainThread()) {
6011         jobject self = (jobject)param;
6012         if (self != NULL) {
6013             PDATA pData = JNI_GET_PDATA(self);
6014             if (pData) {
6015                 AwtComponent *c = (AwtComponent *)pData;
6016                 if (::IsWindow(c->GetHWnd())) {
6017                     c->SendMessage(WM_AWT_BEGIN_VALIDATE);
6018                 }
6019             }
6020             env->DeleteGlobalRef(self);
6021         }
6022     } else {
6023         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_BeginValidate, param);
6024     }
6025 }
6026 
6027 void AwtComponent::_EndValidate(void *param)
6028 {
6029     if (AwtToolkit::IsMainThread()) {
6030         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6031         jobject self = (jobject)param;
6032         if (self != NULL) {
6033             PDATA pData = JNI_GET_PDATA(self);
6034             if (pData) {
6035                 AwtComponent *c = (AwtComponent *)pData;
6036                 if (::IsWindow(c->GetHWnd())) {
6037                     c->SendMessage(WM_AWT_END_VALIDATE);
6038                 }
6039             }
6040             env->DeleteGlobalRef(self);
6041         }
6042     } else {
6043         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_EndValidate, param);
6044     }
6045 }
6046 
6047 void AwtComponent::_UpdateWindow(void *param)
6048 {
6049     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6050     if (AwtToolkit::IsMainThread()) {
6051         jobject self = (jobject)param;
6052         AwtComponent *c = NULL;
6053         PDATA pData;
6054         JNI_CHECK_PEER_GOTO(self, ret);
6055         c = (AwtComponent *)pData;
6056         if (::IsWindow(c->GetHWnd())) {
6057             ::UpdateWindow(c->GetHWnd());
6058         }
6059 ret:
6060         env->DeleteGlobalRef(self);
6061     } else {
6062         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_UpdateWindow, param);
6063     }
6064 }
6065 
6066 jlong AwtComponent::_AddNativeDropTarget(void *param)
6067 {
6068     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6069 
6070     jobject self = (jobject)param;
6071 
6072     jlong result = 0;
6073     AwtComponent *c = NULL;
6074 
6075     PDATA pData;
6076     JNI_CHECK_PEER_GOTO(self, ret);
6077     c = (AwtComponent *)pData;
6078     if (::IsWindow(c->GetHWnd()))
6079     {
6080         result = (jlong)(c->CreateDropTarget(env));
6081     }
6082 ret:
6083     env->DeleteGlobalRef(self);
6084 
6085     return result;
6086 }
6087 
6088 void AwtComponent::_RemoveNativeDropTarget(void *param)
6089 {
6090     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6091 
6092     jobject self = (jobject)param;
6093 
6094     AwtComponent *c = NULL;
6095 
6096     PDATA pData;
6097     JNI_CHECK_PEER_GOTO(self, ret);
6098     c = (AwtComponent *)pData;
6099     if (::IsWindow(c->GetHWnd()))
6100     {
6101         c->DestroyDropTarget();
6102     }
6103 ret:
6104     env->DeleteGlobalRef(self);
6105 }
6106 
6107 jintArray AwtComponent::_CreatePrintedPixels(void *param)
6108 {
6109     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6110 
6111     CreatePrintedPixelsStruct *cpps = (CreatePrintedPixelsStruct *)param;
6112     jobject self = cpps->component;
6113 
6114     jintArray result = NULL;
6115     AwtComponent *c = NULL;
6116 
6117     PDATA pData;
6118     JNI_CHECK_PEER_GOTO(self, ret);
6119     c = (AwtComponent *)pData;
6120     if (::IsWindow(c->GetHWnd()))
6121     {
6122         result = (jintArray)c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)cpps, 0);
6123     }
6124 ret:
6125     env->DeleteGlobalRef(self);
6126 
6127     delete cpps;
6128     return result; // this reference is global
6129 }
6130 
6131 jboolean AwtComponent::_IsObscured(void *param)
6132 {
6133     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6134 
6135     jobject self = (jobject)param;
6136 
6137     jboolean result = JNI_FALSE;
6138     AwtComponent *c = NULL;
6139 
6140     PDATA pData;
6141     JNI_CHECK_PEER_GOTO(self, ret);
6142 
6143     c = (AwtComponent *)pData;
6144 
6145     if (::IsWindow(c->GetHWnd()))
6146     {
6147         HWND hWnd = c->GetHWnd();
6148         HDC hDC = ::GetDC(hWnd);
6149         RECT clipbox;
6150         int callresult = ::GetClipBox(hDC, &clipbox);
6151         switch(callresult) {
6152             case NULLREGION :
6153                 result = JNI_FALSE;
6154                 break;
6155             case SIMPLEREGION : {
6156                 RECT windowRect;
6157                 if (!::GetClientRect(hWnd, &windowRect)) {
6158                     result = JNI_TRUE;
6159                 } else {
6160                     result  = (jboolean)((clipbox.bottom != windowRect.bottom)
6161                         || (clipbox.left != windowRect.left)
6162                         || (clipbox.right != windowRect.right)
6163                         || (clipbox.top != windowRect.top));
6164                 }
6165                 break;
6166             }
6167             case COMPLEXREGION :
6168             default :
6169                 result = JNI_TRUE;
6170                 break;
6171         }
6172         ::ReleaseDC(hWnd, hDC);
6173     }
6174 ret:
6175     env->DeleteGlobalRef(self);
6176 
6177     return result;
6178 }
6179 
6180 jboolean AwtComponent::_NativeHandlesWheelScrolling(void *param)
6181 {
6182     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6183 
6184     jobject self = (jobject)param;
6185 
6186     jboolean result = JNI_FALSE;
6187     AwtComponent *c = NULL;
6188 
6189     PDATA pData;
6190     JNI_CHECK_PEER_GOTO(self, ret);
6191     c = (AwtComponent *)pData;
6192     if (::IsWindow(c->GetHWnd()))
6193     {
6194         result = JNI_IS_TRUE(c->InheritsNativeMouseWheelBehavior());
6195     }
6196 ret:
6197     env->DeleteGlobalRef(self);
6198 
6199     return result;
6200 }
6201 
6202 void AwtComponent::SetParent(void * param) {
6203     if (AwtToolkit::IsMainThread()) {
6204         AwtComponent** comps = (AwtComponent**)param;
6205         if ((comps[0] != NULL) && (comps[1] != NULL)) {
6206             HWND selfWnd = comps[0]->GetHWnd();
6207             HWND parentWnd = comps[1]->GetHWnd();
6208             if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) {
6209                 // Shouldn't trigger native focus change
6210                 // (only the proxy may be the native focus owner).
6211                 ::SetParent(selfWnd, parentWnd);
6212             }
6213         }
6214         delete[] comps;
6215     } else {
6216         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::SetParent, param);
6217     }
6218 }
6219 
6220 void AwtComponent::_SetRectangularShape(void *param)
6221 {
6222     if (!AwtToolkit::IsMainThread()) {
6223         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetRectangularShape, param);
6224     } else {
6225         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6226 
6227         SetRectangularShapeStruct *data = (SetRectangularShapeStruct *)param;
6228         jobject self = data->component;
6229         jint x1 = data->x1;
6230         jint x2 = data->x2;
6231         jint y1 = data->y1;
6232         jint y2 = data->y2;
6233         jobject region = data->region;
6234 
6235         AwtComponent *c = NULL;
6236 
6237         PDATA pData;
6238         JNI_CHECK_PEER_GOTO(self, ret);
6239 
6240         c = (AwtComponent *)pData;
6241         if (::IsWindow(c->GetHWnd())) {
6242             HRGN hRgn = NULL;
6243 
6244             // If all the params are zeros, the shape must be simply reset.
6245             // Otherwise, convert it into a region.
6246             if (region || x1 || x2 || y1 || y2) {
6247                 RECT_T rects[256];
6248                 RECT_T *pRect = rects;
6249 
6250                 const int numrects = RegionToYXBandedRectangles(env, x1, y1, x2, y2,
6251                         region, &pRect, sizeof(rects)/sizeof(rects[0]));
6252                 if (!pRect) {
6253                     // RegionToYXBandedRectangles doesn't use safe_Malloc(),
6254                     // so throw the exception explicitly
6255                     throw std::bad_alloc();
6256                 }
6257 
6258                 RGNDATA *pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc,
6259                         sizeof(RGNDATAHEADER), sizeof(RECT_T), numrects);
6260                 memcpy((BYTE*)pRgnData + sizeof(RGNDATAHEADER), pRect, sizeof(RECT_T) * numrects);
6261                 if (pRect != rects) {
6262                     free(pRect);
6263                 }
6264                 pRect = NULL;
6265 
6266                 RGNDATAHEADER *pRgnHdr = (RGNDATAHEADER *) pRgnData;
6267                 pRgnHdr->dwSize = sizeof(RGNDATAHEADER);
6268                 pRgnHdr->iType = RDH_RECTANGLES;
6269                 pRgnHdr->nRgnSize = 0;
6270                 pRgnHdr->rcBound.top = 0;
6271                 pRgnHdr->rcBound.left = 0;
6272                 pRgnHdr->rcBound.bottom = LONG(y2 - y1);
6273                 pRgnHdr->rcBound.right = LONG(x2 - x1);
6274                 pRgnHdr->nCount = numrects;
6275 
6276                 hRgn = ::ExtCreateRegion(NULL,
6277                         sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, pRgnData);
6278 
6279                 free(pRgnData);
6280             }
6281 
6282             ::SetWindowRgn(c->GetHWnd(), hRgn, TRUE);
6283         }
6284 
6285 ret:
6286         env->DeleteGlobalRef(self);
6287         if (region) {
6288             env->DeleteGlobalRef(region);
6289         }
6290 
6291         delete data;
6292     }
6293 }
6294 
6295 void AwtComponent::_SetZOrder(void *param) {
6296     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6297 
6298     SetZOrderStruct *data = (SetZOrderStruct *)param;
6299     jobject self = data->component;
6300     HWND above = HWND_TOP;
6301     if (data->above != 0) {
6302         above = reinterpret_cast<HWND>(data->above);
6303     }
6304 
6305     AwtComponent *c = NULL;
6306 
6307     PDATA pData;
6308     JNI_CHECK_PEER_GOTO(self, ret);
6309 
6310     c = (AwtComponent *)pData;
6311     if (::IsWindow(c->GetHWnd())) {
6312         ::SetWindowPos(c->GetHWnd(), above, 0, 0, 0, 0,
6313                        SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS);
6314     }
6315 
6316 ret:
6317     env->DeleteGlobalRef(self);
6318 
6319     delete data;
6320 }
6321 
6322 void AwtComponent::PostUngrabEvent() {
6323     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6324     jobject target = GetTarget(env);
6325     jobject event = JNU_NewObjectByName(env, "sun/awt/UngrabEvent", "(Ljava/awt/Component;)V",
6326                                         target);
6327     if (safe_ExceptionOccurred(env)) {
6328         env->ExceptionDescribe();
6329         env->ExceptionClear();
6330     }
6331     env->DeleteLocalRef(target);
6332     if (event != NULL) {
6333         SendEvent(event);
6334         env->DeleteLocalRef(event);
6335     }
6336 }
6337 
6338 void AwtComponent::SetFocusedWindow(HWND window)
6339 {
6340     HWND old = sm_focusedWindow;
6341     sm_focusedWindow = window;
6342 
6343     AwtWindow::FocusedWindowChanged(old, window);
6344 }
6345 
6346 /************************************************************************
6347  * Component native methods
6348  */
6349 
6350 extern "C" {
6351 
6352 /**
6353  * This method is called from the WGL pipeline when it needs to retrieve
6354  * the HWND associated with a ComponentPeer's C++ level object.
6355  */
6356 HWND
6357 AwtComponent_GetHWnd(JNIEnv *env, jlong pData)
6358 {
6359     AwtComponent *p = (AwtComponent *)jlong_to_ptr(pData);
6360     if (p == NULL) {
6361         return (HWND)0;
6362     }
6363     return p->GetHWnd();
6364 }
6365 
6366 static void _GetInsets(void* param)
6367 {
6368     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6369 
6370     GetInsetsStruct *gis = (GetInsetsStruct *)param;
6371     jobject self = gis->window;
6372 
6373     gis->insets->left = gis->insets->top =
6374         gis->insets->right = gis->insets->bottom = 0;
6375 
6376     PDATA pData;
6377     JNI_CHECK_PEER_GOTO(self, ret);
6378     AwtComponent *component = (AwtComponent *)pData;
6379 
6380     component->GetInsets(gis->insets);
6381 
6382   ret:
6383     env->DeleteGlobalRef(self);
6384     delete gis;
6385 }
6386 
6387 /**
6388  * This method is called from the WGL pipeline when it needs to retrieve
6389  * the insets associated with a ComponentPeer's C++ level object.
6390  */
6391 void AwtComponent_GetInsets(JNIEnv *env, jobject peer, RECT *insets)
6392 {
6393     TRY;
6394 
6395     GetInsetsStruct *gis = new GetInsetsStruct;
6396     gis->window = env->NewGlobalRef(peer);
6397     gis->insets = insets;
6398 
6399     AwtToolkit::GetInstance().InvokeFunction(_GetInsets, gis);
6400     // global refs and mds are deleted in _UpdateWindow
6401 
6402     CATCH_BAD_ALLOC;
6403 
6404 }
6405 
6406 JNIEXPORT void JNICALL
6407 Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls)
6408 {
6409     TRY;
6410     jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent");
6411     CHECK_NULL(inputEventClazz);
6412     jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I");
6413     CHECK_NULL(getButtonDownMasksID);
6414     jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID);
6415     jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE);
6416     CHECK_NULL(tmp);
6417     jsize len = env->GetArrayLength(obj);
6418     AwtComponent::masks = SAFE_SIZE_NEW_ARRAY(jint, len);
6419     for (int i = 0; i < len; i++) {
6420         AwtComponent::masks[i] = tmp[i];
6421     }
6422     env->ReleaseIntArrayElements(obj, tmp, 0);
6423     env->DeleteLocalRef(obj);
6424 
6425     /* class ids */
6426     jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer");
6427 
6428     DASSERT(peerCls);
6429     CHECK_NULL(peerCls);
6430 
6431     /* field ids */
6432     AwtComponent::peerID =
6433       env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;");
6434     DASSERT(AwtComponent::peerID);
6435     CHECK_NULL(AwtComponent::peerID);
6436 
6437     AwtComponent::xID = env->GetFieldID(cls, "x", "I");
6438     DASSERT(AwtComponent::xID);
6439     CHECK_NULL(AwtComponent::xID);
6440 
6441     AwtComponent::yID = env->GetFieldID(cls, "y", "I");
6442     DASSERT(AwtComponent::yID);
6443     CHECK_NULL(AwtComponent::yID);
6444 
6445     AwtComponent::heightID = env->GetFieldID(cls, "height", "I");
6446     DASSERT(AwtComponent::heightID);
6447     CHECK_NULL(AwtComponent::heightID);
6448 
6449     AwtComponent::widthID = env->GetFieldID(cls, "width", "I");
6450     DASSERT(AwtComponent::widthID);
6451     CHECK_NULL(AwtComponent::widthID);
6452 
6453     AwtComponent::visibleID = env->GetFieldID(cls, "visible", "Z");
6454     DASSERT(AwtComponent::visibleID);
6455     CHECK_NULL(AwtComponent::visibleID);
6456 
6457     AwtComponent::backgroundID =
6458         env->GetFieldID(cls, "background", "Ljava/awt/Color;");
6459     DASSERT(AwtComponent::backgroundID);
6460     CHECK_NULL(AwtComponent::backgroundID);
6461 
6462     AwtComponent::foregroundID =
6463         env->GetFieldID(cls, "foreground", "Ljava/awt/Color;");
6464     DASSERT(AwtComponent::foregroundID);
6465     CHECK_NULL(AwtComponent::foregroundID);
6466 
6467     AwtComponent::enabledID = env->GetFieldID(cls, "enabled", "Z");
6468     DASSERT(AwtComponent::enabledID);
6469     CHECK_NULL(AwtComponent::enabledID);
6470 
6471     AwtComponent::parentID = env->GetFieldID(cls, "parent", "Ljava/awt/Container;");
6472     DASSERT(AwtComponent::parentID);
6473     CHECK_NULL(AwtComponent::parentID);
6474 
6475     AwtComponent::graphicsConfigID =
6476      env->GetFieldID(cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;");
6477     DASSERT(AwtComponent::graphicsConfigID);
6478     CHECK_NULL(AwtComponent::graphicsConfigID);
6479 
6480     AwtComponent::focusableID = env->GetFieldID(cls, "focusable", "Z");
6481     DASSERT(AwtComponent::focusableID);
6482     CHECK_NULL(AwtComponent::focusableID);
6483 
6484     AwtComponent::appContextID = env->GetFieldID(cls, "appContext",
6485                                                  "Lsun/awt/AppContext;");
6486     DASSERT(AwtComponent::appContextID);
6487     CHECK_NULL(AwtComponent::appContextID);
6488 
6489     AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig",
6490                                         "Lsun/awt/Win32GraphicsConfig;");
6491     DASSERT(AwtComponent::peerGCID);
6492     CHECK_NULL(AwtComponent::peerGCID);
6493 
6494     AwtComponent::hwndID = env->GetFieldID(peerCls, "hwnd", "J");
6495     DASSERT(AwtComponent::hwndID);
6496     CHECK_NULL(AwtComponent::hwndID);
6497 
6498     AwtComponent::cursorID = env->GetFieldID(cls, "cursor", "Ljava/awt/Cursor;");
6499     DASSERT(AwtComponent::cursorID);
6500     CHECK_NULL(AwtComponent::cursorID);
6501 
6502     /* method ids */
6503     AwtComponent::getFontMID =
6504         env->GetMethodID(cls, "getFont_NoClientCode", "()Ljava/awt/Font;");
6505     DASSERT(AwtComponent::getFontMID);
6506     CHECK_NULL(AwtComponent::getFontMID);
6507 
6508     AwtComponent::getToolkitMID =
6509         env->GetMethodID(cls, "getToolkitImpl", "()Ljava/awt/Toolkit;");
6510     DASSERT(AwtComponent::getToolkitMID);
6511     CHECK_NULL(AwtComponent::getToolkitMID);
6512 
6513     AwtComponent::isEnabledMID = env->GetMethodID(cls, "isEnabledImpl", "()Z");
6514     DASSERT(AwtComponent::isEnabledMID);
6515     CHECK_NULL(AwtComponent::isEnabledMID);
6516 
6517     AwtComponent::getLocationOnScreenMID =
6518         env->GetMethodID(cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;");
6519     DASSERT(AwtComponent::getLocationOnScreenMID);
6520     CHECK_NULL(AwtComponent::getLocationOnScreenMID);
6521 
6522     AwtComponent::replaceSurfaceDataMID =
6523         env->GetMethodID(peerCls, "replaceSurfaceData", "()V");
6524     DASSERT(AwtComponent::replaceSurfaceDataMID);
6525     CHECK_NULL(AwtComponent::replaceSurfaceDataMID);
6526 
6527     AwtComponent::replaceSurfaceDataLaterMID =
6528         env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V");
6529     DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
6530     CHECK_NULL(AwtComponent::replaceSurfaceDataLaterMID);
6531 
6532     AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
6533     DASSERT(AwtComponent::disposeLaterMID);
6534     CHECK_NULL(AwtComponent::disposeLaterMID);
6535 
6536     CATCH_BAD_ALLOC;
6537 }
6538 
6539 } /* extern "C" */
6540 
6541 
6542 /************************************************************************
6543  * ComponentPeer native methods
6544  */
6545 
6546 extern "C" {
6547 
6548 /*
6549  * Class:     sun_awt_windows_WComponentPeer
6550  * Method:    pShow
6551  * Signature: ()V
6552  */
6553 JNIEXPORT void JNICALL
6554 Java_sun_awt_windows_WComponentPeer_pShow(JNIEnv *env, jobject self)
6555 {
6556     TRY;
6557 
6558     jobject selfGlobalRef = env->NewGlobalRef(self);
6559 
6560     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Show, (void *)selfGlobalRef);
6561     // selfGlobalRef is deleted in _Show
6562 
6563     CATCH_BAD_ALLOC;
6564 }
6565 
6566 /*
6567  * Class:     sun_awt_windows_WComponentPeer
6568  * Method:    hide
6569  * Signature: ()V
6570  */
6571 JNIEXPORT void JNICALL
6572 Java_sun_awt_windows_WComponentPeer_hide(JNIEnv *env, jobject self)
6573 {
6574     TRY;
6575 
6576     jobject selfGlobalRef = env->NewGlobalRef(self);
6577 
6578     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Hide, (void *)selfGlobalRef);
6579     // selfGlobalRef is deleted in _Hide
6580 
6581     CATCH_BAD_ALLOC;
6582 }
6583 
6584 /*
6585  * Class:     sun_awt_windows_WComponentPeer
6586  * Method:    enable
6587  * Signature: ()V
6588  */
6589 JNIEXPORT void JNICALL
6590 Java_sun_awt_windows_WComponentPeer_enable(JNIEnv *env, jobject self)
6591 {
6592     TRY;
6593 
6594     jobject selfGlobalRef = env->NewGlobalRef(self);
6595 
6596     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Enable, (void *)selfGlobalRef);
6597     // selfGlobalRef is deleted in _Enable
6598 
6599     CATCH_BAD_ALLOC;
6600 }
6601 
6602 /*
6603  * Class:     sun_awt_windows_WComponentPeer
6604  * Method:    disable
6605  * Signature: ()V
6606  */
6607 JNIEXPORT void JNICALL
6608 Java_sun_awt_windows_WComponentPeer_disable(JNIEnv *env, jobject self)
6609 {
6610     TRY;
6611 
6612     jobject selfGlobalRef = env->NewGlobalRef(self);
6613 
6614     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Disable, (void *)selfGlobalRef);
6615     // selfGlobalRef is deleted in _Disable
6616 
6617     CATCH_BAD_ALLOC;
6618 }
6619 
6620 /*
6621  * Class:     sun_awt_windows_WComponentPeer
6622  * Method:    getLocationOnScreen
6623  * Signature: ()Ljava/awt/Point;
6624  */
6625 JNIEXPORT jobject JNICALL
6626 Java_sun_awt_windows_WComponentPeer_getLocationOnScreen(JNIEnv *env, jobject self)
6627 {
6628     TRY;
6629 
6630     jobject selfGlobalRef = env->NewGlobalRef(self);
6631 
6632     jobject resultGlobalRef = (jobject)AwtToolkit::GetInstance().SyncCall(
6633         (void*(*)(void*))AwtComponent::_GetLocationOnScreen, (void *)selfGlobalRef);
6634     // selfGlobalRef is deleted in _GetLocationOnScreen
6635     if (resultGlobalRef != NULL)
6636     {
6637         jobject resultLocalRef = env->NewLocalRef(resultGlobalRef);
6638         env->DeleteGlobalRef(resultGlobalRef);
6639         return resultLocalRef;
6640     }
6641 
6642     return NULL;
6643 
6644     CATCH_BAD_ALLOC_RET(NULL);
6645 }
6646 
6647 /*
6648  * Class:     sun_awt_windows_WComponentPeer
6649  * Method:    reshape
6650  * Signature: (IIII)V
6651  */
6652 JNIEXPORT void JNICALL
6653 Java_sun_awt_windows_WComponentPeer_reshape(JNIEnv *env, jobject self,
6654                                             jint x, jint y, jint w, jint h)
6655 {
6656     TRY;
6657 
6658     ReshapeStruct *rs = new ReshapeStruct;
6659     rs->component = env->NewGlobalRef(self);
6660     rs->x = x;
6661     rs->y = y;
6662     rs->w = w;
6663     rs->h = h;
6664 
6665     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Reshape, rs);
6666     // global ref and rs are deleted in _Reshape
6667 
6668     CATCH_BAD_ALLOC;
6669 }
6670 
6671 /*
6672  * Class:     sun_awt_windows_WComponentPeer
6673  * Method:    reshape
6674  * Signature: (IIII)V
6675  */
6676 JNIEXPORT void JNICALL
6677 Java_sun_awt_windows_WComponentPeer_reshapeNoCheck(JNIEnv *env, jobject self,
6678                                             jint x, jint y, jint w, jint h)
6679 {
6680     TRY;
6681 
6682     ReshapeStruct *rs = new ReshapeStruct;
6683     rs->component = env->NewGlobalRef(self);
6684     rs->x = x;
6685     rs->y = y;
6686     rs->w = w;
6687     rs->h = h;
6688 
6689     AwtToolkit::GetInstance().SyncCall(AwtComponent::_ReshapeNoCheck, rs);
6690     // global ref and rs are deleted in _ReshapeNoCheck
6691 
6692     CATCH_BAD_ALLOC;
6693 }
6694 
6695 
6696 /*
6697  * Class:     sun_awt_windows_WComponentPeer
6698  * Method:    nativeHandleEvent
6699  * Signature: (Ljava/awt/AWTEvent;)V
6700  */
6701 JNIEXPORT void JNICALL
6702 Java_sun_awt_windows_WComponentPeer_nativeHandleEvent(JNIEnv *env,
6703                                                       jobject self,
6704                                                       jobject event)
6705 {
6706     TRY;
6707 
6708     jobject selfGlobalRef = env->NewGlobalRef(self);
6709     jobject eventGlobalRef = env->NewGlobalRef(event);
6710 
6711     NativeHandleEventStruct *nhes = new NativeHandleEventStruct;
6712     nhes->component = selfGlobalRef;
6713     nhes->event = eventGlobalRef;
6714 
6715     AwtToolkit::GetInstance().SyncCall(AwtComponent::_NativeHandleEvent, nhes);
6716     // global refs and nhes are deleted in _NativeHandleEvent
6717 
6718     CATCH_BAD_ALLOC;
6719 }
6720 
6721 /*
6722  * Class:     sun_awt_windows_WComponentPeer
6723  * Method:    _dispose
6724  * Signature: ()V
6725  */
6726 JNIEXPORT void JNICALL
6727 Java_sun_awt_windows_WComponentPeer__1dispose(JNIEnv *env, jobject self)
6728 {
6729     TRY_NO_HANG;
6730 
6731     AwtObject::_Dispose(self);
6732 
6733     CATCH_BAD_ALLOC;
6734 }
6735 
6736 /*
6737  * Class:     sun_awt_windows_WComponentPeer
6738  * Method:    _setForeground
6739  * Signature: (I)V
6740  */
6741 JNIEXPORT void JNICALL
6742 Java_sun_awt_windows_WComponentPeer__1setForeground(JNIEnv *env, jobject self,
6743                                                     jint rgb)
6744 {
6745     TRY;
6746 
6747     jobject selfGlobalRef = env->NewGlobalRef(self);
6748 
6749     SetColorStruct *scs = new SetColorStruct;
6750     scs->component = selfGlobalRef;
6751     scs->rgb = rgb;
6752 
6753     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetForeground, scs);
6754     // selfGlobalRef and scs are deleted in _SetForeground()
6755 
6756     CATCH_BAD_ALLOC;
6757 }
6758 
6759 /*
6760  * Class:     sun_awt_windows_WComponentPeer
6761  * Method:    _setBackground
6762  * Signature: (I)V
6763  */
6764 JNIEXPORT void JNICALL
6765 Java_sun_awt_windows_WComponentPeer__1setBackground(JNIEnv *env, jobject self,
6766                                                     jint rgb)
6767 {
6768     TRY;
6769 
6770     jobject selfGlobalRef = env->NewGlobalRef(self);
6771 
6772     SetColorStruct *scs = new SetColorStruct;
6773     scs->component = selfGlobalRef;
6774     scs->rgb = rgb;
6775 
6776     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetBackground, scs);
6777     // selfGlobalRef and scs are deleted in _SetBackground()
6778 
6779     CATCH_BAD_ALLOC;
6780 }
6781 
6782 /*
6783  * Class:     sun_awt_windows_WComponentPeer
6784  * Method:    _setFont
6785  * Signature: (Ljava/awt/Font;)V
6786  */
6787 JNIEXPORT void JNICALL
6788 Java_sun_awt_windows_WComponentPeer__1setFont(JNIEnv *env, jobject self,
6789                         jobject font)
6790 {
6791     TRY;
6792 
6793     jobject selfGlobalRef = env->NewGlobalRef(self);
6794     jobject fontGlobalRef = env->NewGlobalRef(font);
6795 
6796     SetFontStruct *sfs = new SetFontStruct;
6797     sfs->component = selfGlobalRef;
6798     sfs->font = fontGlobalRef;
6799 
6800     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetFont, sfs);
6801     // global refs and sfs are deleted in _SetFont()
6802 
6803     CATCH_BAD_ALLOC;
6804 }
6805 
6806 /*
6807  * Class:     sun_awt_windows_WComponentPeer
6808  * Method:    focusGained
6809  * Signature: (Z)
6810  */
6811 JNIEXPORT void JNICALL Java_sun_awt_windows_WComponentPeer_setFocus
6812     (JNIEnv *env, jobject self, jboolean doSetFocus)
6813 {
6814     TRY;
6815 
6816     jobject selfGlobalRef = env->NewGlobalRef(self);
6817 
6818     SetFocusStruct *sfs = new SetFocusStruct;
6819     sfs->component = selfGlobalRef;
6820     sfs->doSetFocus = doSetFocus;
6821 
6822     AwtToolkit::GetInstance().SyncCall(
6823         (void*(*)(void*))AwtComponent::_SetFocus, sfs);
6824     // global refs and self are deleted in _SetFocus
6825 
6826     CATCH_BAD_ALLOC;
6827 }
6828 
6829 /*
6830  * Class:     sun_awt_windows_WComponentPeer
6831  * Method:    start
6832  * Signature: ()V
6833  */
6834 JNIEXPORT void JNICALL
6835 Java_sun_awt_windows_WComponentPeer_start(JNIEnv *env, jobject self)
6836 {
6837     TRY;
6838 
6839     jobject selfGlobalRef = env->NewGlobalRef(self);
6840 
6841     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Start, (void *)selfGlobalRef);
6842     // selfGlobalRef is deleted in _Start
6843 
6844     CATCH_BAD_ALLOC;
6845 }
6846 
6847 /*
6848  * Class:     sun_awt_windows_WComponentPeer
6849  * Method:    beginValidate
6850  * Signature: ()V
6851  */
6852 JNIEXPORT void JNICALL
6853 Java_sun_awt_windows_WComponentPeer_beginValidate(JNIEnv *env, jobject self)
6854 {
6855     TRY;
6856 
6857     jobject selfGlobalRef = env->NewGlobalRef(self);
6858 
6859     AwtToolkit::GetInstance().SyncCall(AwtComponent::_BeginValidate, (void *)selfGlobalRef);
6860     // selfGlobalRef is deleted in _BeginValidate
6861 
6862     CATCH_BAD_ALLOC;
6863 }
6864 
6865 /*
6866  * Class:     sun_awt_windows_WComponentPeer
6867  * Method:    endValidate
6868  * Signature: ()V
6869  */
6870 JNIEXPORT void JNICALL
6871 Java_sun_awt_windows_WComponentPeer_endValidate(JNIEnv *env, jobject self)
6872 {
6873     TRY;
6874 
6875     jobject selfGlobalRef = env->NewGlobalRef(self);
6876 
6877     AwtToolkit::GetInstance().SyncCall(AwtComponent::_EndValidate, (void *)selfGlobalRef);
6878     // selfGlobalRef is deleted in _EndValidate
6879 
6880     CATCH_BAD_ALLOC;
6881 }
6882 
6883 JNIEXPORT void JNICALL
6884 Java_sun_awt_windows_WComponentPeer_updateWindow(JNIEnv *env, jobject self)
6885 {
6886     TRY;
6887 
6888     jobject selfGlobalRef = env->NewGlobalRef(self);
6889 
6890     AwtToolkit::GetInstance().SyncCall(AwtComponent::_UpdateWindow, (void *)selfGlobalRef);
6891     // selfGlobalRef is deleted in _UpdateWindow
6892 
6893     CATCH_BAD_ALLOC;
6894 }
6895 
6896 /*
6897  * Class:     sun_awt_windows_WComponentPeer
6898  * Method:    addNativeDropTarget
6899  * Signature: ()L
6900  */
6901 
6902 JNIEXPORT jlong JNICALL
6903 Java_sun_awt_windows_WComponentPeer_addNativeDropTarget(JNIEnv *env,
6904                                                         jobject self)
6905 {
6906     TRY;
6907 
6908     jobject selfGlobalRef = env->NewGlobalRef(self);
6909 
6910     return ptr_to_jlong(AwtToolkit::GetInstance().SyncCall(
6911         (void*(*)(void*))AwtComponent::_AddNativeDropTarget,
6912         (void *)selfGlobalRef));
6913     // selfGlobalRef is deleted in _AddNativeDropTarget
6914 
6915     CATCH_BAD_ALLOC_RET(0);
6916 }
6917 
6918 /*
6919  * Class:     sun_awt_windows_WComponentPeer
6920  * Method:    removeNativeDropTarget
6921  * Signature: ()V
6922  */
6923 
6924 JNIEXPORT void JNICALL
6925 Java_sun_awt_windows_WComponentPeer_removeNativeDropTarget(JNIEnv *env,
6926                                                            jobject self)
6927 {
6928     TRY;
6929 
6930     jobject selfGlobalRef = env->NewGlobalRef(self);
6931 
6932     AwtToolkit::GetInstance().SyncCall(
6933         AwtComponent::_RemoveNativeDropTarget, (void *)selfGlobalRef);
6934     // selfGlobalRef is deleted in _RemoveNativeDropTarget
6935 
6936     CATCH_BAD_ALLOC;
6937 }
6938 
6939 /*
6940  * Class:     sun_awt_windows_WComponentPeer
6941  * Method:    getTargetGC
6942  * Signature: ()Ljava/awt/GraphicsConfiguration;
6943  */
6944 JNIEXPORT jobject JNICALL
6945 Java_sun_awt_windows_WComponentPeer_getTargetGC(JNIEnv* env, jobject theThis)
6946 {
6947     TRY;
6948 
6949     jobject targetObj;
6950     jobject gc = 0;
6951 
6952     targetObj = env->GetObjectField(theThis, AwtObject::targetID);
6953     DASSERT(targetObj);
6954 
6955     gc = env->GetObjectField(targetObj, AwtComponent::graphicsConfigID);
6956     return gc;
6957 
6958     CATCH_BAD_ALLOC_RET(NULL);
6959 }
6960 
6961 /*
6962  * Class:     sun_awt_windows_WComponentPeer
6963  * Method:    createPrintedPixels
6964  * Signature: (IIIIII)I[
6965  */
6966 JNIEXPORT jintArray JNICALL
6967 Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env,
6968     jobject self, jint srcX, jint srcY, jint srcW, jint srcH, jint alpha)
6969 {
6970     TRY;
6971 
6972     jobject selfGlobalRef = env->NewGlobalRef(self);
6973 
6974     CreatePrintedPixelsStruct *cpps = new CreatePrintedPixelsStruct;
6975     cpps->component = selfGlobalRef;
6976     cpps->srcx = srcX;
6977     cpps->srcy = srcY;
6978     cpps->srcw = srcW;
6979     cpps->srch = srcH;
6980     cpps->alpha = alpha;
6981 
6982     jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall(
6983         (void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps);
6984     // selfGlobalRef and cpps are deleted in _CreatePrintedPixels
6985     if (globalRef != NULL)
6986     {
6987         jintArray localRef = (jintArray)env->NewLocalRef(globalRef);
6988         env->DeleteGlobalRef(globalRef);
6989         return localRef;
6990     }
6991     else
6992     {
6993         return NULL;
6994     }
6995 
6996     CATCH_BAD_ALLOC_RET(NULL);
6997 }
6998 
6999 /*
7000  * Class:     sun_awt_windows_WComponentPeer
7001  * Method:    nativeHandlesWheelScrolling
7002  * Signature: ()Z
7003  */
7004 JNIEXPORT jboolean JNICALL
7005 Java_sun_awt_windows_WComponentPeer_nativeHandlesWheelScrolling (JNIEnv* env,
7006     jobject self)
7007 {
7008     TRY;
7009 
7010     return (jboolean)AwtToolkit::GetInstance().SyncCall(
7011         (void *(*)(void *))AwtComponent::_NativeHandlesWheelScrolling,
7012         env->NewGlobalRef(self));
7013     // global ref is deleted in _NativeHandlesWheelScrolling
7014 
7015     CATCH_BAD_ALLOC_RET(NULL);
7016 }
7017 
7018 /*
7019  * Class:     sun_awt_windows_WComponentPeer
7020  * Method:    isObscured
7021  * Signature: ()Z
7022  */
7023 JNIEXPORT jboolean JNICALL
7024 Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv* env,
7025     jobject self)
7026 {
7027     TRY;
7028 
7029     jobject selfGlobalRef = env->NewGlobalRef(self);
7030 
7031     return (jboolean)AwtToolkit::GetInstance().SyncCall(
7032         (void*(*)(void*))AwtComponent::_IsObscured,
7033         (void *)selfGlobalRef);
7034     // selfGlobalRef is deleted in _IsObscured
7035 
7036     CATCH_BAD_ALLOC_RET(NULL);
7037 }
7038 
7039 JNIEXPORT void JNICALL
7040 Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv* env, jobject self, jobject parent) {
7041     TRY;
7042 
7043     typedef AwtComponent* PComponent;
7044     AwtComponent** comps = new PComponent[2];
7045     AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(self);
7046     AwtComponent* parentComp = (AwtComponent*)JNI_GET_PDATA(parent);
7047     comps[0] = comp;
7048     comps[1] = parentComp;
7049 
7050     AwtToolkit::GetInstance().SyncCall(AwtComponent::SetParent, comps);
7051     // comps is deleted in SetParent
7052 
7053     CATCH_BAD_ALLOC;
7054 }
7055 
7056 JNIEXPORT void JNICALL
7057 Java_sun_awt_windows_WComponentPeer_setRectangularShape(JNIEnv* env, jobject self,
7058         jint x1, jint y1, jint x2, jint y2, jobject region)
7059 {
7060     TRY;
7061 
7062     SetRectangularShapeStruct * data = new SetRectangularShapeStruct;
7063     data->component = env->NewGlobalRef(self);
7064     data->x1 = x1;
7065     data->x2 = x2;
7066     data->y1 = y1;
7067     data->y2 = y2;
7068     if (region) {
7069         data->region = env->NewGlobalRef(region);
7070     } else {
7071         data->region = NULL;
7072     }
7073 
7074     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetRectangularShape, data);
7075     // global refs and data are deleted in _SetRectangularShape
7076 
7077     CATCH_BAD_ALLOC;
7078 }
7079 
7080 JNIEXPORT void JNICALL
7081 Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv* env, jobject self, jlong above)
7082 {
7083     TRY;
7084 
7085     SetZOrderStruct * data = new SetZOrderStruct;
7086     data->component = env->NewGlobalRef(self);
7087     data->above = above;
7088 
7089     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetZOrder, data);
7090     // global refs and data are deleted in _SetLower
7091 
7092     CATCH_BAD_ALLOC;
7093 }
7094 
7095 } /* extern "C" */
7096 
7097 
7098 /************************************************************************
7099  * Diagnostic routines
7100  */
7101 
7102 #ifdef DEBUG
7103 
7104 void AwtComponent::VerifyState()
7105 {
7106     if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) {
7107         return;
7108     }
7109 
7110     if (m_callbacksEnabled == FALSE) {
7111         /* Component is not fully setup yet. */
7112         return;
7113     }
7114 
7115     /* Get target bounds. */
7116     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
7117     if (env->PushLocalFrame(10) < 0)
7118         return;
7119 
7120     jobject target = GetTarget(env);
7121 
7122     jint x = env->GetIntField(target, AwtComponent::xID);
7123     jint y = env->GetIntField(target, AwtComponent::yID);
7124     jint width = env->GetIntField(target, AwtComponent::widthID);
7125     jint height = env->GetIntField(target, AwtComponent::heightID);
7126 
7127     /* Convert target origin to absolute coordinates */
7128     while (TRUE) {
7129 
7130         jobject parent = env->GetObjectField(target, AwtComponent::parentID);
7131         if (parent == NULL) {
7132             break;
7133         }
7134         x += env->GetIntField(parent, AwtComponent::xID);
7135         y += env->GetIntField(parent, AwtComponent::yID);
7136 
7137         /* If this component has insets, factor them in, but ignore
7138          * top-level windows.
7139          */
7140         jobject parent2 = env->GetObjectField(parent, AwtComponent::parentID);
7141         if (parent2 != NULL) {
7142             jobject peer = GetPeerForTarget(env, parent);
7143             if (peer != NULL &&
7144                 JNU_IsInstanceOfByName(env, peer,
7145                                        "sun/awt/windows/WPanelPeer") > 0) {
7146                 jobject insets =
7147                     JNU_CallMethodByName(env, NULL, peer,"insets",
7148                                          "()Ljava/awt/Insets;").l;
7149                 x += (env)->GetIntField(insets, AwtInsets::leftID);
7150                 y += (env)->GetIntField(insets, AwtInsets::topID);
7151             }
7152         }
7153         env->DeleteLocalRef(target);
7154         target = parent;
7155     }
7156 
7157     x = ScaleUpX(x);
7158     y = ScaleUpY(y);
7159     width = ScaleUpX(width);
7160     height = ScaleUpY(height);
7161 
7162     // Test whether component's bounds match the native window's
7163     RECT rect;
7164     VERIFY(::GetWindowRect(GetHWnd(), &rect));
7165 #if 0
7166     DASSERT( (x == rect.left) &&
7167             (y == rect.top) &&
7168             (width == (rect.right-rect.left)) &&
7169             (height == (rect.bottom-rect.top)) );
7170 #else
7171     BOOL fSizeValid = ( (x == rect.left) &&
7172             (y == rect.top) &&
7173             (width == (rect.right-rect.left)) &&
7174             (height == (rect.bottom-rect.top)) );
7175 #endif
7176 
7177     // See if visible state matches
7178     BOOL wndVisible = ::IsWindowVisible(GetHWnd());
7179     jboolean targetVisible;
7180     // To avoid possibly running client code on the toolkit thread, don't
7181     // do the following check if we're running on the toolkit thread.
7182     if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7183         targetVisible = JNU_CallMethodByName(env, NULL, GetTarget(env),
7184                                                   "isShowing", "()Z").z;
7185         DASSERT(!safe_ExceptionOccurred(env));
7186     } else {
7187         targetVisible = wndVisible ? 1 : 0;
7188     }
7189 #if 0
7190     DASSERT( (targetVisible && wndVisible) ||
7191             (!targetVisible && !wndVisible) );
7192 #else
7193     BOOL fVisibleValid = ( (targetVisible && wndVisible) ||
7194             (!targetVisible && !wndVisible) );
7195 #endif
7196 
7197     // Check enabled state
7198     BOOL wndEnabled = ::IsWindowEnabled(GetHWnd());
7199     jboolean enabled = (jboolean)env->GetBooleanField(target,
7200                                                       AwtComponent::enabledID);
7201 #if 0
7202     DASSERT( (enabled && wndEnabled) ||
7203             (!enabled && !wndEnabled) );
7204 #else
7205     BOOL fEnabledValid = ((enabled && wndEnabled) ||
7206                           (!(enabled && !wndEnabled) ));
7207 
7208     if (!fSizeValid || !fVisibleValid || !fEnabledValid) {
7209         printf("AwtComponent::ValidateState() failed:\n");
7210         // To avoid possibly running client code on the toolkit thread, don't
7211         // do the following call if we're running on the toolkit thread.
7212         if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7213             jstring targetStr =
7214                 (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),
7215                                               "getName",
7216                                               "()Ljava/lang/String;").l;
7217             DASSERT(!safe_ExceptionOccurred(env));
7218             LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
7219             printf("\t%S\n", targetStrW);
7220             JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
7221         }
7222         printf("\twas:       [%d,%d,%dx%d]\n", x, y, width, height);
7223         if (!fSizeValid) {
7224             printf("\tshould be: [%d,%d,%dx%d]\n", rect.left, rect.top,
7225                    rect.right-rect.left, rect.bottom-rect.top);
7226         }
7227         if (!fVisibleValid) {
7228             printf("\tshould be: %s\n",
7229                    (targetVisible) ? "visible" : "hidden");
7230         }
7231         if (!fEnabledValid) {
7232             printf("\tshould be: %s\n",
7233                    enabled ? "enabled" : "disabled");
7234         }
7235     }
7236 #endif
7237     env->PopLocalFrame(0);
7238 }
7239 #endif //DEBUG
7240 
7241 // Methods for globally managed DC list
7242 
7243 /**
7244  * Add a new DC to the DC list for this component.
7245  */
7246 void DCList::AddDC(HDC hDC, HWND hWnd)
7247 {
7248     DCItem *newItem = new DCItem;
7249     newItem->hDC = hDC;
7250     newItem->hWnd = hWnd;
7251     AddDCItem(newItem);
7252 }
7253 
7254 void DCList::AddDCItem(DCItem *newItem)
7255 {
7256     listLock.Enter();
7257     newItem->next = head;
7258     head = newItem;
7259     listLock.Leave();
7260 }
7261 
7262 /**
7263  * Given a DC and window handle, remove the DC from the DC list
7264  * and return TRUE if it exists on the current list.  Otherwise
7265  * return FALSE.
7266  * A DC may not exist on the list because it has already
7267  * been released elsewhere (for example, the window
7268  * destruction process may release a DC while a rendering
7269  * thread may also want to release a DC when it notices that
7270  * its DC is obsolete for the current window).
7271  */
7272 DCItem *DCList::RemoveDC(HDC hDC, HWND hWnd)
7273 {
7274     listLock.Enter();
7275     DCItem **prevPtrPtr = &head;
7276     DCItem *listPtr = head;
7277     while (listPtr) {
7278         DCItem *nextPtr = listPtr->next;
7279         if (listPtr->hDC == hDC && listPtr->hWnd == hWnd) {
7280             *prevPtrPtr = nextPtr;
7281             break;
7282         }
7283         prevPtrPtr = &listPtr->next;
7284         listPtr = nextPtr;
7285     }
7286     listLock.Leave();
7287     return listPtr;
7288 }
7289 
7290 /**
7291  * Remove all DCs from the DC list which are associated with
7292  * the same window as hWnd.  Return the list of those
7293  * DC's to the caller (which will then probably want to
7294  * call ReleaseDC() for the returned DCs).
7295  */
7296 DCItem *DCList::RemoveAllDCs(HWND hWnd)
7297 {
7298     listLock.Enter();
7299     DCItem **prevPtrPtr = &head;
7300     DCItem *listPtr = head;
7301     DCItem *newListPtr = NULL;
7302     BOOL ret = FALSE;
7303     while (listPtr) {
7304         DCItem *nextPtr = listPtr->next;
7305         if (listPtr->hWnd == hWnd) {
7306             *prevPtrPtr = nextPtr;
7307             listPtr->next = newListPtr;
7308             newListPtr = listPtr;
7309         } else {
7310             prevPtrPtr = &listPtr->next;
7311         }
7312         listPtr = nextPtr;
7313     }
7314     listLock.Leave();
7315     return newListPtr;
7316 }
7317 
7318 
7319 /**
7320  * Realize palettes of all existing HDC objects
7321  */
7322 void DCList::RealizePalettes(int screen)
7323 {
7324     listLock.Enter();
7325     DCItem *listPtr = head;
7326     while (listPtr) {
7327         AwtWin32GraphicsDevice::RealizePalette(listPtr->hDC, screen);
7328         listPtr = listPtr->next;
7329     }
7330     listLock.Leave();
7331 }
7332 
7333 void MoveDCToPassiveList(HDC hDC, HWND hWnd) {
7334     DCItem *removedDC;
7335     if ((removedDC = activeDCList.RemoveDC(hDC, hWnd)) != NULL) {
7336         passiveDCList.AddDCItem(removedDC);
7337     }
7338 }
7339 
7340 void ReleaseDCList(HWND hwnd, DCList &list) {
7341     DCItem *removedDCs = list.RemoveAllDCs(hwnd);
7342     while (removedDCs) {
7343         DCItem *tmpDCList = removedDCs;
7344         DASSERT(::GetObjectType(tmpDCList->hDC) == OBJ_DC);
7345         int retValue = ::ReleaseDC(tmpDCList->hWnd, tmpDCList->hDC);
7346         VERIFY(retValue != 0);
7347         if (retValue != 0) {
7348             // Valid ReleaseDC call; need to decrement GDI object counter
7349             AwtGDIObject::Decrement();
7350         }
7351         removedDCs = removedDCs->next;
7352         delete tmpDCList;
7353     }
7354 }