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