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 void AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, UINT *character, 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* value = transTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3406        void* deadKeyFlag = deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3407        if (value != NULL) {
3408            *character = static_cast<UINT>(reinterpret_cast<INT_PTR>(value));
3409            *isDeadKey = static_cast<UINT>(reinterpret_cast<BOOL>(deadKeyFlag));
3410            return;
3411        }
3412     }
3413 
3414     // If the windows key is a return, wkey will equal 13 ('\r')
3415     // In this case, we want to return 10 ('\n')
3416     // Since ToAscii would convert VK_RETURN to '\r', we need
3417     // to have a special case here.
3418     if (wkey == VK_RETURN){
3419         *character= '\n';
3420         return;
3421     }
3422 
3423     // high order bit in keyboardState indicates whether the key is down
3424     static const BYTE KEY_STATE_DOWN = 0x80;
3425     BYTE    keyboardState[AwtToolkit::KB_STATE_SIZE];
3426     AwtToolkit::GetKeyboardState(keyboardState);
3427 
3428     // apply modifiers to keyboard state if necessary
3429     if (modifiers) {
3430         BOOL shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK;
3431         BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK;
3432         BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK;
3433 
3434         // Windows treats AltGr as Ctrl+Alt
3435         if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
3436             altIsDown = TRUE;
3437             ctrlIsDown = TRUE;
3438         }
3439 
3440         if (shiftIsDown) {
3441             keyboardState[VK_SHIFT] |= KEY_STATE_DOWN;
3442         }
3443 
3444         // fix for 4623376,4737679,4501485,4740906,4708221 (4173679/4122715)
3445         // Here we try to resolve a conflict with ::ToAsciiEx's translating
3446         // ALT+number key combinations. kdm@sarc.spb.su
3447         // yan: Do it for navigation keys only, otherwise some AltGr deadkeys fail.
3448         if( IsNavigationKey(wkey) ) {
3449             keyboardState[VK_MENU] &= ~KEY_STATE_DOWN;
3450         }
3451 
3452         if (ctrlIsDown)
3453         {
3454             if (altIsDown) {
3455                 // bugid 4215009: don't mess with AltGr == Ctrl + Alt
3456                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3457             }
3458             else {
3459                 // bugid 4098210: old event model doesn't have KEY_TYPED
3460                 // events, so try to provide a meaningful character for
3461                 // Ctrl+<key>.  Take Ctrl into account only when we know
3462                 // that Ctrl+<key> will be an ASCII control.  Ignore by
3463                 // default.
3464                 keyboardState[VK_CONTROL] &= ~KEY_STATE_DOWN;
3465 
3466                 // Letters have Ctrl+<letter> counterparts.  According to
3467                 // <winuser.h> VK_A through VK_Z are the same as ASCII
3468                 // 'A' through 'Z'.
3469                 if (wkey >= 'A' && wkey <= 'Z') {
3470                     keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3471                 }
3472                 else {
3473                     // Non-letter controls 033 to 037 are:
3474                     // ^[ (ESC), ^\ (FS), ^] (GS), ^^ (RS), and ^_ (US)
3475 
3476                     // Shift state bits returned by ::VkKeyScan in HIBYTE
3477                     static const UINT _VKS_SHIFT_MASK = 0x01;
3478                     static const UINT _VKS_CTRL_MASK = 0x02;
3479                     static const UINT _VKS_ALT_MASK = 0x04;
3480 
3481                     // Check to see whether there is a meaningful translation
3482                     TCHAR ch;
3483                     short vk;
3484                     for (ch = _T('\033'); ch < _T('\040'); ch++) {
3485                         vk = ::VkKeyScan(ch);
3486                         if (wkey == LOBYTE(vk)) {
3487                             UINT shiftState = HIBYTE(vk);
3488                             if ((shiftState & _VKS_CTRL_MASK) ||
3489                                 (!(shiftState & _VKS_SHIFT_MASK)
3490                                 == !shiftIsDown))
3491                             {
3492                                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3493                             }
3494                             break;
3495                         }
3496                     }
3497                 }
3498             } // ctrlIsDown && altIsDown
3499         } // ctrlIsDown
3500     } // modifiers
3501 
3502     // instead of creating our own conversion tables, I'll let Win32
3503     // convert the character for me.
3504     WORD mbChar;
3505     UINT scancode = ::MapVirtualKey(wkey, 0);
3506     int converted = ::ToAsciiEx(wkey, scancode, keyboardState,
3507                                 &mbChar, 0, GetKeyboardLayout());
3508 
3509     UINT translation;
3510     BOOL deadKeyFlag = (converted == 2);
3511 
3512     // Dead Key
3513     if (converted < 0) {
3514         translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3515     } else
3516     // No translation available -- try known conversions or else punt.
3517     if (converted == 0) {
3518         if (wkey == VK_DELETE) {
3519             translation = '\177';
3520         } else
3521         if (wkey >= VK_NUMPAD0 && wkey <= VK_NUMPAD9) {
3522             translation = '0' + wkey - VK_NUMPAD0;
3523         } else {
3524             translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3525         }
3526     } else
3527     // the caller expects a Unicode character.
3528     if (converted > 0) {
3529         WCHAR unicodeChar[2];
3530         VERIFY(::MultiByteToWideChar(GetCodePage(), MB_PRECOMPOSED,
3531         (LPCSTR)&mbChar, 1, unicodeChar, 1));
3532 
3533         translation = unicodeChar[0];
3534     }
3535     if (ops == SAVE) {
3536         transTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3537                        reinterpret_cast<void*>(static_cast<INT_PTR>(translation)));
3538         deadKeyFlagTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3539                        reinterpret_cast<void*>(static_cast<INT_PTR>(deadKeyFlag)));
3540     }
3541 
3542     *character = translation;
3543     *isDeadKey = deadKeyFlag;
3544     return;
3545 }
3546 
3547 MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt,
3548                                    UINT flags, BOOL system)
3549 {
3550     // VK_PROCESSKEY is a special value which means
3551     //          "Current IME wants to consume this KeyEvent"
3552     // Real key code is saved by IMM32.DLL and can be retrieved by
3553     // calling ImmGetVirtualKey();
3554     if (wkey == VK_PROCESSKEY) {
3555         return mrDoDefault;
3556     }
3557     MSG msg;
3558     InitMessage(&msg, (system ? WM_SYSKEYDOWN : WM_KEYDOWN),
3559                              wkey, MAKELPARAM(repCnt, flags));
3560 
3561     UINT modifiers = GetJavaModifiers();
3562     jint keyLocation = GetKeyLocation(wkey, flags);
3563     BOOL isDeadKey = FALSE;
3564     UINT character;
3565     WindowsKeyToJavaChar(wkey, modifiers, SAVE, &character, &isDeadKey);
3566     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3567     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3568 
3569 
3570     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
3571                              TimeHelper::windowsToUTC(msg.time), jkey, character,
3572                              modifiers, keyLocation, (jlong)wkey, &msg);
3573 
3574     // bugid 4724007: Windows does not create a WM_CHAR for the Del key
3575     // for some reason, so we need to create the KEY_TYPED event on the
3576     // WM_KEYDOWN.  Use null msg so the character doesn't get sent back
3577     // to the native window for processing (this event is synthesized
3578     // for Java - we don't want Windows trying to process it).
3579     if (jkey == java_awt_event_KeyEvent_VK_DELETE) {
3580         SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3581                                  TimeHelper::windowsToUTC(msg.time),
3582                                  java_awt_event_KeyEvent_VK_UNDEFINED,
3583                                  character, modifiers,
3584                                  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
3585     }
3586 
3587     return mrConsume;
3588 }
3589 
3590 MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt,
3591                                  UINT flags, BOOL system)
3592 {
3593 
3594     // VK_PROCESSKEY is a special value which means
3595     //          "Current IME wants to consume this KeyEvent"
3596     // Real key code is saved by IMM32.DLL and can be retrieved by
3597     // calling ImmGetVirtualKey();
3598     if (wkey == VK_PROCESSKEY) {
3599         return mrDoDefault;
3600     }
3601     MSG msg;
3602     InitMessage(&msg, (system ? WM_SYSKEYUP : WM_KEYUP),
3603                              wkey, MAKELPARAM(repCnt, flags));
3604 
3605     UINT modifiers = GetJavaModifiers();
3606     jint keyLocation = GetKeyLocation(wkey, flags);
3607     BOOL isDeadKey = FALSE;
3608     UINT character;
3609     WindowsKeyToJavaChar(wkey, modifiers, LOAD, &character, &isDeadKey);
3610     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3611     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3612 
3613     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
3614                              TimeHelper::windowsToUTC(msg.time), jkey, character,
3615                              modifiers, keyLocation, (jlong)wkey, &msg);
3616     return mrConsume;
3617 }
3618 
3619 MsgRouting AwtComponent::WmInputLangChange(UINT charset, HKL hKeyboardLayout)
3620 {
3621     // Normally we would be able to use charset and TranslateCharSetInfo
3622     // to get a code page that should be associated with this keyboard
3623     // layout change. However, there seems to be an NT 4.0 bug associated
3624     // with the WM_INPUTLANGCHANGE message, which makes the charset parameter
3625     // unreliable, especially on Asian systems. Our workaround uses the
3626     // keyboard layout handle instead.
3627     m_hkl = hKeyboardLayout;
3628     m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID
3629     m_CodePage = LangToCodePage(m_idLang);
3630     BuildDynamicKeyMapTable();  // compute new mappings for VK_OEM
3631     BuildPrimaryDynamicTable();
3632     return mrConsume;           // do not propagate to children
3633 }
3634 
3635 // Convert Language ID to CodePage
3636 UINT AwtComponent::LangToCodePage(LANGID idLang)
3637 {
3638     TCHAR strCodePage[MAX_ACP_STR_LEN];
3639     // use the LANGID to create a LCID
3640     LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
3641     // get the ANSI code page associated with this locale
3642     if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE, strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
3643         return _ttoi(strCodePage);
3644     else
3645         return GetACP();
3646 }
3647 
3648 
3649 MsgRouting AwtComponent::WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL system)
3650 {
3651     // We will simply create Java events here.
3652     WCHAR unicodeChar = character;
3653     MSG msg;
3654     InitMessage(&msg, WM_IME_CHAR, character,
3655                               MAKELPARAM(repCnt, flags));
3656 
3657     jint modifiers = GetJavaModifiers();
3658     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3659                              TimeHelper::windowsToUTC(msg.time),
3660                              java_awt_event_KeyEvent_VK_UNDEFINED,
3661                              unicodeChar, modifiers,
3662                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
3663                              &msg);
3664     return mrConsume;
3665 }
3666 
3667 MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags,
3668                                 BOOL system)
3669 {
3670     // Will only get WmChar messages with DBCS if we create them for
3671     // an Edit class in the WmForwardChar method. These synthesized
3672     // DBCS chars are ok to pass on directly to the default window
3673     // procedure. They've already been filtered through the Java key
3674     // event queue. We will never get the trail byte since the edit
3675     // class will PeekMessage(&msg, hwnd, WM_CHAR, WM_CHAR,
3676     // PM_REMOVE).  I would like to be able to pass this character off
3677     // via WM_AWT_FORWARD_BYTE, but the Edit classes don't seem to
3678     // like that.
3679 
3680     // We will simply create Java events here.
3681     UINT message = system ? WM_SYSCHAR : WM_CHAR;
3682 
3683     // The Alt modifier is reported in the 29th bit of the lParam,
3684     // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
3685     bool alt_is_down = (flags & (1<<13)) != 0;
3686 
3687     // Fix for bug 4141621, corrected by fix for bug 6223726: Alt+space doesn't invoke system menu
3688     // We should not pass this particular combination to Java.
3689 
3690     if (system && alt_is_down) {
3691         if (character == VK_SPACE) {
3692             return mrDoDefault;
3693         }
3694     }
3695 
3696     // If this is a WM_CHAR (non-system) message, then the Alt flag
3697     // indicates that the character was typed using an AltGr key
3698     // (which Windows treats as Ctrl+Alt), so in this case we do NOT
3699     // pass the Ctrl and Alt modifiers to Java, but instead we
3700     // replace them with Java's AltGraph modifier.  Note: the AltGraph
3701     // modifier does not exist in 1.1.x releases.
3702     jint modifiers = GetJavaModifiers();
3703     if (!system && alt_is_down) {
3704         // character typed with AltGraph
3705         modifiers &= ~(java_awt_event_InputEvent_ALT_DOWN_MASK
3706                        | java_awt_event_InputEvent_CTRL_DOWN_MASK);
3707         modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK;
3708     }
3709 
3710     WCHAR unicodeChar = character;
3711 
3712     // Kludge: Combine pending single byte with this char for some Chinese IMEs
3713     if (m_PendingLeadByte != 0) {
3714         character = (m_PendingLeadByte & 0x00ff) | (character << 8);
3715         m_PendingLeadByte = 0;
3716         ::MultiByteToWideChar(GetCodePage(), 0, (CHAR*)&character, 2,
3717                           &unicodeChar, 1);
3718     }
3719 
3720     if (unicodeChar == VK_RETURN) {
3721         // Enter key generates \r in windows, but \n is required in java
3722         unicodeChar = java_awt_event_KeyEvent_VK_ENTER;
3723     }
3724     MSG msg;
3725     InitMessage(&msg, message, character,
3726                               MAKELPARAM(repCnt, flags));
3727     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3728                              TimeHelper::windowsToUTC(msg.time),
3729                              java_awt_event_KeyEvent_VK_UNDEFINED,
3730                              unicodeChar, modifiers,
3731                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
3732                              &msg);
3733     return mrConsume;
3734 }
3735 
3736 MsgRouting AwtComponent::WmForwardChar(WCHAR character, LPARAM lParam,
3737                                        BOOL synthetic)
3738 {
3739     // just post WM_CHAR with unicode key value
3740     DefWindowProc(WM_CHAR, (WPARAM)character, lParam);
3741     return mrConsume;
3742 }
3743 
3744 MsgRouting AwtComponent::WmPaste()
3745 {
3746     return mrDoDefault;
3747 }
3748 
3749 // support IME Composition messages
3750 void AwtComponent::SetCompositionWindow(RECT& r)
3751 {
3752     HWND hwnd = ImmGetHWnd();
3753     HIMC hIMC = ImmGetContext(hwnd);
3754     if (hIMC == NULL) {
3755         return;
3756     }
3757     COMPOSITIONFORM cf = {CFS_DEFAULT, {0, 0}, {0, 0, 0, 0}};
3758     ImmSetCompositionWindow(hIMC, &cf);
3759     ImmReleaseContext(hwnd, hIMC);
3760 }
3761 
3762 void AwtComponent::OpenCandidateWindow(int x, int y)
3763 {
3764     UINT bits = 1;
3765     RECT rc;
3766     GetWindowRect(GetHWnd(), &rc);
3767 
3768     for (int iCandType=0; iCandType<32; iCandType++, bits<<=1) {
3769         if ( m_bitsCandType & bits )
3770             SetCandidateWindow(iCandType, x-rc.left, y-rc.top);
3771     }
3772     if (m_bitsCandType != 0) {
3773         // REMIND: is there any chance GetProxyFocusOwner() returns NULL here?
3774         ::DefWindowProc(ImmGetHWnd(),
3775                         WM_IME_NOTIFY, IMN_OPENCANDIDATE, m_bitsCandType);
3776     }
3777 }
3778 
3779 void AwtComponent::SetCandidateWindow(int iCandType, int x, int y)
3780 {
3781     HWND hwnd = ImmGetHWnd();
3782     HIMC hIMC = ImmGetContext(hwnd);
3783     CANDIDATEFORM cf;
3784     cf.dwIndex = iCandType;
3785     cf.dwStyle = CFS_CANDIDATEPOS;
3786     cf.ptCurrentPos.x = x;
3787     cf.ptCurrentPos.y = y;
3788 
3789     ImmSetCandidateWindow(hIMC, &cf);
3790     ImmReleaseContext(hwnd, hIMC);
3791 }
3792 
3793 MsgRouting AwtComponent::WmImeSetContext(BOOL fSet, LPARAM *lplParam)
3794 {
3795     // If the Windows input context is disabled, do not let Windows
3796     // display any UIs.
3797     HWND hwnd = ImmGetHWnd();
3798     HIMC hIMC = ImmGetContext(hwnd);
3799     if (hIMC == NULL) {
3800         *lplParam = 0;
3801         return mrDoDefault;
3802     }
3803     ImmReleaseContext(hwnd, hIMC);
3804 
3805     if (fSet) {
3806         LPARAM lParam = *lplParam;
3807         if (!m_useNativeCompWindow) {
3808             // stop to draw native composing window.
3809             *lplParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
3810         }
3811     }
3812     return mrDoDefault;
3813 }
3814 
3815 MsgRouting AwtComponent::WmImeNotify(WPARAM subMsg, LPARAM bitsCandType)
3816 {
3817     if (!m_useNativeCompWindow && subMsg == IMN_OPENCANDIDATE) {
3818         m_bitsCandType = bitsCandType;
3819         InquireCandidatePosition();
3820         return mrConsume;
3821     }
3822     return mrDoDefault;
3823 }
3824 
3825 MsgRouting AwtComponent::WmImeStartComposition()
3826 {
3827     if (m_useNativeCompWindow) {
3828         RECT rc;
3829         ::GetClientRect(GetHWnd(), &rc);
3830         SetCompositionWindow(rc);
3831         return mrDoDefault;
3832     } else
3833         return mrConsume;
3834 }
3835 
3836 MsgRouting AwtComponent::WmImeEndComposition()
3837 {
3838     if (m_useNativeCompWindow)   return mrDoDefault;
3839 
3840     SendInputMethodEvent(
3841         java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3842         NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0 );
3843     return mrConsume;
3844 }
3845 
3846 MsgRouting AwtComponent::WmImeComposition(WORD wChar, LPARAM flags)
3847 {
3848     if (m_useNativeCompWindow)   return mrDoDefault;
3849 
3850     int*      bndClauseW = NULL;
3851     jstring*  readingClauseW = NULL;
3852     int*      bndAttrW = NULL;
3853     BYTE*     valAttrW = NULL;
3854     int       cClauseW = 0;
3855     AwtInputTextInfor* textInfor = NULL;
3856 
3857     try {
3858         HWND hwnd = ImmGetHWnd();
3859         HIMC hIMC = ImmGetContext(hwnd);
3860         DASSERT(hIMC!=0);
3861 
3862         textInfor = new AwtInputTextInfor;
3863         textInfor->GetContextData(hIMC, flags);
3864         ImmReleaseContext(hwnd, hIMC);
3865 
3866         jstring jtextString = textInfor->GetText();
3867         /* The conditions to send the input method event to AWT EDT are:
3868            1. Whenever there is a composition message sent regarding whether
3869            the composition text is NULL or not. See details at bug 6222692.
3870            2. When there is a committed message sent, in which case, we have to
3871            check whether the committed string is NULL or not. If the committed string
3872            is NULL, there is no need to send any input method event.
3873            (Minor note: 'jtextString' returned is the merged string in the case of
3874            partial commit.)
3875         */
3876         if ((flags & GCS_RESULTSTR && jtextString != NULL) ||
3877             (flags & GCS_COMPSTR)) {
3878             int       cursorPosW = textInfor->GetCursorPosition();
3879             // In order not to delete the readingClauseW in the catch clause,
3880             // calling GetAttributeInfor before GetClauseInfor.
3881             int       cAttrW = textInfor->GetAttributeInfor(bndAttrW, valAttrW);
3882             cClauseW = textInfor->GetClauseInfor(bndClauseW, readingClauseW);
3883 
3884             /* Send INPUT_METHOD_TEXT_CHANGED event to the WInputMethod which in turn sends
3885                the event to AWT EDT.
3886 
3887                The last two paremeters are set to equal since we don't have recommendations for
3888                the visible position within the current composed text. See details at
3889                java.awt.event.InputMethodEvent.
3890             */
3891             SendInputMethodEvent(java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3892                                  jtextString,
3893                                  cClauseW, bndClauseW, readingClauseW,
3894                                  cAttrW, bndAttrW, valAttrW,
3895                                  textInfor->GetCommittedTextLength(),
3896                                  cursorPosW, cursorPosW);
3897         }
3898     } catch (...) {
3899         // since GetClauseInfor and GetAttributeInfor could throw exception, we have to release
3900         // the pointer here.
3901         delete [] bndClauseW;
3902         delete [] readingClauseW;
3903         delete [] bndAttrW;
3904         delete [] valAttrW;
3905         throw;
3906     }
3907 
3908     /* Free the storage allocated. Since jtextString won't be passed from threads
3909      *  to threads, we just use the local ref and it will be deleted within the destructor
3910      *  of AwtInputTextInfor object.
3911      */
3912     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3913     if (cClauseW && readingClauseW) {
3914         for (int i = 0; i < cClauseW; i ++) {
3915             if (readingClauseW[i]) {
3916                 env->DeleteLocalRef(readingClauseW[i]);
3917             }
3918         }
3919     }
3920     delete [] bndClauseW;
3921     delete [] readingClauseW;
3922     delete [] bndAttrW;
3923     delete [] valAttrW;
3924     delete textInfor;
3925 
3926     return mrConsume;
3927 }
3928 
3929 //
3930 // generate and post InputMethodEvent
3931 //
3932 void AwtComponent::SendInputMethodEvent(jint id, jstring text,
3933                                         int cClause, int* rgClauseBoundary, jstring* rgClauseReading,
3934                                         int cAttrBlock, int* rgAttrBoundary, BYTE *rgAttrValue,
3935                                         int commitedTextLength, int caretPos, int visiblePos)
3936 {
3937     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3938 
3939     // assumption for array type casting
3940     DASSERT(sizeof(int)==sizeof(jint));
3941     DASSERT(sizeof(BYTE)==sizeof(jbyte));
3942 
3943     // caluse information
3944     jintArray clauseBoundary = NULL;
3945     jobjectArray clauseReading = NULL;
3946     if (cClause && rgClauseBoundary && rgClauseReading) {
3947         // convert clause boundary offset array to java array
3948         clauseBoundary = env->NewIntArray(cClause+1);
3949         env->SetIntArrayRegion(clauseBoundary, 0, cClause+1, (jint *)rgClauseBoundary);
3950         DASSERT(!safe_ExceptionOccurred(env));
3951 
3952         // convert clause reading string array to java array
3953         clauseReading = env->NewObjectArray(cClause, JNU_ClassString(env), NULL);
3954         for (int i=0; i<cClause; i++)   env->SetObjectArrayElement(clauseReading, i, rgClauseReading[i]);
3955         DASSERT(!safe_ExceptionOccurred(env));
3956     }
3957 
3958 
3959     // attrubute value definition in WInputMethod.java must be equal to that in IMM.H
3960     DASSERT(ATTR_INPUT==sun_awt_windows_WInputMethod_ATTR_INPUT);
3961     DASSERT(ATTR_TARGET_CONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_CONVERTED);
3962     DASSERT(ATTR_CONVERTED==sun_awt_windows_WInputMethod_ATTR_CONVERTED);
3963     DASSERT(ATTR_TARGET_NOTCONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_NOTCONVERTED);
3964     DASSERT(ATTR_INPUT_ERROR==sun_awt_windows_WInputMethod_ATTR_INPUT_ERROR);
3965 
3966     // attribute information
3967     jintArray attrBoundary = NULL;
3968     jbyteArray attrValue = NULL;
3969     if (cAttrBlock && rgAttrBoundary && rgAttrValue) {
3970         // convert attribute boundary offset array to java array
3971         attrBoundary = env->NewIntArray(cAttrBlock+1);
3972         env->SetIntArrayRegion(attrBoundary, 0, cAttrBlock+1, (jint *)rgAttrBoundary);
3973         DASSERT(!safe_ExceptionOccurred(env));
3974 
3975         // convert attribute value byte array to java array
3976         attrValue = env->NewByteArray(cAttrBlock);
3977         env->SetByteArrayRegion(attrValue, 0, cAttrBlock, (jbyte *)rgAttrValue);
3978         DASSERT(!safe_ExceptionOccurred(env));
3979     }
3980 
3981 
3982     // get global reference of WInputMethod class (run only once)
3983     static jclass wInputMethodCls = NULL;
3984     if (wInputMethodCls == NULL) {
3985         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
3986         DASSERT(wInputMethodClsLocal);
3987         if (wInputMethodClsLocal == NULL) {
3988             /* exception already thrown */
3989             return;
3990         }
3991         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
3992         env->DeleteLocalRef(wInputMethodClsLocal);
3993     }
3994 
3995     // get method ID of sendInputMethodEvent() (run only once)
3996     static jmethodID sendIMEventMid = 0;
3997     if (sendIMEventMid == 0) {
3998         sendIMEventMid =  env->GetMethodID(wInputMethodCls, "sendInputMethodEvent",
3999                                            "(IJLjava/lang/String;[I[Ljava/lang/String;[I[BIII)V");
4000         DASSERT(sendIMEventMid);
4001     }
4002 
4003     // call m_InputMethod.sendInputMethod()
4004     env->CallVoidMethod(m_InputMethod, sendIMEventMid, id, TimeHelper::getMessageTimeUTC(),
4005                         text, clauseBoundary, clauseReading, attrBoundary,
4006                         attrValue, commitedTextLength, caretPos, visiblePos);
4007     if (safe_ExceptionOccurred(env))   env->ExceptionDescribe();
4008     DASSERT(!safe_ExceptionOccurred(env));
4009 
4010 }
4011 
4012 
4013 
4014 //
4015 // Inquires candidate position according to the composed text
4016 //
4017 void AwtComponent::InquireCandidatePosition()
4018 {
4019     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4020 
4021     // get global reference of WInputMethod class (run only once)
4022     static jclass wInputMethodCls = NULL;
4023     if (wInputMethodCls == NULL) {
4024         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
4025         DASSERT(wInputMethodClsLocal);
4026         if (wInputMethodClsLocal == NULL) {
4027             /* exception already thrown */
4028             return;
4029         }
4030         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
4031         env->DeleteLocalRef(wInputMethodClsLocal);
4032     }
4033 
4034     // get method ID of sendInputMethodEvent() (run only once)
4035     static jmethodID inqCandPosMid = 0;
4036     if (inqCandPosMid == 0) {
4037         inqCandPosMid =  env->GetMethodID(wInputMethodCls, "inquireCandidatePosition",
4038                                            "()V");
4039         DASSERT(!safe_ExceptionOccurred(env));
4040         DASSERT(inqCandPosMid);
4041     }
4042 
4043     // call m_InputMethod.sendInputMethod()
4044     jobject candPos = env->CallObjectMethod(m_InputMethod, inqCandPosMid);
4045     DASSERT(!safe_ExceptionOccurred(env));
4046 }
4047 
4048 HWND AwtComponent::ImmGetHWnd()
4049 {
4050     HWND proxy = GetProxyFocusOwner();
4051     return (proxy != NULL) ? proxy : GetHWnd();
4052 }
4053 
4054 HIMC AwtComponent::ImmAssociateContext(HIMC himc)
4055 {
4056     return ::ImmAssociateContext(ImmGetHWnd(), himc);
4057 }
4058 
4059 HWND AwtComponent::GetProxyFocusOwner()
4060 {
4061     AwtWindow *window = GetContainer();
4062     if (window != 0) {
4063         AwtFrame *owner = window->GetOwningFrameOrDialog();
4064         if (owner != 0) {
4065             return owner->GetProxyFocusOwner();
4066         } else if (!window->IsSimpleWindow()) { // isn't an owned simple window
4067             return ((AwtFrame*)window)->GetProxyFocusOwner();
4068         }
4069     }
4070     return (HWND)NULL;
4071 }
4072 
4073 /* Call DefWindowProc for the focus proxy, if any */
4074 void AwtComponent::CallProxyDefWindowProc(UINT message, WPARAM wParam,
4075     LPARAM lParam, LRESULT &retVal, MsgRouting &mr)
4076 {
4077     if (mr != mrConsume)  {
4078         HWND proxy = GetProxyFocusOwner();
4079         if (proxy != NULL) {
4080             retVal = ComCtl32Util::GetInstance().DefWindowProc(NULL, proxy, message, wParam, lParam);
4081             mr = mrConsume;
4082         }
4083     }
4084 }
4085 
4086 MsgRouting AwtComponent::WmCommand(UINT id, HWND hWndChild, UINT notifyCode)
4087 {
4088     /* Menu/Accelerator */
4089     if (hWndChild == 0) {
4090         AwtObject* obj = AwtToolkit::GetInstance().LookupCmdID(id);
4091         if (obj == NULL) {
4092             return mrConsume;
4093         }
4094         DASSERT(((AwtMenuItem*)obj)->GetID() == id);
4095         obj->DoCommand();
4096         return mrConsume;
4097     }
4098     /* Child id notification */
4099     else {
4100         AwtComponent* child = AwtComponent::GetComponent(hWndChild);
4101         if (child) {
4102             child->WmNotify(notifyCode);
4103         }
4104     }
4105     return mrDoDefault;
4106 }
4107 
4108 MsgRouting AwtComponent::WmNotify(UINT notifyCode)
4109 {
4110     return mrDoDefault;
4111 }
4112 
4113 MsgRouting AwtComponent::WmCompareItem(UINT ctrlId,
4114                                        COMPAREITEMSTRUCT &compareInfo,
4115                                        LRESULT &result)
4116 {
4117     AwtComponent* child = AwtComponent::GetComponent(compareInfo.hwndItem);
4118     if (child == this) {
4119         /* DoCallback("handleItemDelete", */
4120     }
4121     else if (child) {
4122         return child->WmCompareItem(ctrlId, compareInfo, result);
4123     }
4124     return mrConsume;
4125 }
4126 
4127 MsgRouting AwtComponent::WmDeleteItem(UINT ctrlId,
4128                                       DELETEITEMSTRUCT &deleteInfo)
4129 {
4130     /*
4131      * Workaround for NT 4.0 bug -- if SetWindowPos is called on a AwtList
4132      * window, a WM_DELETEITEM message is sent to its parent with a window
4133      * handle of one of the list's child windows.  The property lookup
4134      * succeeds, but the HWNDs don't match.
4135      */
4136     if (deleteInfo.hwndItem == NULL) {
4137         return mrConsume;
4138     }
4139     AwtComponent* child = (AwtComponent *)AwtComponent::GetComponent(deleteInfo.hwndItem);
4140 
4141     if (child && child->GetHWnd() != deleteInfo.hwndItem) {
4142         return mrConsume;
4143     }
4144 
4145     if (child == this) {
4146         /*DoCallback("handleItemDelete", */
4147     }
4148     else if (child) {
4149         return child->WmDeleteItem(ctrlId, deleteInfo);
4150     }
4151     return mrConsume;
4152 }
4153 
4154 MsgRouting AwtComponent::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT &drawInfo)
4155 {
4156     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4157 
4158     if (drawInfo.CtlType == ODT_MENU) {
4159         if (drawInfo.itemData != 0) {
4160             AwtMenu* menu = (AwtMenu*)(drawInfo.itemData);
4161             menu->DrawItem(drawInfo);
4162         }
4163     } else {
4164         return OwnerDrawItem(ctrlId, drawInfo);
4165     }
4166     return mrConsume;
4167 }
4168 
4169 MsgRouting AwtComponent::WmMeasureItem(UINT ctrlId,
4170                                        MEASUREITEMSTRUCT &measureInfo)
4171 {
4172     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4173 
4174     if (measureInfo.CtlType == ODT_MENU) {
4175         if (measureInfo.itemData != 0) {
4176             AwtMenu* menu = (AwtMenu*)(measureInfo.itemData);
4177             HDC hDC = ::GetDC(GetHWnd());
4178             /* menu->MeasureItem(env, hDC, measureInfo); */
4179             menu->MeasureItem(hDC, measureInfo);
4180             ::ReleaseDC(GetHWnd(), hDC);
4181         }
4182     } else {
4183         return OwnerMeasureItem(ctrlId, measureInfo);
4184     }
4185     return mrConsume;
4186 }
4187 
4188 MsgRouting AwtComponent::OwnerDrawItem(UINT ctrlId,
4189     DRAWITEMSTRUCT &drawInfo)
4190 {
4191     AwtComponent* child = AwtComponent::GetComponent(drawInfo.hwndItem);
4192     if (child == this) {
4193         /* DoCallback("handleItemDelete", */
4194     } else if (child != NULL) {
4195         return child->WmDrawItem(ctrlId, drawInfo);
4196     }
4197     return mrConsume;
4198 }
4199 
4200 MsgRouting AwtComponent::OwnerMeasureItem(UINT ctrlId,
4201     MEASUREITEMSTRUCT &measureInfo)
4202 {
4203     HWND  hChild = ::GetDlgItem(GetHWnd(), measureInfo.CtlID);
4204     AwtComponent* child = AwtComponent::GetComponent(hChild);
4205     /*
4206      * If the parent cannot find the child's instance from its handle,
4207      * maybe the child is in its creation.  So the child must be searched
4208      * from the list linked before the child's creation.
4209      */
4210     if (child == NULL) {
4211         child = SearchChild((UINT)ctrlId);
4212     }
4213 
4214     if (child == this) {
4215     /* DoCallback("handleItemDelete",  */
4216     }
4217     else if (child) {
4218         return child->WmMeasureItem(ctrlId, measureInfo);
4219     }
4220     return mrConsume;
4221 }
4222 
4223 /* for WmDrawItem method of Label, Button and Checkbox */
4224 void AwtComponent::DrawWindowText(HDC hDC, jobject font, jstring text,
4225                                   int x, int y)
4226 {
4227     int nOldBkMode = ::SetBkMode(hDC,TRANSPARENT);
4228     DASSERT(nOldBkMode != 0);
4229     AwtFont::drawMFString(hDC, font, text, x, y, GetCodePage());
4230     VERIFY(::SetBkMode(hDC,nOldBkMode));
4231 }
4232 
4233 /*
4234  * Draw text in gray (the color being set to COLOR_GRAYTEXT) when the
4235  * component is disabled.  Used only for label, checkbox and button in
4236  * OWNER_DRAW.  It draws the text in emboss.
4237  */
4238 void AwtComponent::DrawGrayText(HDC hDC, jobject font, jstring text,
4239                                 int x, int y)
4240 {
4241     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHILIGHT));
4242     AwtComponent::DrawWindowText(hDC, font, text, x+1, y+1);
4243     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
4244     AwtComponent::DrawWindowText(hDC, font, text, x, y);
4245 }
4246 
4247 /* for WmMeasureItem method of List and Choice */
4248 jstring AwtComponent::GetItemString(JNIEnv *env, jobject target, jint index)
4249 {
4250     jstring str = (jstring)JNU_CallMethodByName(env, NULL, target, "getItemImpl",
4251                                                 "(I)Ljava/lang/String;",
4252                                                 index).l;
4253     DASSERT(!safe_ExceptionOccurred(env));
4254     return str;
4255 }
4256 
4257 /* for WmMeasureItem method of List and Choice */
4258 void AwtComponent::MeasureListItem(JNIEnv *env,
4259                                    MEASUREITEMSTRUCT &measureInfo)
4260 {
4261     if (env->EnsureLocalCapacity(1) < 0) {
4262         return;
4263     }
4264     jobject dimension = PreferredItemSize(env);
4265     DASSERT(dimension);
4266     measureInfo.itemWidth =
4267       env->GetIntField(dimension, AwtDimension::widthID);
4268     measureInfo.itemHeight =
4269       env->GetIntField(dimension, AwtDimension::heightID);
4270     env->DeleteLocalRef(dimension);
4271 }
4272 
4273 /* for WmDrawItem method of List and Choice */
4274 void AwtComponent::DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo)
4275 {
4276     if (env->EnsureLocalCapacity(3) < 0) {
4277         return;
4278     }
4279     jobject peer = GetPeer(env);
4280     jobject target = env->GetObjectField(peer, AwtObject::targetID);
4281 
4282     HDC hDC = drawInfo.hDC;
4283     RECT rect = drawInfo.rcItem;
4284 
4285     BOOL bEnabled = isEnabled();
4286     BOOL unfocusableChoice = (drawInfo.itemState & ODS_COMBOBOXEDIT) && !IsFocusable();
4287     DWORD crBack, crText;
4288     if (drawInfo.itemState & ODS_SELECTED){
4289         /* Set background and text colors for selected item */
4290         crBack = ::GetSysColor (COLOR_HIGHLIGHT);
4291         crText = ::GetSysColor (COLOR_HIGHLIGHTTEXT);
4292     } else {
4293         /* Set background and text colors for unselected item */
4294         crBack = GetBackgroundColor();
4295         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4296     }
4297     if (unfocusableChoice) {
4298         //6190728. Shouldn't draw selection field (edit control) of an owner-drawn combo box.
4299         crBack = GetBackgroundColor();
4300         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4301     }
4302 
4303     /* Fill item rectangle with background color */
4304     HBRUSH hbrBack = ::CreateSolidBrush (crBack);
4305     DASSERT(hbrBack);
4306     /* 6190728. Shouldn't draw any kind of rectangle around selection field
4307      * (edit control) of an owner-drawn combo box while unfocusable
4308      */
4309     if (!unfocusableChoice){
4310         VERIFY(::FillRect (hDC, &rect, hbrBack));
4311     }
4312     VERIFY(::DeleteObject (hbrBack));
4313 
4314     /* Set current background and text colors */
4315     ::SetBkColor (hDC, crBack);
4316     ::SetTextColor (hDC, crText);
4317 
4318     /*draw string (with left margin of 1 point) */
4319     if ((int) (drawInfo.itemID) >= 0) {
4320             jobject font = GET_FONT(target, peer);
4321             jstring text = GetItemString(env, target, drawInfo.itemID);
4322             SIZE size = AwtFont::getMFStringSize(hDC, font, text);
4323             AwtFont::drawMFString(hDC, font, text,
4324                                   (GetRTL()) ? rect.right - size.cx - 1
4325                                              : rect.left + 1,
4326                                   (rect.top + rect.bottom - size.cy) / 2,
4327                                   GetCodePage());
4328             env->DeleteLocalRef(font);
4329             env->DeleteLocalRef(text);
4330     }
4331     if ((drawInfo.itemState & ODS_FOCUS)  &&
4332         (drawInfo.itemAction & (ODA_FOCUS | ODA_DRAWENTIRE))) {
4333       if (!unfocusableChoice){
4334           VERIFY(::DrawFocusRect(hDC, &rect));
4335       }
4336     }
4337     env->DeleteLocalRef(target);
4338 }
4339 
4340 /* for MeasureListItem method and WmDrawItem method of Checkbox */
4341 jint AwtComponent::GetFontHeight(JNIEnv *env)
4342 {
4343     if (env->EnsureLocalCapacity(4) < 0) {
4344         return NULL;
4345     }
4346     jobject self = GetPeer(env);
4347     jobject target = env->GetObjectField(self, AwtObject::targetID);
4348 
4349     jobject font = GET_FONT(target, self);
4350     jobject toolkit = env->CallObjectMethod(target,
4351                                             AwtComponent::getToolkitMID);
4352 
4353     DASSERT(!safe_ExceptionOccurred(env));
4354 
4355     jobject fontMetrics =
4356         env->CallObjectMethod(toolkit, AwtToolkit::getFontMetricsMID, font);
4357 
4358     DASSERT(!safe_ExceptionOccurred(env));
4359 
4360     jint height = env->CallIntMethod(fontMetrics, AwtFont::getHeightMID);
4361     DASSERT(!safe_ExceptionOccurred(env));
4362 
4363     env->DeleteLocalRef(target);
4364     env->DeleteLocalRef(font);
4365     env->DeleteLocalRef(toolkit);
4366     env->DeleteLocalRef(fontMetrics);
4367 
4368     return height;
4369 }
4370 
4371 // If you override WmPrint, make sure to save a copy of the DC on the GDI
4372 // stack to be restored in WmPrintClient. Windows mangles the DC in
4373 // ::DefWindowProc.
4374 MsgRouting AwtComponent::WmPrint(HDC hDC, LPARAM flags)
4375 {
4376     /*
4377      * DefWindowProc for WM_PRINT changes DC parameters, so we have
4378      * to restore it ourselves. Otherwise it will cause problems
4379      * when several components are printed to the same DC.
4380      */
4381     int nOriginalDC = ::SaveDC(hDC);
4382     DASSERT(nOriginalDC != 0);
4383 
4384     if (flags & PRF_NONCLIENT) {
4385 
4386         VERIFY(::SaveDC(hDC));
4387 
4388         DefWindowProc(WM_PRINT, (WPARAM)hDC,
4389                       (flags & (PRF_NONCLIENT
4390                                 | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4391 
4392         VERIFY(::RestoreDC(hDC, -1));
4393 
4394         // Special case for components with a sunken border. Windows does not
4395         // print the border correctly on PCL printers, so we have to do it ourselves.
4396         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4397             RECT r;
4398             VERIFY(::GetWindowRect(GetHWnd(), &r));
4399             VERIFY(::OffsetRect(&r, -r.left, -r.top));
4400             VERIFY(::DrawEdge(hDC, &r, EDGE_SUNKEN, BF_RECT));
4401         }
4402     }
4403 
4404     if (flags & PRF_CLIENT) {
4405 
4406         /*
4407          * Special case for components with a sunken border.
4408          * Windows prints a client area without offset to a border width.
4409          * We will first print the non-client area with the original offset,
4410          * then the client area with a corrected offset.
4411          */
4412         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4413 
4414             int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE);
4415             int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE);
4416 
4417             VERIFY(::OffsetWindowOrgEx(hDC, -nEdgeWidth, -nEdgeHeight, NULL));
4418 
4419             // Save a copy of the DC for WmPrintClient
4420             VERIFY(::SaveDC(hDC));
4421 
4422             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4423                           (flags & (PRF_CLIENT
4424                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4425 
4426             VERIFY(::OffsetWindowOrgEx(hDC, nEdgeWidth, nEdgeHeight, NULL));
4427 
4428         } else {
4429 
4430             // Save a copy of the DC for WmPrintClient
4431             VERIFY(::SaveDC(hDC));
4432             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4433                           (flags & (PRF_CLIENT
4434                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4435         }
4436     }
4437 
4438     if (flags & (PRF_CHILDREN | PRF_OWNED)) {
4439         DefWindowProc(WM_PRINT, (WPARAM) hDC,
4440                       (flags & ~PRF_CLIENT & ~PRF_NONCLIENT));
4441     }
4442 
4443     VERIFY(::RestoreDC(hDC, nOriginalDC));
4444 
4445     return mrConsume;
4446 }
4447 
4448 // If you override WmPrintClient, make sure to obtain a valid copy of
4449 // the DC from the GDI stack. The copy of the DC should have been placed
4450 // there by WmPrint. Windows mangles the DC in ::DefWindowProc.
4451 MsgRouting AwtComponent::WmPrintClient(HDC hDC, LPARAM)
4452 {
4453     // obtain valid DC from GDI stack
4454     ::RestoreDC(hDC, -1);
4455 
4456     return mrDoDefault;
4457 }
4458 
4459 MsgRouting AwtComponent::WmNcCalcSize(BOOL fCalcValidRects,
4460                                       LPNCCALCSIZE_PARAMS lpncsp,
4461                                       LRESULT &retVal)
4462 {
4463     return mrDoDefault;
4464 }
4465 
4466 MsgRouting AwtComponent::WmNcPaint(HRGN hrgn)
4467 {
4468     return mrDoDefault;
4469 }
4470 
4471 MsgRouting AwtComponent::WmNcHitTest(UINT x, UINT y, LRESULT &retVal)
4472 {
4473     return mrDoDefault;
4474 }
4475 
4476 /**
4477  * WmQueryNewPalette is called whenever our component is coming to
4478  * the foreground; this gives us an opportunity to install our
4479  * custom palette.  If this install actually changes entries in
4480  * the system palette, then we get a further call to WmPaletteChanged
4481  * (but note that we only need to realize our palette once).
4482  */
4483 MsgRouting AwtComponent::WmQueryNewPalette(LRESULT &retVal)
4484 {
4485     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4486     m_QueryNewPaletteCalled = TRUE;
4487     HDC hDC = ::GetDC(GetHWnd());
4488     DASSERT(hDC);
4489     AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4490     AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4491     ::ReleaseDC(GetHWnd(), hDC);
4492     // We must realize the palettes of all of our DC's
4493     // There is sometimes a problem where the realization of
4494     // our temporary hDC here does not actually do what
4495     // we want.  Not clear why, but presumably fallout from
4496     // our use of several simultaneous hDC's.
4497     activeDCList.RealizePalettes(screen);
4498     // Do not invalidate here; if the palette
4499     // has not changed we will get an extra repaint
4500     retVal = TRUE;
4501 
4502     return mrDoDefault;
4503 }
4504 
4505 /**
4506  * We should not need to track this event since we handle our
4507  * palette management effectively in the WmQueryNewPalette and
4508  * WmPaletteChanged methods.  However, there seems to be a bug
4509  * on some win32 systems (e.g., NT4) whereby the palette
4510  * immediately after a displayChange is not yet updated to its
4511  * final post-display-change values (hence we adjust our palette
4512  * using the wrong system palette entries), then the palette is
4513  * updated, but a WM_PALETTECHANGED message is never sent.
4514  * By tracking the ISCHANGING message as well (and by tracking
4515  * displayChange events in the AwtToolkit object), we can account
4516  * for this error by forcing our WmPaletteChanged method to be
4517  * called and thereby realizing our logical palette and updating
4518  * our dynamic colorModel object.
4519  */
4520 MsgRouting AwtComponent::WmPaletteIsChanging(HWND hwndPalChg)
4521 {
4522     if (AwtToolkit::GetInstance().HasDisplayChanged()) {
4523         WmPaletteChanged(hwndPalChg);
4524         AwtToolkit::GetInstance().ResetDisplayChanged();
4525     }
4526     return mrDoDefault;
4527 }
4528 
4529 MsgRouting AwtComponent::WmPaletteChanged(HWND hwndPalChg)
4530 {
4531     // We need to re-realize our palette here (unless we're the one
4532     // that was realizing it in the first place).  That will let us match the
4533     // remaining colors in the system palette as best we can.  We always
4534     // invalidate because the palette will have changed when we receive this
4535     // message.
4536 
4537     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4538     if (hwndPalChg != GetHWnd()) {
4539         HDC hDC = ::GetDC(GetHWnd());
4540         DASSERT(hDC);
4541         AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4542         AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4543         ::ReleaseDC(GetHWnd(), hDC);
4544         // We must realize the palettes of all of our DC's
4545         activeDCList.RealizePalettes(screen);
4546     }
4547     if (AwtWin32GraphicsDevice::UpdateSystemPalette(screen)) {
4548         AwtWin32GraphicsDevice::UpdateDynamicColorModel(screen);
4549     }
4550     Invalidate(NULL);
4551     return mrDoDefault;
4552 }
4553 
4554 MsgRouting AwtComponent::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss)
4555 {
4556     DASSERT(!IsBadReadPtr(lpss, sizeof(STYLESTRUCT)));
4557     return mrDoDefault;
4558 }
4559 
4560 MsgRouting AwtComponent::WmSettingChange(UINT wFlag, LPCTSTR pszSection)
4561 {
4562     DASSERT(!IsBadStringPtr(pszSection, 20));
4563     DTRACE_PRINTLN2("WM_SETTINGCHANGE: wFlag=%d pszSection=%s", (int)wFlag, pszSection);
4564     return mrDoDefault;
4565 }
4566 
4567 HDC AwtComponent::GetDCFromComponent()
4568 {
4569     GetDCReturnStruct *hdcStruct =
4570         (GetDCReturnStruct*)SendMessage(WM_AWT_GETDC);
4571     HDC hdc;
4572     if (hdcStruct) {
4573         if (hdcStruct->gdiLimitReached) {
4574             if (jvm != NULL) {
4575                 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4576                 if (env != NULL && !safe_ExceptionOccurred(env)) {
4577                     JNU_ThrowByName(env, "java/awt/AWTError",
4578                         "HDC creation failure - " \
4579                         "exceeded maximum GDI resources");
4580                 }
4581             }
4582         }
4583         hdc = hdcStruct->hDC;
4584         delete hdcStruct;
4585     } else {
4586         hdc = NULL;
4587     }
4588     return hdc;
4589 }
4590 
4591 void AwtComponent::FillBackground(HDC hMemoryDC, SIZE &size)
4592 {
4593     RECT eraseR = { 0, 0, size.cx, size.cy };
4594     VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush()));
4595 }
4596 
4597 void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
4598 {
4599     if (!bitmapBits) {
4600         return;
4601     }
4602 
4603     DWORD* dest = (DWORD*)bitmapBits;
4604     //XXX: might be optimized to use one loop (cy*cx -> 0)
4605     for (int i = 0; i < size.cy; i++ ) {
4606         for (int j = 0; j < size.cx; j++ ) {
4607             ((BYTE*)(dest++))[3] = alpha;
4608         }
4609     }
4610 }
4611 
4612 jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
4613     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4614 
4615     if (!::IsWindowVisible(GetHWnd())) {
4616         return NULL;
4617     }
4618 
4619     HDC hdc = GetDCFromComponent();
4620     if (!hdc) {
4621         return NULL;
4622     }
4623     HDC hMemoryDC = ::CreateCompatibleDC(hdc);
4624     void *bitmapBits = NULL;
4625     HBITMAP hBitmap = BitmapUtil::CreateARGBBitmap(size.cx, size.cy, &bitmapBits);
4626     HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemoryDC, hBitmap);
4627     SendMessage(WM_AWT_RELEASEDC, (WPARAM)hdc);
4628 
4629     FillBackground(hMemoryDC, size);
4630 
4631     VERIFY(::SetWindowOrgEx(hMemoryDC, loc.cx, loc.cy, NULL));
4632 
4633     // Don't bother with PRF_CHECKVISIBLE because we called IsWindowVisible
4634     // above.
4635     SendMessage(WM_PRINT, (WPARAM)hMemoryDC, PRF_CLIENT | PRF_NONCLIENT);
4636 
4637     // First make sure the system completed any drawing to the bitmap.
4638     ::GdiFlush();
4639 
4640     // WM_PRINT does not fill the alpha-channel of the ARGB bitmap
4641     // leaving it equal to zero. Hence we need to fill it manually. Otherwise
4642     // the pixels will be considered transparent when interpreting the data.
4643     FillAlpha(bitmapBits, size, alpha);
4644 
4645     ::SelectObject(hMemoryDC, hOldBitmap);
4646 
4647     BITMAPINFO bmi;
4648     memset(&bmi, 0, sizeof(BITMAPINFO));
4649     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
4650     bmi.bmiHeader.biWidth = size.cx;
4651     bmi.bmiHeader.biHeight = -size.cy;
4652     bmi.bmiHeader.biPlanes = 1;
4653     bmi.bmiHeader.biBitCount = 32;
4654     bmi.bmiHeader.biCompression = BI_RGB;
4655 
4656     jobject localPixelArray = env->NewIntArray(size.cx * size.cy);
4657     jintArray pixelArray = NULL;
4658     if (localPixelArray != NULL) {
4659         pixelArray = (jintArray)env->NewGlobalRef(localPixelArray);
4660         env->DeleteLocalRef(localPixelArray); localPixelArray = NULL;
4661 
4662         jboolean isCopy;
4663         jint *pixels = env->GetIntArrayElements(pixelArray, &isCopy);
4664 
4665         ::GetDIBits(hMemoryDC, hBitmap, 0, size.cy, (LPVOID)pixels, &bmi,
4666                     DIB_RGB_COLORS);
4667 
4668         env->ReleaseIntArrayElements(pixelArray, pixels, 0);
4669     }
4670 
4671     VERIFY(::DeleteObject(hBitmap));
4672     VERIFY(::DeleteDC(hMemoryDC));
4673 
4674     return pixelArray;
4675 }
4676 
4677 void* AwtComponent::SetNativeFocusOwner(void *self) {
4678     if (self == NULL) {
4679         // It means that the KFM wants to set focus to null
4680         sm_focusOwner = NULL;
4681         return NULL;
4682     }
4683 
4684     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4685 
4686     AwtComponent *c = NULL;
4687     jobject peer = (jobject)self;
4688 
4689     PDATA pData;
4690     JNI_CHECK_NULL_GOTO(peer, "peer", ret);
4691     pData = JNI_GET_PDATA(peer);
4692     if (pData == NULL) {
4693         goto ret;
4694     }
4695     c = (AwtComponent *)pData;
4696 
4697 ret:
4698     if (c && ::IsWindow(c->GetHWnd())) {
4699         sm_focusOwner = c->GetHWnd();
4700     } else {
4701         sm_focusOwner = NULL;
4702     }
4703     env->DeleteGlobalRef(peer);
4704     return NULL;
4705 }
4706 
4707 void* AwtComponent::GetNativeFocusedWindow() {
4708     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4709     AwtComponent *comp =
4710         AwtComponent::GetComponent(AwtComponent::GetFocusedWindow());
4711     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4712 }
4713 
4714 void* AwtComponent::GetNativeFocusOwner() {
4715     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4716     AwtComponent *comp =
4717         AwtComponent::GetComponent(AwtComponent::sm_focusOwner);
4718     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4719 }
4720 
4721 AwtComponent* AwtComponent::SearchChild(UINT id) {
4722     ChildListItem* child;
4723     for (child = m_childList; child != NULL;child = child->m_next) {
4724         if (child->m_ID == id)
4725             return child->m_Component;
4726     }
4727     /*
4728      * DASSERT(FALSE);
4729      * This should not be happend if all children are recorded
4730      */
4731     return NULL;        /* make compiler happy */
4732 }
4733 
4734 void AwtComponent::RemoveChild(UINT id) {
4735     ChildListItem* child = m_childList;
4736     ChildListItem* lastChild = NULL;
4737     while (child != NULL) {
4738         if (child->m_ID == id) {
4739             if (lastChild == NULL) {
4740                 m_childList = child->m_next;
4741             } else {
4742                 lastChild->m_next = child->m_next;
4743             }
4744             child->m_next = NULL;
4745             DASSERT(child != NULL);
4746             delete child;
4747             return;
4748         }
4749         lastChild = child;
4750         child = child->m_next;
4751     }
4752 }
4753 
4754 void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked,
4755                                 jint modifiers, jint keyLocation, jlong nativeCode, MSG *pMsg)
4756 {
4757     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4758     CriticalSection::Lock l(GetLock());
4759     if (GetPeer(env) == NULL) {
4760         /* event received during termination. */
4761         return;
4762     }
4763 
4764     static jclass keyEventCls;
4765     if (keyEventCls == NULL) {
4766         jclass keyEventClsLocal = env->FindClass("java/awt/event/KeyEvent");
4767         DASSERT(keyEventClsLocal);
4768         if (keyEventClsLocal == NULL) {
4769             /* exception already thrown */
4770             return;
4771         }
4772         keyEventCls = (jclass)env->NewGlobalRef(keyEventClsLocal);
4773         env->DeleteLocalRef(keyEventClsLocal);
4774     }
4775 
4776     static jmethodID keyEventConst;
4777     if (keyEventConst == NULL) {
4778         keyEventConst =  env->GetMethodID(keyEventCls, "<init>",
4779                                           "(Ljava/awt/Component;IJIICI)V");
4780         DASSERT(keyEventConst);
4781     }
4782     if (env->EnsureLocalCapacity(2) < 0) {
4783         return;
4784     }
4785     jobject target = GetTarget(env);
4786     jobject keyEvent = env->NewObject(keyEventCls, keyEventConst, target,
4787                                       id, when, modifiers, raw, cooked,
4788                                       keyLocation);
4789     if (safe_ExceptionOccurred(env)) env->ExceptionDescribe();
4790     DASSERT(!safe_ExceptionOccurred(env));
4791     DASSERT(keyEvent != NULL);
4792     env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode);
4793     if( nativeCode && nativeCode < 256 ) {
4794         env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode));
4795         env->SetLongField(keyEvent, AwtKeyEvent::extendedKeyCodeID, (jlong)(dynPrimaryKeymap[nativeCode].jkey));
4796         if( nativeCode < 255 ) {
4797             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(dynPrimaryKeymap[nativeCode].scancode));
4798         }else if( pMsg != NULL ) {
4799             // unknown key with virtual keycode 0xFF.
4800             // Its scancode is not in the table, pickup it from the message.
4801             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(HIWORD(pMsg->lParam) & 0xFF));
4802         }
4803     }
4804     if (pMsg != NULL) {
4805         AwtAWTEvent::saveMSG(env, pMsg, keyEvent);
4806     }
4807     SendEvent(keyEvent);
4808 
4809     env->DeleteLocalRef(keyEvent);
4810     env->DeleteLocalRef(target);
4811 }
4812 
4813 void
4814 AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when,
4815                                        jint raw, jint cooked,
4816                                        jint modifiers, jint keyLocation,
4817                                        jlong nativeCode,
4818                                        MSG *msg)
4819 {
4820     /*
4821      * if focus owner is null, but focused window isn't
4822      * we will send key event to focused window
4823      */
4824     HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : AwtComponent::GetFocusedWindow());
4825 
4826     if (hwndTarget == GetHWnd()) {
4827         SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, nativeCode, msg);
4828     } else {
4829         AwtComponent *target = NULL;
4830         if (hwndTarget != NULL) {
4831             target = AwtComponent::GetComponent(hwndTarget);
4832             if (target == NULL) {
4833                 target = this;
4834             }
4835         }
4836         if (target != NULL) {
4837             target->SendKeyEvent(id, when, raw, cooked, modifiers,
4838               keyLocation, nativeCode, msg);
4839         }
4840     }
4841 }
4842 
4843 void AwtComponent::SetDragCapture(UINT flags)
4844 {
4845     // don't want to interfere with other controls
4846     if (::GetCapture() == NULL) {
4847         ::SetCapture(GetHWnd());
4848     }
4849 }
4850 
4851 void AwtComponent::ReleaseDragCapture(UINT flags)
4852 {
4853     if ((::GetCapture() == GetHWnd()) && ((flags & ALL_MK_BUTTONS) == 0)) {
4854         // user has released all buttons, so release the capture
4855         ::ReleaseCapture();
4856     }
4857 }
4858 
4859 void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y,
4860                                   jint modifiers, jint clickCount,
4861                                   jboolean popupTrigger, jint button,
4862                                   MSG *pMsg)
4863 {
4864     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4865     CriticalSection::Lock l(GetLock());
4866     if (GetPeer(env) == NULL) {
4867         /* event received during termination. */
4868         return;
4869     }
4870 
4871     static jclass mouseEventCls;
4872     if (mouseEventCls == NULL) {
4873         jclass mouseEventClsLocal =
4874             env->FindClass("java/awt/event/MouseEvent");
4875         if (!mouseEventClsLocal) {
4876             /* exception already thrown */
4877             return;
4878         }
4879         mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal);
4880         env->DeleteLocalRef(mouseEventClsLocal);
4881     }
4882     RECT insets;
4883     GetInsets(&insets);
4884 
4885     static jmethodID mouseEventConst;
4886     if (mouseEventConst == NULL) {
4887         mouseEventConst =
4888             env->GetMethodID(mouseEventCls, "<init>",
4889                  "(Ljava/awt/Component;IJIIIIIIZI)V");
4890         DASSERT(mouseEventConst);
4891     }
4892     if (env->EnsureLocalCapacity(2) < 0) {
4893         return;
4894     }
4895     jobject target = GetTarget(env);
4896     DWORD curMousePos = ::GetMessagePos();
4897     int xAbs = GET_X_LPARAM(curMousePos);
4898     int yAbs = GET_Y_LPARAM(curMousePos);
4899     jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
4900                                         target,
4901                                         id, when, modifiers,
4902                                         x+insets.left, y+insets.top,
4903                     xAbs, yAbs,
4904                                         clickCount, popupTrigger, button);
4905 
4906     if (safe_ExceptionOccurred(env)) {
4907         env->ExceptionDescribe();
4908         env->ExceptionClear();
4909     }
4910 
4911     DASSERT(mouseEvent != NULL);
4912     if (pMsg != 0) {
4913         AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
4914     }
4915     SendEvent(mouseEvent);
4916 
4917     env->DeleteLocalRef(mouseEvent);
4918     env->DeleteLocalRef(target);
4919 }
4920 
4921 void
4922 AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
4923                                   jint modifiers, jint clickCount,
4924                                   jboolean popupTrigger, jint scrollType,
4925                                   jint scrollAmount, jint roundedWheelRotation,
4926                                   jdouble preciseWheelRotation, MSG *pMsg)
4927 {
4928     /* Code based not so loosely on AwtComponent::SendMouseEvent */
4929     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4930     CriticalSection::Lock l(GetLock());
4931     if (GetPeer(env) == NULL) {
4932         /* event received during termination. */
4933         return;
4934     }
4935 
4936     static jclass mouseWheelEventCls;
4937     if (mouseWheelEventCls == NULL) {
4938         jclass mouseWheelEventClsLocal =
4939             env->FindClass("java/awt/event/MouseWheelEvent");
4940         if (!mouseWheelEventClsLocal) {
4941             /* exception already thrown */
4942             return;
4943         }
4944         mouseWheelEventCls = (jclass)env->NewGlobalRef(mouseWheelEventClsLocal);
4945         env->DeleteLocalRef(mouseWheelEventClsLocal);
4946     }
4947     RECT insets;
4948     GetInsets(&insets);
4949 
4950     static jmethodID mouseWheelEventConst;
4951     if (mouseWheelEventConst == NULL) {
4952         mouseWheelEventConst =
4953             env->GetMethodID(mouseWheelEventCls, "<init>",
4954                            "(Ljava/awt/Component;IJIIIIIIZIIID)V");
4955         DASSERT(mouseWheelEventConst);
4956     }
4957     if (env->EnsureLocalCapacity(2) < 0) {
4958         return;
4959     }
4960     jobject target = GetTarget(env);
4961     DTRACE_PRINTLN("creating MWE in JNI");
4962 
4963     jobject mouseWheelEvent = env->NewObject(mouseWheelEventCls,
4964                                              mouseWheelEventConst,
4965                                              target,
4966                                              id, when, modifiers,
4967                                              x+insets.left, y+insets.top,
4968                                              0, 0,
4969                                              clickCount, popupTrigger,
4970                                              scrollType, scrollAmount,
4971                                              roundedWheelRotation, preciseWheelRotation);
4972     if (safe_ExceptionOccurred(env)) {
4973         env->ExceptionDescribe();
4974         env->ExceptionClear();
4975     }
4976     DASSERT(mouseWheelEvent != NULL);
4977     if (pMsg != NULL) {
4978         AwtAWTEvent::saveMSG(env, pMsg, mouseWheelEvent);
4979     }
4980     SendEvent(mouseWheelEvent);
4981 
4982     env->DeleteLocalRef(mouseWheelEvent);
4983     env->DeleteLocalRef(target);
4984 }
4985 
4986 void AwtComponent::SendFocusEvent(jint id, HWND opposite)
4987 {
4988     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4989 
4990     CriticalSection::Lock l(GetLock());
4991     if (GetPeer(env) == NULL) {
4992         /* event received during termination. */
4993         return;
4994     }
4995 
4996     static jclass focusEventCls;
4997     if (focusEventCls == NULL) {
4998         jclass focusEventClsLocal
4999             = env->FindClass("java/awt/event/FocusEvent");
5000         DASSERT(focusEventClsLocal);
5001         if (focusEventClsLocal == NULL) {
5002             /* exception already thrown */
5003             return;
5004         }
5005         focusEventCls = (jclass)env->NewGlobalRef(focusEventClsLocal);
5006         env->DeleteLocalRef(focusEventClsLocal);
5007     }
5008 
5009     static jmethodID focusEventConst;
5010     if (focusEventConst == NULL) {
5011         focusEventConst =
5012             env->GetMethodID(focusEventCls, "<init>",
5013                              "(Ljava/awt/Component;IZLjava/awt/Component;)V");
5014         DASSERT(focusEventConst);
5015     }
5016 
5017     static jclass sequencedEventCls;
5018     if (sequencedEventCls == NULL) {
5019         jclass sequencedEventClsLocal =
5020             env->FindClass("java/awt/SequencedEvent");
5021         DASSERT(sequencedEventClsLocal);
5022         if (sequencedEventClsLocal == NULL) {
5023             /* exception already thrown */
5024             return;
5025         }
5026         sequencedEventCls =
5027             (jclass)env->NewGlobalRef(sequencedEventClsLocal);
5028         env->DeleteLocalRef(sequencedEventClsLocal);
5029     }
5030 
5031     static jmethodID sequencedEventConst;
5032     if (sequencedEventConst == NULL) {
5033         sequencedEventConst =
5034             env->GetMethodID(sequencedEventCls, "<init>",
5035                              "(Ljava/awt/AWTEvent;)V");
5036     }
5037 
5038     if (env->EnsureLocalCapacity(3) < 0) {
5039         return;
5040     }
5041 
5042     jobject target = GetTarget(env);
5043     jobject jOpposite = NULL;
5044     if (opposite != NULL) {
5045         AwtComponent *awtOpposite = AwtComponent::GetComponent(opposite);
5046         if (awtOpposite != NULL) {
5047             jOpposite = awtOpposite->GetTarget(env);
5048         }
5049     }
5050     jobject focusEvent = env->NewObject(focusEventCls, focusEventConst,
5051                                         target, id, JNI_FALSE, jOpposite);
5052     DASSERT(!safe_ExceptionOccurred(env));
5053     DASSERT(focusEvent != NULL);
5054     if (jOpposite != NULL) {
5055         env->DeleteLocalRef(jOpposite); jOpposite = NULL;
5056     }
5057     env->DeleteLocalRef(target); target = NULL;
5058 
5059     jobject sequencedEvent = env->NewObject(sequencedEventCls,
5060                                             sequencedEventConst,
5061                                             focusEvent);
5062     DASSERT(!safe_ExceptionOccurred(env));
5063     DASSERT(sequencedEvent != NULL);
5064     env->DeleteLocalRef(focusEvent); focusEvent = NULL;
5065 
5066     SendEvent(sequencedEvent);
5067 
5068     env->DeleteLocalRef(sequencedEvent);
5069 }
5070 
5071 /*
5072  * Forward a filtered event directly to the subclassed window.
5073  * This method is needed so that DefWindowProc is invoked on the
5074  * component's owning thread.
5075  */
5076 MsgRouting AwtComponent::HandleEvent(MSG *msg, BOOL)
5077 {
5078     DefWindowProc(msg->message, msg->wParam, msg->lParam);
5079     delete msg;
5080     return mrConsume;
5081 }
5082 
5083 /* Post a WM_AWT_HANDLE_EVENT message which invokes HandleEvent
5084    on the toolkit thread. This method may pre-filter the messages. */
5085 BOOL AwtComponent::PostHandleEventMessage(MSG *msg, BOOL synthetic)
5086 {
5087     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5088     // We should cut off keyboard events to disabled components
5089     // to avoid the components responding visually to keystrokes when disabled.
5090     // we shouldn't cut off WM_SYS* messages as they aren't used for normal activity
5091     // but to activate menus, close windows, etc
5092     switch(msg->message) {
5093         case WM_KEYDOWN:
5094         case WM_KEYUP:
5095         case WM_CHAR:
5096         case WM_DEADCHAR:
5097             {
5098                 if (!isRecursivelyEnabled()) {
5099                     goto quit;
5100                 }
5101                 break;
5102             }
5103     }
5104     if (PostMessage(GetHWnd(), WM_AWT_HANDLE_EVENT,
5105         (WPARAM) synthetic, (LPARAM) msg)) {
5106             return TRUE;
5107     } else {
5108         JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5109     }
5110 quit:
5111     delete msg;
5112     return FALSE;
5113 }
5114 
5115 void AwtComponent::SynthesizeKeyMessage(JNIEnv *env, jobject keyEvent)
5116 {
5117     jint id = (env)->GetIntField(keyEvent, AwtAWTEvent::idID);
5118     UINT message;
5119     switch (id) {
5120       case java_awt_event_KeyEvent_KEY_PRESSED:
5121           message = WM_KEYDOWN;
5122           break;
5123       case java_awt_event_KeyEvent_KEY_RELEASED:
5124           message = WM_KEYUP;
5125           break;
5126       case java_awt_event_KeyEvent_KEY_TYPED:
5127           message = WM_CHAR;
5128           break;
5129       default:
5130           return;
5131     }
5132 
5133     /*
5134      * KeyEvent.modifiers aren't supported -- the Java apppwd must send separate
5135      * KEY_PRESSED and KEY_RELEASED events for the modifier virtual keys.
5136      */
5137     if (id == java_awt_event_KeyEvent_KEY_TYPED) {
5138         // WM_CHAR message must be posted using WM_AWT_FORWARD_CHAR
5139         // (for Edit control)
5140         jchar keyChar = (jchar)
5141           (env)->GetCharField(keyEvent, AwtKeyEvent::keyCharID);
5142 
5143         // Bugid 4724007.  If it is a Delete character, don't send the fake
5144         // KEY_TYPED we created back to the native window: Windows doesn't
5145         // expect a WM_CHAR for Delete in TextFields, so it tries to enter a
5146         // character after deleting.
5147         if (keyChar == '\177') { // the Delete character
5148             return;
5149         }
5150 
5151         // Disable forwarding WM_CHAR messages to disabled components
5152         if (isRecursivelyEnabled()) {
5153             if (!::PostMessage(GetHWnd(), WM_AWT_FORWARD_CHAR,
5154                 MAKEWPARAM(keyChar, TRUE), 0)) {
5155                 JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5156             }
5157         }
5158     } else {
5159         jint keyCode =
5160           (env)->GetIntField(keyEvent, AwtKeyEvent::keyCodeID);
5161         UINT key, modifiers;
5162         AwtComponent::JavaKeyToWindowsKey(keyCode, &key, &modifiers);
5163         MSG* msg = CreateMessage(message, key, 0);
5164         PostHandleEventMessage(msg, TRUE);
5165     }
5166 }
5167 
5168 void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent)
5169 {
5170     /*    DebugBreak(); */
5171     jint button = (env)->GetIntField(mouseEvent, AwtMouseEvent::buttonID);
5172     jint modifiers = (env)->GetIntField(mouseEvent, AwtInputEvent::modifiersID);
5173 
5174     WPARAM wParam = 0;
5175     WORD wLow = 0;
5176     jint wheelAmt = 0;
5177     jint id = (env)->GetIntField(mouseEvent, AwtAWTEvent::idID);
5178     UINT message;
5179     switch (id) {
5180       case java_awt_event_MouseEvent_MOUSE_PRESSED: {
5181           switch (button) {
5182             case java_awt_event_MouseEvent_BUTTON1:
5183                 message = WM_LBUTTONDOWN; break;
5184             case java_awt_event_MouseEvent_BUTTON3:
5185                 message = WM_MBUTTONDOWN; break;
5186             case java_awt_event_MouseEvent_BUTTON2:
5187                 message = WM_RBUTTONDOWN; break;
5188           }
5189           break;
5190       }
5191       case java_awt_event_MouseEvent_MOUSE_RELEASED: {
5192           switch (button) {
5193             case java_awt_event_MouseEvent_BUTTON1:
5194                 message = WM_LBUTTONUP; break;
5195             case java_awt_event_MouseEvent_BUTTON3:
5196                 message = WM_MBUTTONUP; break;
5197             case java_awt_event_MouseEvent_BUTTON2:
5198                 message = WM_RBUTTONUP; break;
5199           }
5200           break;
5201       }
5202       case java_awt_event_MouseEvent_MOUSE_MOVED:
5203           /* MOUSE_DRAGGED events must first have sent a MOUSE_PRESSED event. */
5204       case java_awt_event_MouseEvent_MOUSE_DRAGGED:
5205           message = WM_MOUSEMOVE;
5206           break;
5207       case java_awt_event_MouseEvent_MOUSE_WHEEL:
5208           if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
5209               wLow |= MK_CONTROL;
5210           }
5211           if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
5212               wLow |= MK_SHIFT;
5213           }
5214           if (modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
5215               wLow |= MK_LBUTTON;
5216           }
5217           if (modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) {
5218               wLow |= MK_RBUTTON;
5219           }
5220           if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) {
5221               wLow |= MK_MBUTTON;
5222           }
5223           if (modifiers & X1_BUTTON) {
5224               wLow |= GetButtonMK(X1_BUTTON);
5225           }
5226           if (modifiers & X2_BUTTON) {
5227               wLow |= GetButtonMK(X2_BUTTON);
5228           }
5229 
5230           wheelAmt = (jint)JNU_CallMethodByName(env,
5231                                                NULL,
5232                                                mouseEvent,
5233                                                "getWheelRotation",
5234                                                "()I").i;
5235           DASSERT(!safe_ExceptionOccurred(env));
5236           //DASSERT(wheelAmt);
5237           DTRACE_PRINTLN1("wheelAmt = %i\n", wheelAmt);
5238 
5239           // convert Java wheel amount value to Win32
5240           wheelAmt *= -1 * WHEEL_DELTA;
5241 
5242           message = WM_MOUSEWHEEL;
5243           wParam = MAKEWPARAM(wLow, wheelAmt);
5244 
5245           break;
5246       default:
5247           return;
5248     }
5249     jint x = (env)->GetIntField(mouseEvent, AwtMouseEvent::xID);
5250     jint y = (env)->GetIntField(mouseEvent, AwtMouseEvent::yID);
5251     MSG* msg = CreateMessage(message, wParam, MAKELPARAM(x, y), x, y);
5252     PostHandleEventMessage(msg, TRUE);
5253 }
5254 
5255 BOOL AwtComponent::InheritsNativeMouseWheelBehavior() {return false;}
5256 
5257 void AwtComponent::Invalidate(RECT* r)
5258 {
5259     ::InvalidateRect(GetHWnd(), r, FALSE);
5260 }
5261 
5262 void AwtComponent::BeginValidate()
5263 {
5264     DASSERT(m_validationNestCount >= 0 &&
5265            m_validationNestCount < 1000); // sanity check
5266 
5267     if (m_validationNestCount == 0) {
5268     // begin deferred window positioning if we're not inside
5269     // another Begin/EndValidate pair
5270         DASSERT(m_hdwp == NULL);
5271         m_hdwp = ::BeginDeferWindowPos(32);
5272     }
5273 
5274     m_validationNestCount++;
5275 }
5276 
5277 void AwtComponent::EndValidate()
5278 {
5279     DASSERT(m_validationNestCount > 0 &&
5280            m_validationNestCount < 1000); // sanity check
5281     DASSERT(m_hdwp != NULL);
5282 
5283     m_validationNestCount--;
5284     if (m_validationNestCount == 0) {
5285     // if this call to EndValidate is not nested inside another
5286     // Begin/EndValidate pair, end deferred window positioning
5287         ::EndDeferWindowPos(m_hdwp);
5288         m_hdwp = NULL;
5289     }
5290 }
5291 
5292 /**
5293  * HWND, AwtComponent and Java Peer interaction
5294  */
5295 
5296 /*
5297  *Link the C++, Java peer, and HWNDs together.
5298  */
5299 void AwtComponent::LinkObjects(JNIEnv *env, jobject peer)
5300 {
5301     /*
5302      * Bind all three objects together thru this C++ object, two-way to each:
5303      *     JavaPeer <-> C++ <-> HWND
5304      *
5305      * C++ -> JavaPeer
5306      */
5307     if (m_peerObject == NULL) {
5308         // This may have already been set up by CreateHWnd
5309         // And we don't want to create two references so we
5310         // will leave the prior one alone
5311         m_peerObject = env->NewGlobalRef(peer);
5312     }
5313     /* JavaPeer -> HWND */
5314     env->SetLongField(peer, AwtComponent::hwndID, reinterpret_cast<jlong>(m_hwnd));
5315 
5316     /* JavaPeer -> C++ */
5317     JNI_SET_PDATA(peer, this);
5318 
5319     /* HWND -> C++ */
5320     SetComponentInHWND();
5321 }
5322 
5323 /* Cleanup above linking */
5324 void AwtComponent::UnlinkObjects()
5325 {
5326     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5327     if (m_peerObject) {
5328         env->SetLongField(m_peerObject, AwtComponent::hwndID, 0);
5329         JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL));
5330         JNI_SET_DESTROYED(m_peerObject);
5331         env->DeleteGlobalRef(m_peerObject);
5332         m_peerObject = NULL;
5333     }
5334 }
5335 
5336 void AwtComponent::Enable(BOOL bEnable)
5337 {
5338     if (bEnable && IsTopLevel()) {
5339         // we should not enable blocked toplevels
5340         bEnable = !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()));
5341     }
5342     // Shouldn't trigger native focus change
5343     // (only the proxy may be the native focus owner).
5344     ::EnableWindow(GetHWnd(), bEnable);
5345 
5346     CriticalSection::Lock l(GetLock());
5347     VerifyState();
5348 }
5349 
5350 /*
5351  * associate an AwtDropTarget with this AwtComponent
5352  */
5353 
5354 AwtDropTarget* AwtComponent::CreateDropTarget(JNIEnv* env) {
5355     m_dropTarget = new AwtDropTarget(env, this);
5356     m_dropTarget->RegisterTarget(TRUE);
5357     return m_dropTarget;
5358 }
5359 
5360 /*
5361  * disassociate an AwtDropTarget with this AwtComponent
5362  */
5363 
5364 void AwtComponent::DestroyDropTarget() {
5365     if (m_dropTarget != NULL) {
5366         m_dropTarget->RegisterTarget(FALSE);
5367         m_dropTarget->Release();
5368         m_dropTarget = NULL;
5369     }
5370 }
5371 
5372 BOOL AwtComponent::IsFocusingMouseMessage(MSG *pMsg) {
5373     return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
5374 }
5375 
5376 BOOL AwtComponent::IsFocusingKeyMessage(MSG *pMsg) {
5377     return pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_SPACE;
5378 }
5379 
5380 void AwtComponent::_Show(void *param)
5381 {
5382     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5383 
5384     jobject self = (jobject)param;
5385 
5386     AwtComponent *p;
5387 
5388     PDATA pData;
5389     JNI_CHECK_PEER_GOTO(self, ret);
5390     p = (AwtComponent *)pData;
5391     if (::IsWindow(p->GetHWnd()))
5392     {
5393         p->SendMessage(WM_AWT_COMPONENT_SHOW);
5394     }
5395 ret:
5396     env->DeleteGlobalRef(self);
5397 }
5398 
5399 void AwtComponent::_Hide(void *param)
5400 {
5401     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5402 
5403     jobject self = (jobject)param;
5404 
5405     AwtComponent *p;
5406 
5407     PDATA pData;
5408     JNI_CHECK_PEER_GOTO(self, ret);
5409     p = (AwtComponent *)pData;
5410     if (::IsWindow(p->GetHWnd()))
5411     {
5412         p->SendMessage(WM_AWT_COMPONENT_HIDE);
5413     }
5414 ret:
5415     env->DeleteGlobalRef(self);
5416 }
5417 
5418 void AwtComponent::_Enable(void *param)
5419 {
5420     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5421 
5422     jobject self = (jobject)param;
5423 
5424     AwtComponent *p;
5425 
5426     PDATA pData;
5427     JNI_CHECK_PEER_GOTO(self, ret);
5428     p = (AwtComponent *)pData;
5429     if (::IsWindow(p->GetHWnd()))
5430     {
5431         p->Enable(TRUE);
5432     }
5433 ret:
5434     env->DeleteGlobalRef(self);
5435 }
5436 
5437 void AwtComponent::_Disable(void *param)
5438 {
5439     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5440 
5441     jobject self = (jobject)param;
5442 
5443     AwtComponent *p;
5444 
5445     PDATA pData;
5446     JNI_CHECK_PEER_GOTO(self, ret);
5447     p = (AwtComponent *)pData;
5448     if (::IsWindow(p->GetHWnd()))
5449     {
5450         p->Enable(FALSE);
5451     }
5452 ret:
5453     env->DeleteGlobalRef(self);
5454 }
5455 
5456 jobject AwtComponent::_GetLocationOnScreen(void *param)
5457 {
5458     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5459 
5460     jobject self = (jobject)param;
5461 
5462     jobject result = NULL;
5463     AwtComponent *p;
5464 
5465     PDATA pData;
5466     JNI_CHECK_PEER_GOTO(self, ret);
5467     p = (AwtComponent *)pData;
5468     if (::IsWindow(p->GetHWnd()))
5469     {
5470         RECT rect;
5471         VERIFY(::GetWindowRect(p->GetHWnd(),&rect));
5472         result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
5473             rect.left, rect.top);
5474     }
5475 ret:
5476     env->DeleteGlobalRef(self);
5477 
5478     if (result != NULL)
5479     {
5480         jobject resultGlobalRef = env->NewGlobalRef(result);
5481         env->DeleteLocalRef(result);
5482         return resultGlobalRef;
5483     }
5484     else
5485     {
5486         return NULL;
5487     }
5488 }
5489 
5490 void AwtComponent::_Reshape(void *param)
5491 {
5492     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5493 
5494     ReshapeStruct *rs = (ReshapeStruct*)param;
5495     jobject self = rs->component;
5496     jint x = rs->x;
5497     jint y = rs->y;
5498     jint w = rs->w;
5499     jint h = rs->h;
5500 
5501     AwtComponent *p;
5502 
5503     PDATA pData;
5504     JNI_CHECK_PEER_GOTO(self, ret);
5505     p = (AwtComponent *)pData;
5506     if (::IsWindow(p->GetHWnd()))
5507     {
5508         RECT* r = new RECT;
5509         ::SetRect(r, x, y, x + w, y + h);
5510         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, CHECK_EMBEDDED, (LPARAM)r);
5511     }
5512 ret:
5513     env->DeleteGlobalRef(self);
5514 
5515     delete rs;
5516 }
5517 
5518 void AwtComponent::_ReshapeNoCheck(void *param)
5519 {
5520     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5521 
5522     ReshapeStruct *rs = (ReshapeStruct*)param;
5523     jobject self = rs->component;
5524     jint x = rs->x;
5525     jint y = rs->y;
5526     jint w = rs->w;
5527     jint h = rs->h;
5528 
5529     AwtComponent *p;
5530 
5531     PDATA pData;
5532     JNI_CHECK_PEER_GOTO(self, ret);
5533     p = (AwtComponent *)pData;
5534     if (::IsWindow(p->GetHWnd()))
5535     {
5536         RECT* r = new RECT;
5537         ::SetRect(r, x, y, x + w, y + h);
5538         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, DONT_CHECK_EMBEDDED, (LPARAM)r);
5539     }
5540 ret:
5541     env->DeleteGlobalRef(self);
5542 
5543     delete rs;
5544 }
5545 
5546 void AwtComponent::_NativeHandleEvent(void *param)
5547 {
5548     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5549 
5550     NativeHandleEventStruct *nhes = (NativeHandleEventStruct *)param;
5551     jobject self = nhes->component;
5552     jobject event = nhes->event;
5553 
5554     AwtComponent *p;
5555 
5556     PDATA pData;
5557     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5558     pData = JNI_GET_PDATA(self);
5559     if (pData == NULL) {
5560         env->DeleteGlobalRef(self);
5561         if (event != NULL) {
5562             env->DeleteGlobalRef(event);
5563         }
5564         delete nhes;
5565         return;
5566     }
5567     JNI_CHECK_NULL_GOTO(event, "null AWTEvent", ret);
5568 
5569     p = (AwtComponent *)pData;
5570     if (::IsWindow(p->GetHWnd()))
5571     {
5572         if (env->EnsureLocalCapacity(1) < 0) {
5573             env->DeleteGlobalRef(self);
5574             env->DeleteGlobalRef(event);
5575             delete nhes;
5576             return;
5577         }
5578         jbyteArray bdata = (jbyteArray)(env)->GetObjectField(event, AwtAWTEvent::bdataID);
5579         int id = (env)->GetIntField(event, AwtAWTEvent::idID);
5580         DASSERT(!safe_ExceptionOccurred(env));
5581         if (bdata != 0) {
5582             MSG msg;
5583             (env)->GetByteArrayRegion(bdata, 0, sizeof(MSG), (jbyte *)&msg);
5584             (env)->DeleteLocalRef(bdata);
5585             static BOOL keyDownConsumed = FALSE;
5586             static BOOL bCharChanged = FALSE;
5587             static WCHAR modifiedChar;
5588             WCHAR unicodeChar;
5589 
5590             /* Remember if a KEY_PRESSED event is consumed, as an old model
5591              * program won't consume a subsequent KEY_TYPED event.
5592              */
5593             jboolean consumed =
5594                 (env)->GetBooleanField(event, AwtAWTEvent::consumedID);
5595             DASSERT(!safe_ExceptionOccurred(env));
5596 
5597             if (consumed) {
5598                 keyDownConsumed = (id == java_awt_event_KeyEvent_KEY_PRESSED);
5599                 env->DeleteGlobalRef(self);
5600                 env->DeleteGlobalRef(event);
5601                 delete nhes;
5602                 return;
5603 
5604             } else if (id == java_awt_event_KeyEvent_KEY_PRESSED) {
5605                 // Fix for 6637607: reset consuming
5606                 keyDownConsumed = FALSE;
5607             }
5608 
5609             /* Consume a KEY_TYPED event if a KEY_PRESSED had been, to support
5610              * the old model.
5611              */
5612             if ((id == java_awt_event_KeyEvent_KEY_TYPED) && keyDownConsumed) {
5613                 keyDownConsumed = FALSE;
5614                 env->DeleteGlobalRef(self);
5615                 env->DeleteGlobalRef(event);
5616                 delete nhes;
5617                 return;
5618             }
5619 
5620             /* Modify any event parameters, if necessary. */
5621             if (self && pData &&
5622                 id >= java_awt_event_KeyEvent_KEY_FIRST &&
5623                 id <= java_awt_event_KeyEvent_KEY_LAST) {
5624 
5625                     AwtComponent* p = (AwtComponent*)pData;
5626 
5627                     jint keyCode =
5628                       (env)->GetIntField(event, AwtKeyEvent::keyCodeID);
5629                     jchar keyChar =
5630                       (env)->GetCharField(event, AwtKeyEvent::keyCharID);
5631                     jint modifiers =
5632                       (env)->GetIntField(event, AwtInputEvent::modifiersID);
5633 
5634                     DASSERT(!safe_ExceptionOccurred(env));
5635 
5636                 /* Check to see whether the keyCode or modifiers were changed
5637                    on the keyPressed event, and tweak the following keyTyped
5638                    event (if any) accodingly.  */
5639                 switch (id) {
5640                 case java_awt_event_KeyEvent_KEY_PRESSED:
5641                 {
5642                     UINT winKey = (UINT)msg.wParam;
5643                     bCharChanged = FALSE;
5644 
5645                     if (winKey == VK_PROCESSKEY) {
5646                         // Leave it up to IME
5647                         break;
5648                     }
5649 
5650                     if (keyCode != java_awt_event_KeyEvent_VK_UNDEFINED) {
5651                         UINT newWinKey, ignored;
5652                         p->JavaKeyToWindowsKey(keyCode, &newWinKey, &ignored, winKey);
5653                         if (newWinKey != 0) {
5654                             winKey = newWinKey;
5655                         }
5656                     }
5657 
5658                     BOOL isDeadKey = FALSE;
5659                     UINT character;
5660                     p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE, &character, &isDeadKey);
5661                     modifiedChar = character;
5662                     bCharChanged = (keyChar != modifiedChar);
5663                 }
5664                 break;
5665 
5666                 case java_awt_event_KeyEvent_KEY_RELEASED:
5667                 {
5668                     keyDownConsumed = FALSE;
5669                     bCharChanged = FALSE;
5670                 }
5671                 break;
5672 
5673                 case java_awt_event_KeyEvent_KEY_TYPED:
5674                 {
5675                     if (bCharChanged)
5676                     {
5677                         unicodeChar = modifiedChar;
5678                     }
5679                     else
5680                     {
5681                         unicodeChar = keyChar;
5682                     }
5683                     bCharChanged = FALSE;
5684 
5685                     // Disable forwarding KEY_TYPED messages to peers of
5686                     // disabled components
5687                     if (p->isRecursivelyEnabled()) {
5688                         // send the character back to the native window for
5689                         // processing. The WM_AWT_FORWARD_CHAR handler will send
5690                         // this character to DefWindowProc
5691                         if (!::PostMessage(p->GetHWnd(), WM_AWT_FORWARD_CHAR,
5692                             MAKEWPARAM(unicodeChar, FALSE), msg.lParam)) {
5693                             JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5694                         }
5695                     }
5696                     env->DeleteGlobalRef(self);
5697                     env->DeleteGlobalRef(event);
5698                     delete nhes;
5699                     return;
5700                 }
5701                 break;
5702 
5703                 default:
5704                     break;
5705                 }
5706             }
5707 
5708             // ignore all InputMethodEvents
5709             if (self && (pData = JNI_GET_PDATA(self)) &&
5710                 id >= java_awt_event_InputMethodEvent_INPUT_METHOD_FIRST &&
5711                 id <= java_awt_event_InputMethodEvent_INPUT_METHOD_LAST) {
5712                 env->DeleteGlobalRef(self);
5713                 env->DeleteGlobalRef(event);
5714                 delete nhes;
5715                 return;
5716             }
5717 
5718             // Create copy for local msg
5719             MSG* pCopiedMsg = new MSG;
5720             memmove(pCopiedMsg, &msg, sizeof(MSG));
5721             // Event handler deletes msg
5722             p->PostHandleEventMessage(pCopiedMsg, FALSE);
5723 
5724             env->DeleteGlobalRef(self);
5725             env->DeleteGlobalRef(event);
5726             delete nhes;
5727             return;
5728         }
5729 
5730         /* Forward any valid synthesized events.  Currently only mouse and
5731          * key events are supported.
5732          */
5733         if (self == NULL || (pData = JNI_GET_PDATA(self)) == NULL) {
5734             env->DeleteGlobalRef(self);
5735             env->DeleteGlobalRef(event);
5736             delete nhes;
5737             return;
5738         }
5739 
5740         AwtComponent* p = (AwtComponent*)pData;
5741         if (id >= java_awt_event_KeyEvent_KEY_FIRST &&
5742             id <= java_awt_event_KeyEvent_KEY_LAST) {
5743             p->SynthesizeKeyMessage(env, event);
5744         } else if (id >= java_awt_event_MouseEvent_MOUSE_FIRST &&
5745                    id <= java_awt_event_MouseEvent_MOUSE_LAST) {
5746             p->SynthesizeMouseMessage(env, event);
5747         }
5748     }
5749 
5750 ret:
5751     if (self != NULL) {
5752         env->DeleteGlobalRef(self);
5753     }
5754     if (event != NULL) {
5755         env->DeleteGlobalRef(event);
5756     }
5757 
5758     delete nhes;
5759 }
5760 
5761 void AwtComponent::_SetForeground(void *param)
5762 {
5763     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5764 
5765     SetColorStruct *scs = (SetColorStruct *)param;
5766     jobject self = scs->component;
5767     jint rgb = scs->rgb;
5768 
5769     AwtComponent *c = NULL;
5770 
5771     PDATA pData;
5772     JNI_CHECK_PEER_GOTO(self, ret);
5773     c = (AwtComponent *)pData;
5774     if (::IsWindow(c->GetHWnd()))
5775     {
5776         c->SetColor(PALETTERGB((rgb>>16)&0xff,
5777                                (rgb>>8)&0xff,
5778                                (rgb)&0xff));
5779         c->VerifyState();
5780     }
5781 ret:
5782     env->DeleteGlobalRef(self);
5783 
5784     delete scs;
5785 }
5786 
5787 void AwtComponent::_SetBackground(void *param)
5788 {
5789     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5790 
5791     SetColorStruct *scs = (SetColorStruct *)param;
5792     jobject self = scs->component;
5793     jint rgb = scs->rgb;
5794 
5795     AwtComponent *c = NULL;
5796 
5797     PDATA pData;
5798     JNI_CHECK_PEER_GOTO(self, ret);
5799     c = (AwtComponent *)pData;
5800     if (::IsWindow(c->GetHWnd()))
5801     {
5802         c->SetBackgroundColor(PALETTERGB((rgb>>16)&0xff,
5803                                          (rgb>>8)&0xff,
5804                                          (rgb)&0xff));
5805         c->VerifyState();
5806     }
5807 ret:
5808     env->DeleteGlobalRef(self);
5809 
5810     delete scs;
5811 }
5812 
5813 void AwtComponent::_SetFont(void *param)
5814 {
5815     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5816 
5817     SetFontStruct *sfs = (SetFontStruct *)param;
5818     jobject self = sfs->component;
5819     jobject font = sfs->font;
5820 
5821     AwtComponent *c = NULL;
5822 
5823     PDATA pData;
5824     JNI_CHECK_PEER_GOTO(self, ret);
5825     JNI_CHECK_NULL_GOTO(font, "null font", ret);
5826     c = (AwtComponent *)pData;
5827     if (::IsWindow(c->GetHWnd()))
5828     {
5829         AwtFont *awtFont = (AwtFont *)env->GetLongField(font, AwtFont::pDataID);
5830         if (awtFont == NULL) {
5831             /*arguments of AwtFont::Create are changed for multifont component */
5832             awtFont = AwtFont::Create(env, font);
5833         }
5834         env->SetLongField(font, AwtFont::pDataID, (jlong)awtFont);
5835 
5836         c->SetFont(awtFont);
5837     }
5838 ret:
5839     env->DeleteGlobalRef(self);
5840     env->DeleteGlobalRef(font);
5841 
5842     delete sfs;
5843 }
5844 
5845 // Sets or kills focus for a component.
5846 void AwtComponent::_SetFocus(void *param)
5847 {
5848     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5849 
5850     SetFocusStruct *sfs = (SetFocusStruct *)param;
5851     jobject self = sfs->component;
5852     jboolean doSetFocus = sfs->doSetFocus;
5853 
5854     AwtComponent *c = NULL;
5855 
5856     PDATA pData;
5857     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5858     pData = JNI_GET_PDATA(self);
5859     if (pData == NULL) {
5860         // do nothing just return false
5861         goto ret;
5862     }
5863 
5864     c = (AwtComponent *)pData;
5865     if (::IsWindow(c->GetHWnd())) {
5866         c->SendMessage(WM_AWT_COMPONENT_SETFOCUS, (WPARAM)doSetFocus, 0);
5867     }
5868 ret:
5869     env->DeleteGlobalRef(self);
5870 
5871     delete sfs;
5872 }
5873 
5874 void AwtComponent::_Start(void *param)
5875 {
5876     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5877 
5878     jobject self = (jobject)param;
5879 
5880     AwtComponent *c = NULL;
5881 
5882     PDATA pData;
5883     JNI_CHECK_PEER_GOTO(self, ret);
5884     c = (AwtComponent *)pData;
5885     if (::IsWindow(c->GetHWnd()))
5886     {
5887         jobject target = c->GetTarget(env);
5888 
5889         /* Disable window if specified -- windows are enabled by default. */
5890         jboolean enabled = (jboolean)env->GetBooleanField(target,
5891                                                           AwtComponent::enabledID);
5892         if (!enabled) {
5893             ::EnableWindow(c->GetHWnd(), FALSE);
5894         }
5895 
5896         /* The peer is now ready for callbacks, since this is the last
5897          * initialization call
5898          */
5899         c->EnableCallbacks(TRUE);
5900 
5901         // Fix 4745222: we need to invalidate region since we validated it before initialization.
5902         ::InvalidateRgn(c->GetHWnd(), NULL, FALSE);
5903 
5904         // Fix 4530093: WM_PAINT after EnableCallbacks
5905         ::UpdateWindow(c->GetHWnd());
5906 
5907         env->DeleteLocalRef(target);
5908     }
5909 ret:
5910     env->DeleteGlobalRef(self);
5911 }
5912 
5913 void AwtComponent::_BeginValidate(void *param)
5914 {
5915     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5916     if (AwtToolkit::IsMainThread()) {
5917         jobject self = (jobject)param;
5918         if (self != NULL) {
5919             PDATA pData = JNI_GET_PDATA(self);
5920             if (pData) {
5921                 AwtComponent *c = (AwtComponent *)pData;
5922                 if (::IsWindow(c->GetHWnd())) {
5923                     c->SendMessage(WM_AWT_BEGIN_VALIDATE);
5924                 }
5925             }
5926             env->DeleteGlobalRef(self);
5927         }
5928     } else {
5929         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_BeginValidate, param);
5930     }
5931 }
5932 
5933 void AwtComponent::_EndValidate(void *param)
5934 {
5935     if (AwtToolkit::IsMainThread()) {
5936         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5937         jobject self = (jobject)param;
5938         if (self != NULL) {
5939             PDATA pData = JNI_GET_PDATA(self);
5940             if (pData) {
5941                 AwtComponent *c = (AwtComponent *)pData;
5942                 if (::IsWindow(c->GetHWnd())) {
5943                     c->SendMessage(WM_AWT_END_VALIDATE);
5944                 }
5945             }
5946             env->DeleteGlobalRef(self);
5947         }
5948     } else {
5949         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_EndValidate, param);
5950     }
5951 }
5952 
5953 void AwtComponent::_UpdateWindow(void *param)
5954 {
5955     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5956     if (AwtToolkit::IsMainThread()) {
5957         jobject self = (jobject)param;
5958         AwtComponent *c = NULL;
5959         PDATA pData;
5960         JNI_CHECK_PEER_GOTO(self, ret);
5961         c = (AwtComponent *)pData;
5962         if (::IsWindow(c->GetHWnd())) {
5963             ::UpdateWindow(c->GetHWnd());
5964         }
5965 ret:
5966         env->DeleteGlobalRef(self);
5967     } else {
5968         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_UpdateWindow, param);
5969     }
5970 }
5971 
5972 jlong AwtComponent::_AddNativeDropTarget(void *param)
5973 {
5974     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5975 
5976     jobject self = (jobject)param;
5977 
5978     jlong result = 0;
5979     AwtComponent *c = NULL;
5980 
5981     PDATA pData;
5982     JNI_CHECK_PEER_GOTO(self, ret);
5983     c = (AwtComponent *)pData;
5984     if (::IsWindow(c->GetHWnd()))
5985     {
5986         result = (jlong)(c->CreateDropTarget(env));
5987     }
5988 ret:
5989     env->DeleteGlobalRef(self);
5990 
5991     return result;
5992 }
5993 
5994 void AwtComponent::_RemoveNativeDropTarget(void *param)
5995 {
5996     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5997 
5998     jobject self = (jobject)param;
5999 
6000     AwtComponent *c = NULL;
6001 
6002     PDATA pData;
6003     JNI_CHECK_PEER_GOTO(self, ret);
6004     c = (AwtComponent *)pData;
6005     if (::IsWindow(c->GetHWnd()))
6006     {
6007         c->DestroyDropTarget();
6008     }
6009 ret:
6010     env->DeleteGlobalRef(self);
6011 }
6012 
6013 jintArray AwtComponent::_CreatePrintedPixels(void *param)
6014 {
6015     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6016 
6017     CreatePrintedPixelsStruct *cpps = (CreatePrintedPixelsStruct *)param;
6018     jobject self = cpps->component;
6019 
6020     jintArray result = NULL;
6021     AwtComponent *c = NULL;
6022 
6023     PDATA pData;
6024     JNI_CHECK_PEER_GOTO(self, ret);
6025     c = (AwtComponent *)pData;
6026     if (::IsWindow(c->GetHWnd()))
6027     {
6028         result = (jintArray)c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)cpps, 0);
6029     }
6030 ret:
6031     env->DeleteGlobalRef(self);
6032 
6033     delete cpps;
6034     return result; // this reference is global
6035 }
6036 
6037 jboolean AwtComponent::_IsObscured(void *param)
6038 {
6039     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6040 
6041     jobject self = (jobject)param;
6042 
6043     jboolean result = JNI_FALSE;
6044     AwtComponent *c = NULL;
6045 
6046     PDATA pData;
6047     JNI_CHECK_PEER_GOTO(self, ret);
6048 
6049     c = (AwtComponent *)pData;
6050 
6051     if (::IsWindow(c->GetHWnd()))
6052     {
6053         HWND hWnd = c->GetHWnd();
6054         HDC hDC = ::GetDC(hWnd);
6055         RECT clipbox;
6056         int callresult = ::GetClipBox(hDC, &clipbox);
6057         switch(callresult) {
6058             case NULLREGION :
6059                 result = JNI_FALSE;
6060                 break;
6061             case SIMPLEREGION : {
6062                 RECT windowRect;
6063                 if (!::GetClientRect(hWnd, &windowRect)) {
6064                     result = JNI_TRUE;
6065                 } else {
6066                     result  = (jboolean)((clipbox.bottom != windowRect.bottom)
6067                         || (clipbox.left != windowRect.left)
6068                         || (clipbox.right != windowRect.right)
6069                         || (clipbox.top != windowRect.top));
6070                 }
6071                 break;
6072             }
6073             case COMPLEXREGION :
6074             default :
6075                 result = JNI_TRUE;
6076                 break;
6077         }
6078         ::ReleaseDC(hWnd, hDC);
6079     }
6080 ret:
6081     env->DeleteGlobalRef(self);
6082 
6083     return result;
6084 }
6085 
6086 jboolean AwtComponent::_NativeHandlesWheelScrolling(void *param)
6087 {
6088     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6089 
6090     jobject self = (jobject)param;
6091 
6092     jboolean result = JNI_FALSE;
6093     AwtComponent *c = NULL;
6094 
6095     PDATA pData;
6096     JNI_CHECK_PEER_GOTO(self, ret);
6097     c = (AwtComponent *)pData;
6098     if (::IsWindow(c->GetHWnd()))
6099     {
6100         result = (jboolean)c->InheritsNativeMouseWheelBehavior();
6101     }
6102 ret:
6103     env->DeleteGlobalRef(self);
6104 
6105     return result;
6106 }
6107 
6108 void AwtComponent::SetParent(void * param) {
6109     if (AwtToolkit::IsMainThread()) {
6110         AwtComponent** comps = (AwtComponent**)param;
6111         if ((comps[0] != NULL) && (comps[1] != NULL)) {
6112             HWND selfWnd = comps[0]->GetHWnd();
6113             HWND parentWnd = comps[1]->GetHWnd();
6114             if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) {
6115                 // Shouldn't trigger native focus change
6116                 // (only the proxy may be the native focus owner).
6117                 ::SetParent(selfWnd, parentWnd);
6118             }
6119         }
6120         delete[] comps;
6121     } else {
6122         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::SetParent, param);
6123     }
6124 }
6125 
6126 void AwtComponent::_SetRectangularShape(void *param)
6127 {
6128     if (!AwtToolkit::IsMainThread()) {
6129         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetRectangularShape, param);
6130     } else {
6131         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6132 
6133         SetRectangularShapeStruct *data = (SetRectangularShapeStruct *)param;
6134         jobject self = data->component;
6135         jint x1 = data->x1;
6136         jint x2 = data->x2;
6137         jint y1 = data->y1;
6138         jint y2 = data->y2;
6139         jobject region = data->region;
6140 
6141         AwtComponent *c = NULL;
6142 
6143         PDATA pData;
6144         JNI_CHECK_PEER_GOTO(self, ret);
6145 
6146         c = (AwtComponent *)pData;
6147         if (::IsWindow(c->GetHWnd())) {
6148             HRGN hRgn = NULL;
6149             if (region || x1 || x2 || y1 || y2) {
6150                 // If all the params are zeros, the shape must be simply reset.
6151                 // Otherwise, convert it into a region.
6152                 RGNDATA *pRgnData = NULL;
6153                 RGNDATAHEADER *pRgnHdr;
6154 
6155                 /* reserving memory for the worst case */
6156                 size_t worstBufferSize = size_t(((x2 - x1) / 2 + 1) * (y2 - y1));
6157                 pRgnData = (RGNDATA *) safe_Malloc(sizeof(RGNDATAHEADER) +
6158                         sizeof(RECT_T) * worstBufferSize);
6159                 pRgnHdr = (RGNDATAHEADER *) pRgnData;
6160 
6161                 pRgnHdr->dwSize = sizeof(RGNDATAHEADER);
6162                 pRgnHdr->iType = RDH_RECTANGLES;
6163                 pRgnHdr->nRgnSize = 0;
6164                 pRgnHdr->rcBound.top = 0;
6165                 pRgnHdr->rcBound.left = 0;
6166                 pRgnHdr->rcBound.bottom = LONG(y2 - y1);
6167                 pRgnHdr->rcBound.right = LONG(x2 - x1);
6168 
6169                 RECT_T * pRect = (RECT_T *) (((BYTE *) pRgnData) + sizeof(RGNDATAHEADER));
6170                 pRgnHdr->nCount = RegionToYXBandedRectangles(env, x1, y1, x2, y2, region, &pRect, worstBufferSize);
6171 
6172                 hRgn = ::ExtCreateRegion(NULL,
6173                         sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, pRgnData);
6174 
6175                 free(pRgnData);
6176             }
6177 
6178             ::SetWindowRgn(c->GetHWnd(), hRgn, TRUE);
6179         }
6180 
6181 ret:
6182         env->DeleteGlobalRef(self);
6183         if (region) {
6184             env->DeleteGlobalRef(region);
6185         }
6186 
6187         delete data;
6188     }
6189 }
6190 
6191 void AwtComponent::_SetZOrder(void *param) {
6192     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6193 
6194     SetZOrderStruct *data = (SetZOrderStruct *)param;
6195     jobject self = data->component;
6196     HWND above = HWND_TOP;
6197     if (data->above != 0) {
6198         above = reinterpret_cast<HWND>(data->above);
6199     }
6200 
6201     AwtComponent *c = NULL;
6202 
6203     PDATA pData;
6204     JNI_CHECK_PEER_GOTO(self, ret);
6205 
6206     c = (AwtComponent *)pData;
6207     if (::IsWindow(c->GetHWnd())) {
6208         ::SetWindowPos(c->GetHWnd(), above, 0, 0, 0, 0,
6209                        SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS);
6210     }
6211 
6212 ret:
6213     env->DeleteGlobalRef(self);
6214 
6215     delete data;
6216 }
6217 
6218 void AwtComponent::PostUngrabEvent() {
6219     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6220     jobject target = GetTarget(env);
6221     jobject event = JNU_NewObjectByName(env, "sun/awt/UngrabEvent", "(Ljava/awt/Component;)V",
6222                                         target);
6223     if (safe_ExceptionOccurred(env)) {
6224         env->ExceptionDescribe();
6225         env->ExceptionClear();
6226     }
6227     env->DeleteLocalRef(target);
6228     if (event != NULL) {
6229         SendEvent(event);
6230         env->DeleteLocalRef(event);
6231     }
6232 }
6233 
6234 void AwtComponent::SetFocusedWindow(HWND window)
6235 {
6236     HWND old = sm_focusedWindow;
6237     sm_focusedWindow = window;
6238 
6239     AwtWindow::FocusedWindowChanged(old, window);
6240 }
6241 
6242 /************************************************************************
6243  * Component native methods
6244  */
6245 
6246 extern "C" {
6247 
6248 /**
6249  * This method is called from the WGL pipeline when it needs to retrieve
6250  * the HWND associated with a ComponentPeer's C++ level object.
6251  */
6252 HWND
6253 AwtComponent_GetHWnd(JNIEnv *env, jlong pData)
6254 {
6255     AwtComponent *p = (AwtComponent *)jlong_to_ptr(pData);
6256     if (p == NULL) {
6257         return (HWND)0;
6258     }
6259     return p->GetHWnd();
6260 }
6261 
6262 static void _GetInsets(void* param)
6263 {
6264     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6265 
6266     GetInsetsStruct *gis = (GetInsetsStruct *)param;
6267     jobject self = gis->window;
6268 
6269     gis->insets->left = gis->insets->top =
6270         gis->insets->right = gis->insets->bottom = 0;
6271 
6272     PDATA pData;
6273     JNI_CHECK_PEER_GOTO(self, ret);
6274     AwtComponent *component = (AwtComponent *)pData;
6275 
6276     component->GetInsets(gis->insets);
6277 
6278   ret:
6279     env->DeleteGlobalRef(self);
6280     delete gis;
6281 }
6282 
6283 /**
6284  * This method is called from the WGL pipeline when it needs to retrieve
6285  * the insets associated with a ComponentPeer's C++ level object.
6286  */
6287 void AwtComponent_GetInsets(JNIEnv *env, jobject peer, RECT *insets)
6288 {
6289     TRY;
6290 
6291     GetInsetsStruct *gis = new GetInsetsStruct;
6292     gis->window = env->NewGlobalRef(peer);
6293     gis->insets = insets;
6294 
6295     AwtToolkit::GetInstance().InvokeFunction(_GetInsets, gis);
6296     // global refs and mds are deleted in _UpdateWindow
6297 
6298     CATCH_BAD_ALLOC;
6299 
6300 }
6301 
6302 JNIEXPORT void JNICALL
6303 Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls)
6304 {
6305     TRY;
6306     jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent");
6307     jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I");
6308     jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID);
6309     jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE);
6310 
6311     jsize len = env->GetArrayLength(obj);
6312     AwtComponent::masks = new jint[len];
6313     for (int i = 0; i < len; i++) {
6314         AwtComponent::masks[i] = tmp[i];
6315     }
6316     env->ReleaseIntArrayElements(obj, tmp, 0);
6317     env->DeleteLocalRef(obj);
6318 
6319     /* class ids */
6320     jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer");
6321 
6322     DASSERT(peerCls);
6323 
6324     /* field ids */
6325     AwtComponent::peerID =
6326       env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;");
6327     AwtComponent::xID = env->GetFieldID(cls, "x", "I");
6328     AwtComponent::yID = env->GetFieldID(cls, "y", "I");
6329     AwtComponent::heightID = env->GetFieldID(cls, "height", "I");
6330     AwtComponent::widthID = env->GetFieldID(cls, "width", "I");
6331     AwtComponent::visibleID = env->GetFieldID(cls, "visible", "Z");
6332     AwtComponent::backgroundID =
6333         env->GetFieldID(cls, "background", "Ljava/awt/Color;");
6334     AwtComponent::foregroundID =
6335         env->GetFieldID(cls, "foreground", "Ljava/awt/Color;");
6336     AwtComponent::enabledID = env->GetFieldID(cls, "enabled", "Z");
6337     AwtComponent::parentID = env->GetFieldID(cls, "parent", "Ljava/awt/Container;");
6338     AwtComponent::graphicsConfigID =
6339      env->GetFieldID(cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;");
6340     AwtComponent::focusableID = env->GetFieldID(cls, "focusable", "Z");
6341 
6342     AwtComponent::appContextID = env->GetFieldID(cls, "appContext",
6343                                                  "Lsun/awt/AppContext;");
6344 
6345     AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig",
6346                                         "Lsun/awt/Win32GraphicsConfig;");
6347 
6348     AwtComponent::hwndID = env->GetFieldID(peerCls, "hwnd", "J");
6349 
6350     AwtComponent::cursorID = env->GetFieldID(cls, "cursor", "Ljava/awt/Cursor;");
6351 
6352     /* method ids */
6353     AwtComponent::getFontMID =
6354         env->GetMethodID(cls, "getFont_NoClientCode", "()Ljava/awt/Font;");
6355     AwtComponent::getToolkitMID =
6356         env->GetMethodID(cls, "getToolkitImpl", "()Ljava/awt/Toolkit;");
6357     AwtComponent::isEnabledMID = env->GetMethodID(cls, "isEnabledImpl", "()Z");
6358     AwtComponent::getLocationOnScreenMID =
6359         env->GetMethodID(cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;");
6360     AwtComponent::replaceSurfaceDataMID =
6361         env->GetMethodID(peerCls, "replaceSurfaceData", "()V");
6362     AwtComponent::replaceSurfaceDataLaterMID =
6363         env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V");
6364     AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
6365 
6366     DASSERT(AwtComponent::xID);
6367     DASSERT(AwtComponent::yID);
6368     DASSERT(AwtComponent::heightID);
6369     DASSERT(AwtComponent::widthID);
6370     DASSERT(AwtComponent::visibleID);
6371     DASSERT(AwtComponent::backgroundID);
6372     DASSERT(AwtComponent::foregroundID);
6373     DASSERT(AwtComponent::enabledID);
6374     DASSERT(AwtComponent::parentID);
6375     DASSERT(AwtComponent::hwndID);
6376 
6377     DASSERT(AwtComponent::getFontMID);
6378     DASSERT(AwtComponent::getToolkitMID);
6379     DASSERT(AwtComponent::isEnabledMID);
6380     DASSERT(AwtComponent::getLocationOnScreenMID);
6381     DASSERT(AwtComponent::replaceSurfaceDataMID);
6382     DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
6383     DASSERT(AwtComponent::disposeLaterMID);
6384 
6385 
6386     CATCH_BAD_ALLOC;
6387 }
6388 
6389 } /* extern "C" */
6390 
6391 
6392 /************************************************************************
6393  * ComponentPeer native methods
6394  */
6395 
6396 extern "C" {
6397 
6398 /*
6399  * Class:     sun_awt_windows_WComponentPeer
6400  * Method:    pShow
6401  * Signature: ()V
6402  */
6403 JNIEXPORT void JNICALL
6404 Java_sun_awt_windows_WComponentPeer_pShow(JNIEnv *env, jobject self)
6405 {
6406     TRY;
6407 
6408     jobject selfGlobalRef = env->NewGlobalRef(self);
6409 
6410     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Show, (void *)selfGlobalRef);
6411     // selfGlobalRef is deleted in _Show
6412 
6413     CATCH_BAD_ALLOC;
6414 }
6415 
6416 /*
6417  * Class:     sun_awt_windows_WComponentPeer
6418  * Method:    hide
6419  * Signature: ()V
6420  */
6421 JNIEXPORT void JNICALL
6422 Java_sun_awt_windows_WComponentPeer_hide(JNIEnv *env, jobject self)
6423 {
6424     TRY;
6425 
6426     jobject selfGlobalRef = env->NewGlobalRef(self);
6427 
6428     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Hide, (void *)selfGlobalRef);
6429     // selfGlobalRef is deleted in _Hide
6430 
6431     CATCH_BAD_ALLOC;
6432 }
6433 
6434 /*
6435  * Class:     sun_awt_windows_WComponentPeer
6436  * Method:    enable
6437  * Signature: ()V
6438  */
6439 JNIEXPORT void JNICALL
6440 Java_sun_awt_windows_WComponentPeer_enable(JNIEnv *env, jobject self)
6441 {
6442     TRY;
6443 
6444     jobject selfGlobalRef = env->NewGlobalRef(self);
6445 
6446     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Enable, (void *)selfGlobalRef);
6447     // selfGlobalRef is deleted in _Enable
6448 
6449     CATCH_BAD_ALLOC;
6450 }
6451 
6452 /*
6453  * Class:     sun_awt_windows_WComponentPeer
6454  * Method:    disable
6455  * Signature: ()V
6456  */
6457 JNIEXPORT void JNICALL
6458 Java_sun_awt_windows_WComponentPeer_disable(JNIEnv *env, jobject self)
6459 {
6460     TRY;
6461 
6462     jobject selfGlobalRef = env->NewGlobalRef(self);
6463 
6464     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Disable, (void *)selfGlobalRef);
6465     // selfGlobalRef is deleted in _Disable
6466 
6467     CATCH_BAD_ALLOC;
6468 }
6469 
6470 /*
6471  * Class:     sun_awt_windows_WComponentPeer
6472  * Method:    getLocationOnScreen
6473  * Signature: ()Ljava/awt/Point;
6474  */
6475 JNIEXPORT jobject JNICALL
6476 Java_sun_awt_windows_WComponentPeer_getLocationOnScreen(JNIEnv *env, jobject self)
6477 {
6478     TRY;
6479 
6480     jobject selfGlobalRef = env->NewGlobalRef(self);
6481 
6482     jobject resultGlobalRef = (jobject)AwtToolkit::GetInstance().SyncCall(
6483         (void*(*)(void*))AwtComponent::_GetLocationOnScreen, (void *)selfGlobalRef);
6484     // selfGlobalRef is deleted in _GetLocationOnScreen
6485     if (resultGlobalRef != NULL)
6486     {
6487         jobject resultLocalRef = env->NewLocalRef(resultGlobalRef);
6488         env->DeleteGlobalRef(resultGlobalRef);
6489         return resultLocalRef;
6490     }
6491 
6492     return NULL;
6493 
6494     CATCH_BAD_ALLOC_RET(NULL);
6495 }
6496 
6497 /*
6498  * Class:     sun_awt_windows_WComponentPeer
6499  * Method:    reshape
6500  * Signature: (IIII)V
6501  */
6502 JNIEXPORT void JNICALL
6503 Java_sun_awt_windows_WComponentPeer_reshape(JNIEnv *env, jobject self,
6504                                             jint x, jint y, jint w, jint h)
6505 {
6506     TRY;
6507 
6508     ReshapeStruct *rs = new ReshapeStruct;
6509     rs->component = env->NewGlobalRef(self);
6510     rs->x = x;
6511     rs->y = y;
6512     rs->w = w;
6513     rs->h = h;
6514 
6515     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Reshape, rs);
6516     // global ref and rs are deleted in _Reshape
6517 
6518     CATCH_BAD_ALLOC;
6519 }
6520 
6521 /*
6522  * Class:     sun_awt_windows_WComponentPeer
6523  * Method:    reshape
6524  * Signature: (IIII)V
6525  */
6526 JNIEXPORT void JNICALL
6527 Java_sun_awt_windows_WComponentPeer_reshapeNoCheck(JNIEnv *env, jobject self,
6528                                             jint x, jint y, jint w, jint h)
6529 {
6530     TRY;
6531 
6532     ReshapeStruct *rs = new ReshapeStruct;
6533     rs->component = env->NewGlobalRef(self);
6534     rs->x = x;
6535     rs->y = y;
6536     rs->w = w;
6537     rs->h = h;
6538 
6539     AwtToolkit::GetInstance().SyncCall(AwtComponent::_ReshapeNoCheck, rs);
6540     // global ref and rs are deleted in _ReshapeNoCheck
6541 
6542     CATCH_BAD_ALLOC;
6543 }
6544 
6545 
6546 /*
6547  * Class:     sun_awt_windows_WComponentPeer
6548  * Method:    nativeHandleEvent
6549  * Signature: (Ljava/awt/AWTEvent;)V
6550  */
6551 JNIEXPORT void JNICALL
6552 Java_sun_awt_windows_WComponentPeer_nativeHandleEvent(JNIEnv *env,
6553                                                       jobject self,
6554                                                       jobject event)
6555 {
6556     TRY;
6557 
6558     jobject selfGlobalRef = env->NewGlobalRef(self);
6559     jobject eventGlobalRef = env->NewGlobalRef(event);
6560 
6561     NativeHandleEventStruct *nhes = new NativeHandleEventStruct;
6562     nhes->component = selfGlobalRef;
6563     nhes->event = eventGlobalRef;
6564 
6565     AwtToolkit::GetInstance().SyncCall(AwtComponent::_NativeHandleEvent, nhes);
6566     // global refs and nhes are deleted in _NativeHandleEvent
6567 
6568     CATCH_BAD_ALLOC;
6569 }
6570 
6571 /*
6572  * Class:     sun_awt_windows_WComponentPeer
6573  * Method:    _dispose
6574  * Signature: ()V
6575  */
6576 JNIEXPORT void JNICALL
6577 Java_sun_awt_windows_WComponentPeer__1dispose(JNIEnv *env, jobject self)
6578 {
6579     TRY_NO_HANG;
6580 
6581     AwtObject::_Dispose(self);
6582 
6583     CATCH_BAD_ALLOC;
6584 }
6585 
6586 /*
6587  * Class:     sun_awt_windows_WComponentPeer
6588  * Method:    _setForeground
6589  * Signature: (I)V
6590  */
6591 JNIEXPORT void JNICALL
6592 Java_sun_awt_windows_WComponentPeer__1setForeground(JNIEnv *env, jobject self,
6593                                                     jint rgb)
6594 {
6595     TRY;
6596 
6597     jobject selfGlobalRef = env->NewGlobalRef(self);
6598 
6599     SetColorStruct *scs = new SetColorStruct;
6600     scs->component = selfGlobalRef;
6601     scs->rgb = rgb;
6602 
6603     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetForeground, scs);
6604     // selfGlobalRef and scs are deleted in _SetForeground()
6605 
6606     CATCH_BAD_ALLOC;
6607 }
6608 
6609 /*
6610  * Class:     sun_awt_windows_WComponentPeer
6611  * Method:    _setBackground
6612  * Signature: (I)V
6613  */
6614 JNIEXPORT void JNICALL
6615 Java_sun_awt_windows_WComponentPeer__1setBackground(JNIEnv *env, jobject self,
6616                                                     jint rgb)
6617 {
6618     TRY;
6619 
6620     jobject selfGlobalRef = env->NewGlobalRef(self);
6621 
6622     SetColorStruct *scs = new SetColorStruct;
6623     scs->component = selfGlobalRef;
6624     scs->rgb = rgb;
6625 
6626     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetBackground, scs);
6627     // selfGlobalRef and scs are deleted in _SetBackground()
6628 
6629     CATCH_BAD_ALLOC;
6630 }
6631 
6632 /*
6633  * Class:     sun_awt_windows_WComponentPeer
6634  * Method:    _setFont
6635  * Signature: (Ljava/awt/Font;)V
6636  */
6637 JNIEXPORT void JNICALL
6638 Java_sun_awt_windows_WComponentPeer__1setFont(JNIEnv *env, jobject self,
6639                         jobject font)
6640 {
6641     TRY;
6642 
6643     jobject selfGlobalRef = env->NewGlobalRef(self);
6644     jobject fontGlobalRef = env->NewGlobalRef(font);
6645 
6646     SetFontStruct *sfs = new SetFontStruct;
6647     sfs->component = selfGlobalRef;
6648     sfs->font = fontGlobalRef;
6649 
6650     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetFont, sfs);
6651     // global refs and sfs are deleted in _SetFont()
6652 
6653     CATCH_BAD_ALLOC;
6654 }
6655 
6656 /*
6657  * Class:     sun_awt_windows_WComponentPeer
6658  * Method:    focusGained
6659  * Signature: (Z)
6660  */
6661 JNIEXPORT void JNICALL Java_sun_awt_windows_WComponentPeer_setFocus
6662     (JNIEnv *env, jobject self, jboolean doSetFocus)
6663 {
6664     TRY;
6665 
6666     jobject selfGlobalRef = env->NewGlobalRef(self);
6667 
6668     SetFocusStruct *sfs = new SetFocusStruct;
6669     sfs->component = selfGlobalRef;
6670     sfs->doSetFocus = doSetFocus;
6671 
6672     AwtToolkit::GetInstance().SyncCall(
6673         (void*(*)(void*))AwtComponent::_SetFocus, sfs);
6674     // global refs and self are deleted in _SetFocus
6675 
6676     CATCH_BAD_ALLOC;
6677 }
6678 
6679 /*
6680  * Class:     sun_awt_windows_WComponentPeer
6681  * Method:    start
6682  * Signature: ()V
6683  */
6684 JNIEXPORT void JNICALL
6685 Java_sun_awt_windows_WComponentPeer_start(JNIEnv *env, jobject self)
6686 {
6687     TRY;
6688 
6689     jobject selfGlobalRef = env->NewGlobalRef(self);
6690 
6691     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Start, (void *)selfGlobalRef);
6692     // selfGlobalRef is deleted in _Start
6693 
6694     CATCH_BAD_ALLOC;
6695 }
6696 
6697 /*
6698  * Class:     sun_awt_windows_WComponentPeer
6699  * Method:    beginValidate
6700  * Signature: ()V
6701  */
6702 JNIEXPORT void JNICALL
6703 Java_sun_awt_windows_WComponentPeer_beginValidate(JNIEnv *env, jobject self)
6704 {
6705     TRY;
6706 
6707     jobject selfGlobalRef = env->NewGlobalRef(self);
6708 
6709     AwtToolkit::GetInstance().SyncCall(AwtComponent::_BeginValidate, (void *)selfGlobalRef);
6710     // selfGlobalRef is deleted in _BeginValidate
6711 
6712     CATCH_BAD_ALLOC;
6713 }
6714 
6715 /*
6716  * Class:     sun_awt_windows_WComponentPeer
6717  * Method:    endValidate
6718  * Signature: ()V
6719  */
6720 JNIEXPORT void JNICALL
6721 Java_sun_awt_windows_WComponentPeer_endValidate(JNIEnv *env, jobject self)
6722 {
6723     TRY;
6724 
6725     jobject selfGlobalRef = env->NewGlobalRef(self);
6726 
6727     AwtToolkit::GetInstance().SyncCall(AwtComponent::_EndValidate, (void *)selfGlobalRef);
6728     // selfGlobalRef is deleted in _EndValidate
6729 
6730     CATCH_BAD_ALLOC;
6731 }
6732 
6733 JNIEXPORT void JNICALL
6734 Java_sun_awt_windows_WComponentPeer_updateWindow(JNIEnv *env, jobject self)
6735 {
6736     TRY;
6737 
6738     jobject selfGlobalRef = env->NewGlobalRef(self);
6739 
6740     AwtToolkit::GetInstance().SyncCall(AwtComponent::_UpdateWindow, (void *)selfGlobalRef);
6741     // selfGlobalRef is deleted in _UpdateWindow
6742 
6743     CATCH_BAD_ALLOC;
6744 }
6745 
6746 /*
6747  * Class:     sun_awt_windows_WComponentPeer
6748  * Method:    addNativeDropTarget
6749  * Signature: ()L
6750  */
6751 
6752 JNIEXPORT jlong JNICALL
6753 Java_sun_awt_windows_WComponentPeer_addNativeDropTarget(JNIEnv *env,
6754                                                         jobject self)
6755 {
6756     TRY;
6757 
6758     jobject selfGlobalRef = env->NewGlobalRef(self);
6759 
6760     return ptr_to_jlong(AwtToolkit::GetInstance().SyncCall(
6761         (void*(*)(void*))AwtComponent::_AddNativeDropTarget,
6762         (void *)selfGlobalRef));
6763     // selfGlobalRef is deleted in _AddNativeDropTarget
6764 
6765     CATCH_BAD_ALLOC_RET(0);
6766 }
6767 
6768 /*
6769  * Class:     sun_awt_windows_WComponentPeer
6770  * Method:    removeNativeDropTarget
6771  * Signature: ()V
6772  */
6773 
6774 JNIEXPORT void JNICALL
6775 Java_sun_awt_windows_WComponentPeer_removeNativeDropTarget(JNIEnv *env,
6776                                                            jobject self)
6777 {
6778     TRY;
6779 
6780     jobject selfGlobalRef = env->NewGlobalRef(self);
6781 
6782     AwtToolkit::GetInstance().SyncCall(
6783         AwtComponent::_RemoveNativeDropTarget, (void *)selfGlobalRef);
6784     // selfGlobalRef is deleted in _RemoveNativeDropTarget
6785 
6786     CATCH_BAD_ALLOC;
6787 }
6788 
6789 /*
6790  * Class:     sun_awt_windows_WComponentPeer
6791  * Method:    getTargetGC
6792  * Signature: ()Ljava/awt/GraphicsConfiguration;
6793  */
6794 JNIEXPORT jobject JNICALL
6795 Java_sun_awt_windows_WComponentPeer_getTargetGC(JNIEnv* env, jobject theThis)
6796 {
6797     TRY;
6798 
6799     jobject targetObj;
6800     jobject gc = 0;
6801 
6802     targetObj = env->GetObjectField(theThis, AwtObject::targetID);
6803     DASSERT(targetObj);
6804 
6805     gc = env->GetObjectField(targetObj, AwtComponent::graphicsConfigID);
6806     return gc;
6807 
6808     CATCH_BAD_ALLOC_RET(NULL);
6809 }
6810 
6811 /*
6812  * Class:     sun_awt_windows_WComponentPeer
6813  * Method:    createPrintedPixels
6814  * Signature: (IIIIII)I[
6815  */
6816 JNIEXPORT jintArray JNICALL
6817 Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env,
6818     jobject self, jint srcX, jint srcY, jint srcW, jint srcH, jint alpha)
6819 {
6820     TRY;
6821 
6822     jobject selfGlobalRef = env->NewGlobalRef(self);
6823 
6824     CreatePrintedPixelsStruct *cpps = new CreatePrintedPixelsStruct;
6825     cpps->component = selfGlobalRef;
6826     cpps->srcx = srcX;
6827     cpps->srcy = srcY;
6828     cpps->srcw = srcW;
6829     cpps->srch = srcH;
6830     cpps->alpha = alpha;
6831 
6832     jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall(
6833         (void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps);
6834     // selfGlobalRef and cpps are deleted in _CreatePrintedPixels
6835     if (globalRef != NULL)
6836     {
6837         jintArray localRef = (jintArray)env->NewLocalRef(globalRef);
6838         env->DeleteGlobalRef(globalRef);
6839         return localRef;
6840     }
6841     else
6842     {
6843         return NULL;
6844     }
6845 
6846     CATCH_BAD_ALLOC_RET(NULL);
6847 }
6848 
6849 /*
6850  * Class:     sun_awt_windows_WComponentPeer
6851  * Method:    nativeHandlesWheelScrolling
6852  * Signature: ()Z
6853  */
6854 JNIEXPORT jboolean JNICALL
6855 Java_sun_awt_windows_WComponentPeer_nativeHandlesWheelScrolling (JNIEnv* env,
6856     jobject self)
6857 {
6858     TRY;
6859 
6860     return (jboolean)AwtToolkit::GetInstance().SyncCall(
6861         (void *(*)(void *))AwtComponent::_NativeHandlesWheelScrolling,
6862         env->NewGlobalRef(self));
6863     // global ref is deleted in _NativeHandlesWheelScrolling
6864 
6865     CATCH_BAD_ALLOC_RET(NULL);
6866 }
6867 
6868 /*
6869  * Class:     sun_awt_windows_WComponentPeer
6870  * Method:    isObscured
6871  * Signature: ()Z
6872  */
6873 JNIEXPORT jboolean JNICALL
6874 Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv* env,
6875     jobject self)
6876 {
6877     TRY;
6878 
6879     jobject selfGlobalRef = env->NewGlobalRef(self);
6880 
6881     return (jboolean)AwtToolkit::GetInstance().SyncCall(
6882         (void*(*)(void*))AwtComponent::_IsObscured,
6883         (void *)selfGlobalRef);
6884     // selfGlobalRef is deleted in _IsObscured
6885 
6886     CATCH_BAD_ALLOC_RET(NULL);
6887 }
6888 
6889 JNIEXPORT void JNICALL
6890 Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv* env, jobject self, jobject parent) {
6891     TRY;
6892 
6893     typedef AwtComponent* PComponent;
6894     AwtComponent** comps = new PComponent[2];
6895     AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(self);
6896     AwtComponent* parentComp = (AwtComponent*)JNI_GET_PDATA(parent);
6897     comps[0] = comp;
6898     comps[1] = parentComp;
6899 
6900     AwtToolkit::GetInstance().SyncCall(AwtComponent::SetParent, comps);
6901     // comps is deleted in SetParent
6902 
6903     CATCH_BAD_ALLOC;
6904 }
6905 
6906 JNIEXPORT void JNICALL
6907 Java_sun_awt_windows_WComponentPeer_setRectangularShape(JNIEnv* env, jobject self,
6908         jint x1, jint y1, jint x2, jint y2, jobject region)
6909 {
6910     TRY;
6911 
6912     SetRectangularShapeStruct * data = new SetRectangularShapeStruct;
6913     data->component = env->NewGlobalRef(self);
6914     data->x1 = x1;
6915     data->x2 = x2;
6916     data->y1 = y1;
6917     data->y2 = y2;
6918     if (region) {
6919         data->region = env->NewGlobalRef(region);
6920     } else {
6921         data->region = NULL;
6922     }
6923 
6924     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetRectangularShape, data);
6925     // global refs and data are deleted in _SetRectangularShape
6926 
6927     CATCH_BAD_ALLOC;
6928 }
6929 
6930 JNIEXPORT void JNICALL
6931 Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv* env, jobject self, jlong above)
6932 {
6933     TRY;
6934 
6935     SetZOrderStruct * data = new SetZOrderStruct;
6936     data->component = env->NewGlobalRef(self);
6937     data->above = above;
6938 
6939     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetZOrder, data);
6940     // global refs and data are deleted in _SetLower
6941 
6942     CATCH_BAD_ALLOC;
6943 }
6944 
6945 } /* extern "C" */
6946 
6947 
6948 /************************************************************************
6949  * Diagnostic routines
6950  */
6951 
6952 #ifdef DEBUG
6953 
6954 void AwtComponent::VerifyState()
6955 {
6956     if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) {
6957         return;
6958     }
6959 
6960     if (m_callbacksEnabled == FALSE) {
6961         /* Component is not fully setup yet. */
6962         return;
6963     }
6964 
6965     /* Get target bounds. */
6966     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6967     if (env->PushLocalFrame(10) < 0)
6968         return;
6969 
6970     jobject target = GetTarget(env);
6971 
6972     jint x = env->GetIntField(target, AwtComponent::xID);
6973     jint y = env->GetIntField(target, AwtComponent::yID);
6974     jint width = env->GetIntField(target, AwtComponent::widthID);
6975     jint height = env->GetIntField(target, AwtComponent::heightID);
6976 
6977     /* Convert target origin to absolute coordinates */
6978     while (TRUE) {
6979 
6980         jobject parent = env->GetObjectField(target, AwtComponent::parentID);
6981         if (parent == NULL) {
6982             break;
6983         }
6984         x += env->GetIntField(parent, AwtComponent::xID);
6985         y += env->GetIntField(parent, AwtComponent::yID);
6986 
6987         /* If this component has insets, factor them in, but ignore
6988          * top-level windows.
6989          */
6990         jobject parent2 = env->GetObjectField(parent, AwtComponent::parentID);
6991         if (parent2 != NULL) {
6992             jobject peer = GetPeerForTarget(env, parent);
6993             if (peer != NULL &&
6994                 JNU_IsInstanceOfByName(env, peer,
6995                                        "sun/awt/windows/WPanelPeer") > 0) {
6996                 jobject insets =
6997                     JNU_CallMethodByName(env, NULL, peer,"insets",
6998                                          "()Ljava/awt/Insets;").l;
6999                 x += (env)->GetIntField(insets, AwtInsets::leftID);
7000                 y += (env)->GetIntField(insets, AwtInsets::topID);
7001             }
7002         }
7003         env->DeleteLocalRef(target);
7004         target = parent;
7005     }
7006 
7007     // Test whether component's bounds match the native window's
7008     RECT rect;
7009     VERIFY(::GetWindowRect(GetHWnd(), &rect));
7010 #if 0
7011     DASSERT( (x == rect.left) &&
7012             (y == rect.top) &&
7013             (width == (rect.right-rect.left)) &&
7014             (height == (rect.bottom-rect.top)) );
7015 #else
7016     BOOL fSizeValid = ( (x == rect.left) &&
7017             (y == rect.top) &&
7018             (width == (rect.right-rect.left)) &&
7019             (height == (rect.bottom-rect.top)) );
7020 #endif
7021 
7022     // See if visible state matches
7023     BOOL wndVisible = ::IsWindowVisible(GetHWnd());
7024     jboolean targetVisible;
7025     // To avoid possibly running client code on the toolkit thread, don't
7026     // do the following check if we're running on the toolkit thread.
7027     if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7028         targetVisible = JNU_CallMethodByName(env, NULL, GetTarget(env),
7029                                                   "isShowing", "()Z").z;
7030         DASSERT(!safe_ExceptionOccurred(env));
7031     } else {
7032         targetVisible = wndVisible ? 1 : 0;
7033     }
7034 #if 0
7035     DASSERT( (targetVisible && wndVisible) ||
7036             (!targetVisible && !wndVisible) );
7037 #else
7038     BOOL fVisibleValid = ( (targetVisible && wndVisible) ||
7039             (!targetVisible && !wndVisible) );
7040 #endif
7041 
7042     // Check enabled state
7043     BOOL wndEnabled = ::IsWindowEnabled(GetHWnd());
7044     jboolean enabled = (jboolean)env->GetBooleanField(target,
7045                                                       AwtComponent::enabledID);
7046 #if 0
7047     DASSERT( (enabled && wndEnabled) ||
7048             (!enabled && !wndEnabled) );
7049 #else
7050     BOOL fEnabledValid = ((enabled && wndEnabled) ||
7051                           (!(enabled && !wndEnabled) ));
7052 
7053     if (!fSizeValid || !fVisibleValid || !fEnabledValid) {
7054         printf("AwtComponent::ValidateState() failed:\n");
7055         // To avoid possibly running client code on the toolkit thread, don't
7056         // do the following call if we're running on the toolkit thread.
7057         if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7058             jstring targetStr =
7059                 (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),
7060                                               "getName",
7061                                               "()Ljava/lang/String;").l;
7062             DASSERT(!safe_ExceptionOccurred(env));
7063             LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
7064             printf("\t%S\n", targetStrW);
7065             JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
7066         }
7067         printf("\twas:       [%d,%d,%dx%d]\n", x, y, width, height);
7068         if (!fSizeValid) {
7069             printf("\tshould be: [%d,%d,%dx%d]\n", rect.left, rect.top,
7070                    rect.right-rect.left, rect.bottom-rect.top);
7071         }
7072         if (!fVisibleValid) {
7073             printf("\tshould be: %s\n",
7074                    (targetVisible) ? "visible" : "hidden");
7075         }
7076         if (!fEnabledValid) {
7077             printf("\tshould be: %s\n",
7078                    enabled ? "enabled" : "disabled");
7079         }
7080     }
7081 #endif
7082     env->PopLocalFrame(0);
7083 }
7084 #endif //DEBUG
7085 
7086 // Methods for globally managed DC list
7087 
7088 /**
7089  * Add a new DC to the DC list for this component.
7090  */
7091 void DCList::AddDC(HDC hDC, HWND hWnd)
7092 {
7093     DCItem *newItem = new DCItem;
7094     newItem->hDC = hDC;
7095     newItem->hWnd = hWnd;
7096     AddDCItem(newItem);
7097 }
7098 
7099 void DCList::AddDCItem(DCItem *newItem)
7100 {
7101     listLock.Enter();
7102     newItem->next = head;
7103     head = newItem;
7104     listLock.Leave();
7105 }
7106 
7107 /**
7108  * Given a DC, remove it from the DC list and return
7109  * TRUE if it exists on the current list.  Otherwise
7110  * return FALSE.
7111  * A DC may not exist on the list because it has already
7112  * been released elsewhere (for example, the window
7113  * destruction process may release a DC while a rendering
7114  * thread may also want to release a DC when it notices that
7115  * its DC is obsolete for the current window).
7116  */
7117 DCItem *DCList::RemoveDC(HDC hDC)
7118 {
7119     listLock.Enter();
7120     DCItem **prevPtrPtr = &head;
7121     DCItem *listPtr = head;
7122     while (listPtr) {
7123         DCItem *nextPtr = listPtr->next;
7124         if (listPtr->hDC == hDC) {
7125             *prevPtrPtr = nextPtr;
7126             break;
7127         }
7128         prevPtrPtr = &listPtr->next;
7129         listPtr = nextPtr;
7130     }
7131     listLock.Leave();
7132     return listPtr;
7133 }
7134 
7135 /**
7136  * Remove all DCs from the DC list which are associated with
7137  * the same window as hWnd.  Return the list of those
7138  * DC's to the caller (which will then probably want to
7139  * call ReleaseDC() for the returned DCs).
7140  */
7141 DCItem *DCList::RemoveAllDCs(HWND hWnd)
7142 {
7143     listLock.Enter();
7144     DCItem **prevPtrPtr = &head;
7145     DCItem *listPtr = head;
7146     DCItem *newListPtr = NULL;
7147     BOOL ret = FALSE;
7148     while (listPtr) {
7149         DCItem *nextPtr = listPtr->next;
7150         if (listPtr->hWnd == hWnd) {
7151             *prevPtrPtr = nextPtr;
7152             listPtr->next = newListPtr;
7153             newListPtr = listPtr;
7154         } else {
7155             prevPtrPtr = &listPtr->next;
7156         }
7157         listPtr = nextPtr;
7158     }
7159     listLock.Leave();
7160     return newListPtr;
7161 }
7162 
7163 
7164 /**
7165  * Realize palettes of all existing HDC objects
7166  */
7167 void DCList::RealizePalettes(int screen)
7168 {
7169     listLock.Enter();
7170     DCItem *listPtr = head;
7171     while (listPtr) {
7172         AwtWin32GraphicsDevice::RealizePalette(listPtr->hDC, screen);
7173         listPtr = listPtr->next;
7174     }
7175     listLock.Leave();
7176 }
7177 
7178 void MoveDCToPassiveList(HDC hDC) {
7179     DCItem *removedDC;
7180     if ((removedDC = activeDCList.RemoveDC(hDC)) != NULL) {
7181         passiveDCList.AddDCItem(removedDC);
7182     }
7183 }
7184 
7185 void ReleaseDCList(HWND hwnd, DCList &list) {
7186     DCItem *removedDCs = list.RemoveAllDCs(hwnd);
7187     while (removedDCs) {
7188         DCItem *tmpDCList = removedDCs;
7189         DASSERT(::GetObjectType(tmpDCList->hDC) == OBJ_DC);
7190         int retValue = ::ReleaseDC(tmpDCList->hWnd, tmpDCList->hDC);
7191         VERIFY(retValue != 0);
7192         if (retValue != 0) {
7193             // Valid ReleaseDC call; need to decrement GDI object counter
7194             AwtGDIObject::Decrement();
7195         }
7196         removedDCs = removedDCs->next;
7197         delete tmpDCList;
7198     }
7199 }