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