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