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