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