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         DWORD size = ::GetRegionData(rgn, 0, NULL);
2190         if (size == 0) {
2191             ::DeleteObject((HGDIOBJ)rgn);
2192             return;
2193         }
2194         char* buffer = new char[size]; // safe because sizeof(char)==1
2195         memset(buffer, 0, size);
2196         LPRGNDATA rgndata = (LPRGNDATA)buffer;
2197         rgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
2198         rgndata->rdh.iType = RDH_RECTANGLES;
2199         int retCode = ::GetRegionData(rgn, size, rgndata);
2200         VERIFY(retCode);
2201         if (retCode == 0) {
2202             delete [] buffer;
2203             ::DeleteObject((HGDIOBJ)rgn);
2204             return;
2205         }
2206         /*
2207          * Updating rects are divided into mostly vertical and mostly horizontal
2208          * Each group is united together and if not empty painted separately
2209          */
2210         RECT* r = (RECT*)(buffer + rgndata->rdh.dwSize);
2211         RECT* un[2] = {0, 0};
2212     DWORD i;
2213     for (i = 0; i < rgndata->rdh.nCount; i++, r++) {
2214             int width = r->right-r->left;
2215             int height = r->bottom-r->top;
2216             if (width > 0 && height > 0) {
2217                 int toAdd = (width > height) ? 0: 1;
2218                 if (un[toAdd] != 0) {
2219                     ::UnionRect(un[toAdd], un[toAdd], r);
2220                 } else {
2221                     un[toAdd] = r;
2222                 }
2223             }
2224         }
2225         for(i = 0; i < 2; i++) {
2226             if (un[i] != 0) {
2227                 DoCallback("handleExpose", "(IIII)V", un[i]->left, un[i]->top,
2228                     un[i]->right-un[i]->left, un[i]->bottom-un[i]->top);
2229             }
2230         }
2231         delete [] buffer;
2232     }
2233     ::DeleteObject((HGDIOBJ)rgn);
2234 }
2235 
2236 MsgRouting AwtComponent::WmMouseEnter(UINT flags, int x, int y)
2237 {
2238     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_ENTERED,
2239                    TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(), 0, JNI_FALSE);
2240     if ((flags & ALL_MK_BUTTONS) == 0) {
2241         AwtCursor::UpdateCursor(this);
2242     }
2243     sm_cursorOn = GetHWnd();
2244     return mrConsume;   /* Don't pass our synthetic event on! */
2245 }
2246 
2247 MSG*
2248 AwtComponent::CreateMessage(UINT message, WPARAM wParam, LPARAM lParam,
2249                             int x = 0, int y = 0)
2250 {
2251     MSG* pMsg = new MSG;
2252     InitMessage(pMsg, message, wParam, lParam, x, y);
2253     return pMsg;
2254 }
2255 
2256 
2257 jint
2258 AwtComponent::GetDrawState(HWND hwnd) {
2259     return (jint)(INT_PTR)(::GetProp(hwnd, DrawingStateProp));
2260 }
2261 
2262 void
2263 AwtComponent::SetDrawState(HWND hwnd, jint state) {
2264     ::SetProp(hwnd, DrawingStateProp, (HANDLE)(INT_PTR)state);
2265 }
2266 
2267 void
2268 AwtComponent::InitMessage(MSG* msg, UINT message, WPARAM wParam, LPARAM lParam,
2269                             int x = 0, int y = 0)
2270 {
2271     msg->message = message;
2272     msg->wParam = wParam;
2273     msg->lParam = lParam;
2274     msg->time = TimeHelper::getMessageTimeWindows();
2275     msg->pt.x = x;
2276     msg->pt.y = y;
2277 }
2278 
2279 MsgRouting AwtComponent::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
2280     return mrDoDefault;
2281 }
2282 MsgRouting AwtComponent::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) {
2283     return mrDoDefault;
2284 }
2285 
2286 MsgRouting AwtComponent::WmWindowPosChanging(LPARAM windowPos) {
2287     return mrDoDefault;
2288 }
2289 MsgRouting AwtComponent::WmWindowPosChanged(LPARAM windowPos) {
2290     return mrDoDefault;
2291 }
2292 
2293 /* Double-click variables. */
2294 static jlong multiClickTime = ::GetDoubleClickTime();
2295 static int multiClickMaxX = ::GetSystemMetrics(SM_CXDOUBLECLK);
2296 static int multiClickMaxY = ::GetSystemMetrics(SM_CYDOUBLECLK);
2297 static AwtComponent* lastClickWnd = NULL;
2298 static jlong lastTime = 0;
2299 static int lastClickX = 0;
2300 static int lastClickY = 0;
2301 static int lastButton = 0;
2302 static int clickCount = 0;
2303 
2304 // A static method that makes the clickCount available in the derived classes
2305 // overriding WmMouseDown().
2306 int AwtComponent::GetClickCount()
2307 {
2308     return clickCount;
2309 }
2310 
2311 MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button)
2312 {
2313     jlong now = TimeHelper::getMessageTimeUTC();
2314 
2315     if (lastClickWnd == this &&
2316         lastButton == button &&
2317         (now - lastTime) <= multiClickTime &&
2318         abs(x - lastClickX) <= multiClickMaxX &&
2319         abs(y - lastClickY) <= multiClickMaxY)
2320     {
2321         clickCount++;
2322     } else {
2323         clickCount = 1;
2324         lastClickWnd = this;
2325         lastButton = button;
2326         lastClickX = x;
2327         lastClickY = y;
2328     }
2329     /*
2330      *Set appropriate bit of the mask on WM_MOUSE_DOWN message.
2331      */
2332     m_mouseButtonClickAllowed |= GetButtonMK(button);
2333     lastTime = now;
2334 
2335     MSG msg;
2336     InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2337 
2338     AwtWindow *toplevel = GetContainer();
2339     if (toplevel && !toplevel->IsSimpleWindow()) {
2340         /*
2341          * The frame should be focused by click in case it is
2342          * the active window but not the focused window. See 6886678.
2343          */
2344         if (toplevel->GetHWnd() == ::GetActiveWindow() &&
2345             toplevel->GetHWnd() != AwtComponent::GetFocusedWindow())
2346         {
2347             toplevel->AwtSetActiveWindow();
2348         }
2349     }
2350 
2351     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y,
2352                    GetJavaModifiers(), clickCount, JNI_FALSE,
2353                    GetButton(button), &msg);
2354     /*
2355      * NOTE: this call is intentionally placed after all other code,
2356      * since AwtComponent::WmMouseDown() assumes that the cached id of the
2357      * latest retrieved message (see lastMessage in awt_Component.cpp)
2358      * matches the mouse message being processed.
2359      * SetCapture() sends WM_CAPTURECHANGED and breaks that
2360      * assumption.
2361      */
2362     SetDragCapture(flags);
2363 
2364     AwtWindow * owner = (AwtWindow*)GetComponent(GetTopLevelParentForWindow(GetHWnd()));
2365     if (AwtWindow::GetGrabbedWindow() != NULL && owner != NULL) {
2366         if (!AwtWindow::GetGrabbedWindow()->IsOneOfOwnersOf(owner)) {
2367             AwtWindow::GetGrabbedWindow()->Ungrab();
2368         }
2369     }
2370     return mrConsume;
2371 }
2372 
2373 MsgRouting AwtComponent::WmMouseUp(UINT flags, int x, int y, int button)
2374 {
2375     MSG msg;
2376     InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2377 
2378     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, TimeHelper::getMessageTimeUTC(),
2379                    x, y, GetJavaModifiers(), clickCount,
2380                    (GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
2381                     TRUE : FALSE), GetButton(button), &msg);
2382     /*
2383      * If no movement, then report a click following the button release.
2384      * When WM_MOUSEUP comes to a window without previous WM_MOUSEDOWN,
2385      * spurous MOUSE_CLICK is about to happen. See 6430553.
2386      */
2387     if ((m_mouseButtonClickAllowed & GetButtonMK(button)) != 0) { //CLICK allowed
2388         SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
2389                        TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(),
2390                        clickCount, JNI_FALSE, GetButton(button));
2391     }
2392     // Exclude button from allowed to generate CLICK messages
2393     m_mouseButtonClickAllowed &= ~GetButtonMK(button);
2394 
2395     if ((flags & ALL_MK_BUTTONS) == 0) {
2396         // only update if all buttons have been released
2397         AwtCursor::UpdateCursor(this);
2398     }
2399     /*
2400      * NOTE: this call is intentionally placed after all other code,
2401      * since AwtComponent::WmMouseUp() assumes that the cached id of the
2402      * latest retrieved message (see lastMessage in awt_Component.cpp)
2403      * matches the mouse message being processed.
2404      * ReleaseCapture() sends WM_CAPTURECHANGED and breaks that
2405      * assumption.
2406      */
2407     ReleaseDragCapture(flags);
2408 
2409     return mrConsume;
2410 }
2411 
2412 MsgRouting AwtComponent::WmMouseMove(UINT flags, int x, int y)
2413 {
2414     static AwtComponent* lastComp = NULL;
2415     static int lastX = 0;
2416     static int lastY = 0;
2417 
2418     /*
2419      * Only report mouse move and drag events if a move or drag
2420      * actually happened -- Windows sends a WM_MOUSEMOVE in case the
2421      * app wants to modify the cursor.
2422      */
2423     if (lastComp != this || x != lastX || y != lastY) {
2424         lastComp = this;
2425         lastX = x;
2426         lastY = y;
2427         BOOL extraButtonsEnabled = AwtToolkit::GetInstance().areExtraMouseButtonsEnabled();
2428         if (((flags & (ALL_MK_BUTTONS)) != 0) ||
2429             (extraButtonsEnabled && (flags & (X_BUTTONS)) != 0))
2430 //        if (( extraButtonsEnabled && ( (flags & (ALL_MK_BUTTONS | X_BUTTONS)) != 0 )) ||
2431 //            ( !extraButtonsEnabled && (((flags & (ALL_MK_BUTTONS)) != 0 )) && ((flags & (X_BUTTONS)) == 0) ))
2432         {
2433             // 6404008 : if Dragged event fired we shouldn't fire
2434             // Clicked event: m_firstDragSent set to TRUE.
2435             // This is a partial backout of 5039416 fix.
2436             MSG msg;
2437             InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2438             SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, TimeHelper::getMessageTimeUTC(), x, y,
2439                            GetJavaModifiers(), 0, JNI_FALSE,
2440                            java_awt_event_MouseEvent_NOBUTTON, &msg);
2441             //dragging means no more CLICKs until next WM_MOUSE_DOWN/WM_MOUSE_UP message sequence
2442             m_mouseButtonClickAllowed = 0;
2443         } else {
2444             MSG msg;
2445             InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2446             SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::getMessageTimeUTC(), x, y,
2447                            GetJavaModifiers(), 0, JNI_FALSE,
2448                            java_awt_event_MouseEvent_NOBUTTON, &msg);
2449         }
2450     }
2451 
2452     return mrConsume;
2453 }
2454 
2455 MsgRouting AwtComponent::WmMouseExit(UINT flags, int x, int y)
2456 {
2457     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_EXITED, TimeHelper::getMessageTimeUTC(), x,
2458                    y, GetJavaModifiers(), 0, JNI_FALSE);
2459     sm_cursorOn = NULL;
2460     return mrConsume;   /* Don't pass our synthetic event on! */
2461 }
2462 
2463 MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y,
2464                                       int wheelRotation)
2465 {
2466     // convert coordinates to be Component-relative, not screen relative
2467     // for wheeling when outside the window, this works similar to
2468     // coordinates during a drag
2469     POINT eventPt;
2470     eventPt.x = x;
2471     eventPt.y = y;
2472     DTRACE_PRINT2("  original coords: %i,%i\n", x, y);
2473     ::ScreenToClient(GetHWnd(), &eventPt);
2474     DTRACE_PRINT2("  new coords: %i,%i\n\n", eventPt.x, eventPt.y);
2475 
2476     // set some defaults
2477     jint scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL;
2478     jint scrollLines = 3;
2479 
2480     BOOL result;
2481     UINT platformLines;
2482 
2483     m_wheelRotationAmount += wheelRotation;
2484 
2485     // AWT interprets wheel rotation differently than win32, so we need to
2486     // decode wheel amount.
2487     jint roundedWheelRotation = m_wheelRotationAmount / (-1 * WHEEL_DELTA);
2488     jdouble preciseWheelRotation = (jdouble) wheelRotation / (-1 * WHEEL_DELTA);
2489 
2490     MSG msg;
2491     result = ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
2492                                     &platformLines, 0);
2493     InitMessage(&msg, lastMessage, MAKEWPARAM(flags, wheelRotation),
2494                 MAKELPARAM(x, y));
2495 
2496     if (result) {
2497         if (platformLines == WHEEL_PAGESCROLL) {
2498             scrollType = java_awt_event_MouseWheelEvent_WHEEL_BLOCK_SCROLL;
2499             scrollLines = 1;
2500         }
2501         else {
2502             scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL;
2503             scrollLines = platformLines;
2504         }
2505     }
2506 
2507     DTRACE_PRINTLN("calling SendMouseWheelEvent");
2508 
2509     SendMouseWheelEvent(java_awt_event_MouseEvent_MOUSE_WHEEL, TimeHelper::getMessageTimeUTC(),
2510                         eventPt.x, eventPt.y, GetJavaModifiers(), 0, 0, scrollType,
2511                         scrollLines, roundedWheelRotation, preciseWheelRotation, &msg);
2512 
2513     m_wheelRotationAmount %= WHEEL_DELTA;
2514     // this message could be propagated up to the parent chain
2515     // by the mouse message post processors
2516     return mrConsume;
2517 }
2518 
2519 jint AwtComponent::GetKeyLocation(UINT wkey, UINT flags) {
2520     // Rector+Newcomer page 413
2521     // The extended keys are the Alt and Control on the right of
2522     // the space bar, the non-Numpad arrow keys, the non-Numpad
2523     // Insert, PageUp, etc. keys, and the Numpad Divide and Enter keys.
2524     // Note that neither Shift key is extended.
2525     // Although not listed in Rector+Newcomer, both Windows keys
2526     // (91 and 92) are extended keys, the Context Menu key
2527     // (property key or application key - 93) is extended,
2528     // and so is the NumLock key.
2529 
2530     // wkey is the wParam, flags is the HIWORD of the lParam
2531 
2532     // "Extended" bit is 24th in lParam, so it's 8th in flags = HIWORD(lParam)
2533     BOOL extended = ((1<<8) & flags);
2534 
2535     if (IsNumPadKey(wkey, extended)) {
2536         return java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD;
2537     }
2538 
2539     switch (wkey) {
2540       case VK_SHIFT:
2541         return AwtComponent::GetShiftKeyLocation(wkey, flags);
2542       case VK_CONTROL: // fall through
2543       case VK_MENU:
2544         if (extended) {
2545             return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
2546         } else {
2547             return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2548         }
2549       case VK_LWIN:
2550         return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2551       case VK_RWIN:
2552         return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
2553       default:
2554         break;
2555     }
2556 
2557     // REMIND: if we add keycodes for the windows keys, we'll have to
2558     // include left/right discrimination code for them.
2559 
2560     return java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
2561 }
2562 
2563 jint AwtComponent::GetShiftKeyLocation(UINT vkey, UINT flags)
2564 {
2565     // init scancodes to safe values
2566     UINT leftShiftScancode = 0;
2567     UINT rightShiftScancode = 0;
2568 
2569     // First 8 bits of flags is the scancode
2570     UINT keyScanCode = flags & 0xFF;
2571 
2572     DTRACE_PRINTLN3(
2573       "AwtComponent::GetShiftKeyLocation  vkey = %d = 0x%x  scan = %d",
2574       vkey, vkey, keyScanCode);
2575 
2576     leftShiftScancode = ::MapVirtualKey(VK_LSHIFT, 0);
2577     rightShiftScancode = ::MapVirtualKey(VK_RSHIFT, 0);
2578 
2579     if (keyScanCode == leftShiftScancode) {
2580         return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2581     }
2582     if (keyScanCode == rightShiftScancode) {
2583         return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
2584     }
2585 
2586     DASSERT(false);
2587     // Note: the above should not fail on NT (or 2000)
2588 
2589     // default value
2590     return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2591 }
2592 
2593 /* Returns Java extended InputEvent modifieres.
2594  * Since ::GetKeyState returns current state and Java modifiers represent
2595  * state before event, modifier on changed key are inverted.
2596  */
2597 jint
2598 AwtComponent::GetJavaModifiers()
2599 {
2600     jint modifiers = 0;
2601 
2602     if (HIBYTE(::GetKeyState(VK_CONTROL)) != 0) {
2603         modifiers |= java_awt_event_InputEvent_CTRL_DOWN_MASK;
2604     }
2605     if (HIBYTE(::GetKeyState(VK_SHIFT)) != 0) {
2606         modifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK;
2607     }
2608     if (HIBYTE(::GetKeyState(VK_MENU)) != 0) {
2609         modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK;
2610     }
2611     if (HIBYTE(::GetKeyState(VK_MBUTTON)) != 0) {
2612        modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK;
2613     }
2614     if (HIBYTE(::GetKeyState(VK_RBUTTON)) != 0) {
2615         modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK;
2616     }
2617     if (HIBYTE(::GetKeyState(VK_LBUTTON)) != 0) {
2618         modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK;
2619     }
2620 
2621     if (HIBYTE(::GetKeyState(VK_XBUTTON1)) != 0) {
2622         modifiers |= masks[3];
2623     }
2624     if (HIBYTE(::GetKeyState(VK_XBUTTON2)) != 0) {
2625         modifiers |= masks[4];
2626     }
2627     return modifiers;
2628 }
2629 
2630 jint
2631 AwtComponent::GetButton(int mouseButton)
2632 {
2633     /* Mouse buttons are already set correctly for left/right handedness */
2634     switch(mouseButton) {
2635     case LEFT_BUTTON:
2636         return java_awt_event_MouseEvent_BUTTON1;
2637     case MIDDLE_BUTTON:
2638         return java_awt_event_MouseEvent_BUTTON2;
2639     case RIGHT_BUTTON:
2640         return java_awt_event_MouseEvent_BUTTON3;
2641     case X1_BUTTON: //16 :
2642         //just assign 4 and 5 numbers because MouseEvent class doesn't contain const identifier for them now
2643         return 4;
2644     case X2_BUTTON: //32
2645         return 5;
2646     }
2647     return java_awt_event_MouseEvent_NOBUTTON;
2648 }
2649 
2650 UINT
2651 AwtComponent::GetButtonMK(int mouseButton)
2652 {
2653     switch(mouseButton) {
2654     case LEFT_BUTTON:
2655         return MK_LBUTTON;
2656     case MIDDLE_BUTTON:
2657         return MK_MBUTTON;
2658     case RIGHT_BUTTON:
2659         return MK_RBUTTON;
2660     case X1_BUTTON:
2661         return MK_XBUTTON1;
2662     case X2_BUTTON:
2663         return MK_XBUTTON2;
2664     }
2665     return 0;
2666 }
2667 
2668 // FIXME: Keyboard related stuff has grown so big and hairy that we
2669 // really need to move it into a class of its own.  And, since
2670 // keyboard is a shared resource, AwtComponent is a bad place for it.
2671 
2672 // These constants are defined in the Japanese version of VC++5.0,
2673 // but not the US version
2674 #ifndef VK_CONVERT
2675 #define VK_KANA           0x15
2676 #define VK_KANJI          0x19
2677 #define VK_CONVERT        0x1C
2678 #define VK_NONCONVERT     0x1D
2679 #endif
2680 
2681 #ifndef VK_XBUTTON1
2682 #define VK_XBUTTON1      0x05
2683 #endif
2684 
2685 #ifndef VK_XBUTTON2
2686 #define VK_XBUTTON2      0x06
2687 #endif
2688 
2689 typedef struct {
2690     UINT javaKey;
2691     UINT windowsKey;
2692 } KeyMapEntry;
2693 
2694 // Static table, arranged more or less spatially.
2695 KeyMapEntry keyMapTable[] = {
2696     // Modifier keys
2697     {java_awt_event_KeyEvent_VK_CAPS_LOCK,        VK_CAPITAL},
2698     {java_awt_event_KeyEvent_VK_SHIFT,            VK_SHIFT},
2699     {java_awt_event_KeyEvent_VK_CONTROL,          VK_CONTROL},
2700     {java_awt_event_KeyEvent_VK_ALT,              VK_MENU},
2701     {java_awt_event_KeyEvent_VK_NUM_LOCK,         VK_NUMLOCK},
2702 
2703     // Miscellaneous Windows keys
2704     {java_awt_event_KeyEvent_VK_WINDOWS,          VK_LWIN},
2705     {java_awt_event_KeyEvent_VK_WINDOWS,          VK_RWIN},
2706     {java_awt_event_KeyEvent_VK_CONTEXT_MENU,     VK_APPS},
2707 
2708     // Alphabet
2709     {java_awt_event_KeyEvent_VK_A,                'A'},
2710     {java_awt_event_KeyEvent_VK_B,                'B'},
2711     {java_awt_event_KeyEvent_VK_C,                'C'},
2712     {java_awt_event_KeyEvent_VK_D,                'D'},
2713     {java_awt_event_KeyEvent_VK_E,                'E'},
2714     {java_awt_event_KeyEvent_VK_F,                'F'},
2715     {java_awt_event_KeyEvent_VK_G,                'G'},
2716     {java_awt_event_KeyEvent_VK_H,                'H'},
2717     {java_awt_event_KeyEvent_VK_I,                'I'},
2718     {java_awt_event_KeyEvent_VK_J,                'J'},
2719     {java_awt_event_KeyEvent_VK_K,                'K'},
2720     {java_awt_event_KeyEvent_VK_L,                'L'},
2721     {java_awt_event_KeyEvent_VK_M,                'M'},
2722     {java_awt_event_KeyEvent_VK_N,                'N'},
2723     {java_awt_event_KeyEvent_VK_O,                'O'},
2724     {java_awt_event_KeyEvent_VK_P,                'P'},
2725     {java_awt_event_KeyEvent_VK_Q,                'Q'},
2726     {java_awt_event_KeyEvent_VK_R,                'R'},
2727     {java_awt_event_KeyEvent_VK_S,                'S'},
2728     {java_awt_event_KeyEvent_VK_T,                'T'},
2729     {java_awt_event_KeyEvent_VK_U,                'U'},
2730     {java_awt_event_KeyEvent_VK_V,                'V'},
2731     {java_awt_event_KeyEvent_VK_W,                'W'},
2732     {java_awt_event_KeyEvent_VK_X,                'X'},
2733     {java_awt_event_KeyEvent_VK_Y,                'Y'},
2734     {java_awt_event_KeyEvent_VK_Z,                'Z'},
2735 
2736     // Standard numeric row
2737     {java_awt_event_KeyEvent_VK_0,                '0'},
2738     {java_awt_event_KeyEvent_VK_1,                '1'},
2739     {java_awt_event_KeyEvent_VK_2,                '2'},
2740     {java_awt_event_KeyEvent_VK_3,                '3'},
2741     {java_awt_event_KeyEvent_VK_4,                '4'},
2742     {java_awt_event_KeyEvent_VK_5,                '5'},
2743     {java_awt_event_KeyEvent_VK_6,                '6'},
2744     {java_awt_event_KeyEvent_VK_7,                '7'},
2745     {java_awt_event_KeyEvent_VK_8,                '8'},
2746     {java_awt_event_KeyEvent_VK_9,                '9'},
2747 
2748     // Misc key from main block
2749     {java_awt_event_KeyEvent_VK_ENTER,            VK_RETURN},
2750     {java_awt_event_KeyEvent_VK_SPACE,            VK_SPACE},
2751     {java_awt_event_KeyEvent_VK_BACK_SPACE,       VK_BACK},
2752     {java_awt_event_KeyEvent_VK_TAB,              VK_TAB},
2753     {java_awt_event_KeyEvent_VK_ESCAPE,           VK_ESCAPE},
2754 
2755     // NumPad with NumLock off & extended block (rectangular)
2756     {java_awt_event_KeyEvent_VK_INSERT,           VK_INSERT},
2757     {java_awt_event_KeyEvent_VK_DELETE,           VK_DELETE},
2758     {java_awt_event_KeyEvent_VK_HOME,             VK_HOME},
2759     {java_awt_event_KeyEvent_VK_END,              VK_END},
2760     {java_awt_event_KeyEvent_VK_PAGE_UP,          VK_PRIOR},
2761     {java_awt_event_KeyEvent_VK_PAGE_DOWN,        VK_NEXT},
2762     {java_awt_event_KeyEvent_VK_CLEAR,            VK_CLEAR}, // NumPad 5
2763 
2764     // NumPad with NumLock off & extended arrows block (triangular)
2765     {java_awt_event_KeyEvent_VK_LEFT,             VK_LEFT},
2766     {java_awt_event_KeyEvent_VK_RIGHT,            VK_RIGHT},
2767     {java_awt_event_KeyEvent_VK_UP,               VK_UP},
2768     {java_awt_event_KeyEvent_VK_DOWN,             VK_DOWN},
2769 
2770     // NumPad with NumLock on: numbers
2771     {java_awt_event_KeyEvent_VK_NUMPAD0,          VK_NUMPAD0},
2772     {java_awt_event_KeyEvent_VK_NUMPAD1,          VK_NUMPAD1},
2773     {java_awt_event_KeyEvent_VK_NUMPAD2,          VK_NUMPAD2},
2774     {java_awt_event_KeyEvent_VK_NUMPAD3,          VK_NUMPAD3},
2775     {java_awt_event_KeyEvent_VK_NUMPAD4,          VK_NUMPAD4},
2776     {java_awt_event_KeyEvent_VK_NUMPAD5,          VK_NUMPAD5},
2777     {java_awt_event_KeyEvent_VK_NUMPAD6,          VK_NUMPAD6},
2778     {java_awt_event_KeyEvent_VK_NUMPAD7,          VK_NUMPAD7},
2779     {java_awt_event_KeyEvent_VK_NUMPAD8,          VK_NUMPAD8},
2780     {java_awt_event_KeyEvent_VK_NUMPAD9,          VK_NUMPAD9},
2781 
2782     // NumPad with NumLock on
2783     {java_awt_event_KeyEvent_VK_MULTIPLY,         VK_MULTIPLY},
2784     {java_awt_event_KeyEvent_VK_ADD,              VK_ADD},
2785     {java_awt_event_KeyEvent_VK_SEPARATOR,        VK_SEPARATOR},
2786     {java_awt_event_KeyEvent_VK_SUBTRACT,         VK_SUBTRACT},
2787     {java_awt_event_KeyEvent_VK_DECIMAL,          VK_DECIMAL},
2788     {java_awt_event_KeyEvent_VK_DIVIDE,           VK_DIVIDE},
2789 
2790     // Functional keys
2791     {java_awt_event_KeyEvent_VK_F1,               VK_F1},
2792     {java_awt_event_KeyEvent_VK_F2,               VK_F2},
2793     {java_awt_event_KeyEvent_VK_F3,               VK_F3},
2794     {java_awt_event_KeyEvent_VK_F4,               VK_F4},
2795     {java_awt_event_KeyEvent_VK_F5,               VK_F5},
2796     {java_awt_event_KeyEvent_VK_F6,               VK_F6},
2797     {java_awt_event_KeyEvent_VK_F7,               VK_F7},
2798     {java_awt_event_KeyEvent_VK_F8,               VK_F8},
2799     {java_awt_event_KeyEvent_VK_F9,               VK_F9},
2800     {java_awt_event_KeyEvent_VK_F10,              VK_F10},
2801     {java_awt_event_KeyEvent_VK_F11,              VK_F11},
2802     {java_awt_event_KeyEvent_VK_F12,              VK_F12},
2803     {java_awt_event_KeyEvent_VK_F13,              VK_F13},
2804     {java_awt_event_KeyEvent_VK_F14,              VK_F14},
2805     {java_awt_event_KeyEvent_VK_F15,              VK_F15},
2806     {java_awt_event_KeyEvent_VK_F16,              VK_F16},
2807     {java_awt_event_KeyEvent_VK_F17,              VK_F17},
2808     {java_awt_event_KeyEvent_VK_F18,              VK_F18},
2809     {java_awt_event_KeyEvent_VK_F19,              VK_F19},
2810     {java_awt_event_KeyEvent_VK_F20,              VK_F20},
2811     {java_awt_event_KeyEvent_VK_F21,              VK_F21},
2812     {java_awt_event_KeyEvent_VK_F22,              VK_F22},
2813     {java_awt_event_KeyEvent_VK_F23,              VK_F23},
2814     {java_awt_event_KeyEvent_VK_F24,              VK_F24},
2815 
2816     {java_awt_event_KeyEvent_VK_PRINTSCREEN,      VK_SNAPSHOT},
2817     {java_awt_event_KeyEvent_VK_SCROLL_LOCK,      VK_SCROLL},
2818     {java_awt_event_KeyEvent_VK_PAUSE,            VK_PAUSE},
2819     {java_awt_event_KeyEvent_VK_CANCEL,           VK_CANCEL},
2820     {java_awt_event_KeyEvent_VK_HELP,             VK_HELP},
2821 
2822     // Japanese
2823     {java_awt_event_KeyEvent_VK_CONVERT,          VK_CONVERT},
2824     {java_awt_event_KeyEvent_VK_NONCONVERT,       VK_NONCONVERT},
2825     {java_awt_event_KeyEvent_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
2826     {java_awt_event_KeyEvent_VK_ALPHANUMERIC,     VK_DBE_ALPHANUMERIC},
2827     {java_awt_event_KeyEvent_VK_KATAKANA,         VK_DBE_KATAKANA},
2828     {java_awt_event_KeyEvent_VK_HIRAGANA,         VK_DBE_HIRAGANA},
2829     {java_awt_event_KeyEvent_VK_FULL_WIDTH,       VK_DBE_DBCSCHAR},
2830     {java_awt_event_KeyEvent_VK_HALF_WIDTH,       VK_DBE_SBCSCHAR},
2831     {java_awt_event_KeyEvent_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},
2832 
2833     {java_awt_event_KeyEvent_VK_UNDEFINED,        0}
2834 };
2835 
2836 
2837 // Dynamic mapping table for OEM VK codes.  This table is refilled
2838 // by BuildDynamicKeyMapTable when keyboard layout is switched.
2839 // (see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
2840 struct DynamicKeyMapEntry {
2841     UINT windowsKey;            // OEM VK codes known in advance
2842     UINT javaKey;               // depends on input langauge (kbd layout)
2843 };
2844 
2845 static DynamicKeyMapEntry dynamicKeyMapTable[] = {
2846     {0x00BA,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_1
2847     {0x00BB,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PLUS
2848     {0x00BC,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_COMMA
2849     {0x00BD,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_MINUS
2850     {0x00BE,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PERIOD
2851     {0x00BF,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_2
2852     {0x00C0,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_3
2853     {0x00DB,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_4
2854     {0x00DC,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_5
2855     {0x00DD,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_6
2856     {0x00DE,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_7
2857     {0x00DF,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_8
2858     {0x00E2,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_102
2859     {0, 0}
2860 };
2861 
2862 
2863 
2864 // Auxiliary tables used to fill the above dynamic table.  We first
2865 // find the character for the OEM VK code using ::MapVirtualKey and
2866 // then go through these auxiliary tables to map it to Java VK code.
2867 
2868 struct CharToVKEntry {
2869     WCHAR c;
2870     UINT  javaKey;
2871 };
2872 
2873 static const CharToVKEntry charToVKTable[] = {
2874     {L'!',   java_awt_event_KeyEvent_VK_EXCLAMATION_MARK},
2875     {L'"',   java_awt_event_KeyEvent_VK_QUOTEDBL},
2876     {L'#',   java_awt_event_KeyEvent_VK_NUMBER_SIGN},
2877     {L'$',   java_awt_event_KeyEvent_VK_DOLLAR},
2878     {L'&',   java_awt_event_KeyEvent_VK_AMPERSAND},
2879     {L'\'',  java_awt_event_KeyEvent_VK_QUOTE},
2880     {L'(',   java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS},
2881     {L')',   java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS},
2882     {L'*',   java_awt_event_KeyEvent_VK_ASTERISK},
2883     {L'+',   java_awt_event_KeyEvent_VK_PLUS},
2884     {L',',   java_awt_event_KeyEvent_VK_COMMA},
2885     {L'-',   java_awt_event_KeyEvent_VK_MINUS},
2886     {L'.',   java_awt_event_KeyEvent_VK_PERIOD},
2887     {L'/',   java_awt_event_KeyEvent_VK_SLASH},
2888     {L':',   java_awt_event_KeyEvent_VK_COLON},
2889     {L';',   java_awt_event_KeyEvent_VK_SEMICOLON},
2890     {L'<',   java_awt_event_KeyEvent_VK_LESS},
2891     {L'=',   java_awt_event_KeyEvent_VK_EQUALS},
2892     {L'>',   java_awt_event_KeyEvent_VK_GREATER},
2893     {L'@',   java_awt_event_KeyEvent_VK_AT},
2894     {L'[',   java_awt_event_KeyEvent_VK_OPEN_BRACKET},
2895     {L'\\',  java_awt_event_KeyEvent_VK_BACK_SLASH},
2896     {L']',   java_awt_event_KeyEvent_VK_CLOSE_BRACKET},
2897     {L'^',   java_awt_event_KeyEvent_VK_CIRCUMFLEX},
2898     {L'_',   java_awt_event_KeyEvent_VK_UNDERSCORE},
2899     {L'`',   java_awt_event_KeyEvent_VK_BACK_QUOTE},
2900     {L'{',   java_awt_event_KeyEvent_VK_BRACELEFT},
2901     {L'}',   java_awt_event_KeyEvent_VK_BRACERIGHT},
2902     {0x00A1, java_awt_event_KeyEvent_VK_INVERTED_EXCLAMATION_MARK},
2903     {0x20A0, java_awt_event_KeyEvent_VK_EURO_SIGN}, // ????
2904     {0,0}
2905 };
2906 
2907 // For dead accents some layouts return ASCII punctuation, while some
2908 // return spacing accent chars, so both should be listed.  NB: MS docs
2909 // say that conversion routings return spacing accent character, not
2910 // combining.
2911 static const CharToVKEntry charToDeadVKTable[] = {
2912     {L'`',   java_awt_event_KeyEvent_VK_DEAD_GRAVE},
2913     {L'\'',  java_awt_event_KeyEvent_VK_DEAD_ACUTE},
2914     {0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE},
2915     {L'^',   java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX},
2916     {L'~',   java_awt_event_KeyEvent_VK_DEAD_TILDE},
2917     {0x02DC, java_awt_event_KeyEvent_VK_DEAD_TILDE},
2918     {0x00AF, java_awt_event_KeyEvent_VK_DEAD_MACRON},
2919     {0x02D8, java_awt_event_KeyEvent_VK_DEAD_BREVE},
2920     {0x02D9, java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT},
2921     {L'"',   java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
2922     {0x00A8, java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
2923     {0x02DA, java_awt_event_KeyEvent_VK_DEAD_ABOVERING},
2924     {0x02DD, java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE},
2925     {0x02C7, java_awt_event_KeyEvent_VK_DEAD_CARON},            // aka hacek
2926     {L',',   java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
2927     {0x00B8, java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
2928     {0x02DB, java_awt_event_KeyEvent_VK_DEAD_OGONEK},
2929     {0x037A, java_awt_event_KeyEvent_VK_DEAD_IOTA},             // ASCII ???
2930     {0x309B, java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND},
2931     {0x309C, java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND},
2932     {0,0}
2933 };
2934 
2935 // The full map of the current keyboard state including
2936 // windows virtual key, scancode, java virtual key, and unicode
2937 // for this key sans modifiers.
2938 // All but first element may be 0.
2939 // XXX in the update releases this is an addition to the unchanged existing code
2940 struct DynPrimaryKeymapEntry {
2941     UINT wkey;
2942     UINT scancode;
2943     UINT jkey;
2944     WCHAR unicode;
2945 };
2946 
2947 static DynPrimaryKeymapEntry dynPrimaryKeymap[256];
2948 
2949 void
2950 AwtComponent::InitDynamicKeyMapTable()
2951 {
2952     static BOOL kbdinited = FALSE;
2953 
2954     if (!kbdinited) {
2955         AwtComponent::BuildDynamicKeyMapTable();
2956         // We cannot build it here since JNI is not available yet:
2957         //AwtComponent::BuildPrimaryDynamicTable();
2958         kbdinited = TRUE;
2959     }
2960 }
2961 
2962 void
2963 AwtComponent::BuildDynamicKeyMapTable()
2964 {
2965     HKL hkl = GetKeyboardLayout();
2966 
2967     DTRACE_PRINTLN2("Building dynamic VK mapping tables: HKL = %08X (CP%d)",
2968                     hkl, AwtComponent::GetCodePage());
2969 
2970     // Will need this to reset layout after dead keys.
2971     UINT spaceScanCode = ::MapVirtualKeyEx(VK_SPACE, 0, hkl);
2972 
2973     // Entries in dynamic table that maps between Java VK and Windows
2974     // VK are built in three steps:
2975     //   1. Map windows VK to ANSI character (cannot map to unicode
2976     //      directly, since ::ToUnicode is not implemented on win9x)
2977     //   2. Convert ANSI char to Unicode char
2978     //   3. Map Unicode char to Java VK via two auxilary tables.
2979 
2980     for (DynamicKeyMapEntry *dynamic = dynamicKeyMapTable;
2981          dynamic->windowsKey != 0;
2982          ++dynamic)
2983     {
2984         // Defaults to VK_UNDEFINED
2985         dynamic->javaKey = java_awt_event_KeyEvent_VK_UNDEFINED;
2986 
2987         BYTE kbdState[AwtToolkit::KB_STATE_SIZE];
2988         AwtToolkit::GetKeyboardState(kbdState);
2989 
2990         kbdState[dynamic->windowsKey] |=  0x80; // Press the key.
2991 
2992         // Unpress modifiers, since they are most likely pressed as
2993         // part of the keyboard switching shortcut.
2994         kbdState[VK_CONTROL] &= ~0x80;
2995         kbdState[VK_SHIFT]   &= ~0x80;
2996         kbdState[VK_MENU]    &= ~0x80;
2997 
2998         char cbuf[2] = { '\0', '\0'};
2999         UINT scancode = ::MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
3000         int nchars = ::ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
3001                                  (WORD*)cbuf, 0, hkl);
3002 
3003         // Auxiliary table used to map Unicode character to Java VK.
3004         // Will assign a different table for dead keys (below).
3005         const CharToVKEntry *charMap = charToVKTable;
3006 
3007         if (nchars < 0) { // Dead key
3008             // Use a different table for dead chars since different layouts
3009             // return different characters for the same dead key.
3010             charMap = charToDeadVKTable;
3011 
3012             // We also need to reset layout so that next translation
3013             // is unaffected by the dead status.  We do this by
3014             // translating <SPACE> key.
3015             kbdState[dynamic->windowsKey] &= ~0x80;
3016             kbdState[VK_SPACE] |= 0x80;
3017 
3018             char junkbuf[2] = { '\0', '\0'};
3019             ::ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
3020                         (WORD*)junkbuf, 0, hkl);
3021         }
3022 
3023 #ifdef DEBUG
3024         if (nchars == 0) {
3025             DTRACE_PRINTLN1("VK 0x%02X -> cannot convert to ANSI char",
3026                             dynamic->windowsKey);
3027             continue;
3028         }
3029         else if (nchars > 1) {  // can't happen, see reset code below
3030             DTRACE_PRINTLN3("VK 0x%02X -> converted to <0x%02X,0x%02X>",
3031                             dynamic->windowsKey,
3032                             (UCHAR)cbuf[0], (UCHAR)cbuf[1]);
3033             continue;
3034         }
3035 #endif
3036 
3037         WCHAR ucbuf[2] = { L'\0', L'\0' };
3038         int nconverted = ::MultiByteToWideChar(AwtComponent::GetCodePage(), 0,
3039                                                cbuf, 1, ucbuf, 2);
3040 #ifdef DEBUG
3041         if (nconverted < 0) {
3042             DTRACE_PRINTLN3("VK 0x%02X -> ANSI 0x%02X -> MultiByteToWideChar failed (0x%X)",
3043                             dynamic->windowsKey, (UCHAR)cbuf[0],
3044                             ::GetLastError());
3045             continue;
3046         }
3047 #endif
3048 
3049         WCHAR uc = ucbuf[0];
3050         for (const CharToVKEntry *map = charMap;  map->c != 0;  ++map) {
3051             if (uc == map->c) {
3052                 dynamic->javaKey = map->javaKey;
3053                 break;
3054             }
3055         }
3056 
3057         DTRACE_PRINTLN4("VK 0x%02X -> ANSI 0x%02X -> U+%04X -> Java VK 0x%X",
3058                         dynamic->windowsKey, (UCHAR)cbuf[0], (UINT)ucbuf[0],
3059                         dynamic->javaKey);
3060     } // for each VK_OEM_*
3061 }
3062 
3063 
3064 static BOOL isKanaLockAvailable()
3065 {
3066     // This method is to determine whether the Kana Lock feature is
3067     // available on the attached keyboard.  Kana Lock feature does not
3068     // necessarily require that the real KANA keytop is available on
3069     // keyboard, so using MapVirtualKey(VK_KANA) is not sufficient for testing.
3070     // Instead of that we regard it as Japanese keyboard (w/ Kana Lock) if :-
3071     //
3072     // - the keyboard layout is Japanese (VK_KANA has the same value as VK_HANGUL)
3073     // - the keyboard is Japanese keyboard (keyboard type == 7).
3074     return (LOWORD(GetKeyboardLayout(0)) == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
3075         && (GetKeyboardType(0) == 7);
3076 }
3077 
3078 void AwtComponent::JavaKeyToWindowsKey(UINT javaKey,
3079                                        UINT *windowsKey, UINT *modifiers, UINT originalWindowsKey)
3080 {
3081     // Handle the few cases where a Java VK code corresponds to a Windows
3082     // key/modifier combination or applies only to specific keyboard layouts
3083     switch (javaKey) {
3084         case java_awt_event_KeyEvent_VK_ALL_CANDIDATES:
3085             *windowsKey = VK_CONVERT;
3086             *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK;
3087             return;
3088         case java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE:
3089             *windowsKey = VK_CONVERT;
3090             *modifiers = java_awt_event_InputEvent_SHIFT_DOWN_MASK;
3091             return;
3092         case java_awt_event_KeyEvent_VK_CODE_INPUT:
3093             *windowsKey = VK_DBE_ALPHANUMERIC;
3094             *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK;
3095             return;
3096         case java_awt_event_KeyEvent_VK_KANA_LOCK:
3097             if (isKanaLockAvailable()) {
3098                 *windowsKey = VK_KANA;
3099                 *modifiers = java_awt_event_InputEvent_CTRL_DOWN_MASK;
3100                 return;
3101             }
3102     }
3103 
3104     // for the general case, use a bi-directional table
3105     for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
3106         if (keyMapTable[i].javaKey == javaKey) {
3107             *windowsKey = keyMapTable[i].windowsKey;
3108             *modifiers = 0;
3109             return;
3110         }
3111     }
3112 
3113     // Bug 4766655
3114     // Two Windows keys could map to the same Java key, so
3115     // give preference to the originalWindowsKey if it is
3116     // specified (not IGNORE_KEY).
3117     if (originalWindowsKey == IGNORE_KEY) {
3118         for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3119             if (dynamicKeyMapTable[j].javaKey == javaKey) {
3120                 *windowsKey = dynamicKeyMapTable[j].windowsKey;
3121                 *modifiers = 0;
3122                 return;
3123             }
3124         }
3125     } else {
3126         BOOL found = false;
3127         for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3128             if (dynamicKeyMapTable[j].javaKey == javaKey) {
3129                 *windowsKey = dynamicKeyMapTable[j].windowsKey;
3130                 *modifiers = 0;
3131                 found = true;
3132                 if (*windowsKey == originalWindowsKey) {
3133                     return;   /* if ideal case found return, else keep looking */
3134                 }
3135             }
3136         }
3137         if (found) {
3138             return;
3139         }
3140     }
3141 
3142     *windowsKey = 0;
3143     *modifiers = 0;
3144     return;
3145 }
3146 
3147 UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey)
3148 
3149 {
3150     // Handle the few cases where we need to take the modifier into
3151     // consideration for the Java VK code or where we have to take the keyboard
3152     // layout into consideration so that function keys can get
3153     // recognized in a platform-independent way.
3154     switch (windowsKey) {
3155         case VK_CONVERT:
3156             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3157                 return java_awt_event_KeyEvent_VK_ALL_CANDIDATES;
3158             }
3159             if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0) {
3160                 return java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE;
3161             }
3162             break;
3163         case VK_DBE_ALPHANUMERIC:
3164             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3165                 return java_awt_event_KeyEvent_VK_CODE_INPUT;
3166             }
3167             break;
3168         case VK_KANA:
3169             if (isKanaLockAvailable()) {
3170                 return java_awt_event_KeyEvent_VK_KANA_LOCK;
3171             }
3172             break;
3173     };
3174 
3175     // check dead key
3176     if (isDeadKey) {
3177       for (int i = 0; charToDeadVKTable[i].c != 0; i++) {
3178         if (charToDeadVKTable[i].c == character) {
3179             return charToDeadVKTable[i].javaKey;
3180         }
3181       }
3182     }
3183 
3184     // for the general case, use a bi-directional table
3185     for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
3186         if (keyMapTable[i].windowsKey == windowsKey) {
3187             return keyMapTable[i].javaKey;
3188         }
3189     }
3190 
3191     for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3192         if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
3193             if (dynamicKeyMapTable[j].javaKey != java_awt_event_KeyEvent_VK_UNDEFINED) {
3194                 return dynamicKeyMapTable[j].javaKey;
3195             }else{
3196                 break;
3197             }
3198         }
3199     }
3200 
3201     return java_awt_event_KeyEvent_VK_UNDEFINED;
3202 }
3203 
3204 BOOL AwtComponent::IsNavigationKey(UINT wkey) {
3205     switch (wkey) {
3206       case VK_END:
3207       case VK_PRIOR:  // PageUp
3208       case VK_NEXT:  // PageDown
3209       case VK_HOME:
3210       case VK_LEFT:
3211       case VK_UP:
3212       case VK_RIGHT:
3213       case VK_DOWN:
3214           return TRUE;
3215     }
3216     return FALSE;
3217 }
3218 
3219 // determine if a key is a numpad key (distinguishes the numpad
3220 // arrow keys from the non-numpad arrow keys, for example).
3221 BOOL AwtComponent::IsNumPadKey(UINT vkey, BOOL extended)
3222 {
3223     // Note: scancodes are the same for the numpad arrow keys and
3224     // the non-numpad arrow keys (also for PageUp, etc.).
3225     // The scancodes for the numpad divide and the non-numpad slash
3226     // are the same, but the wparams are different
3227 
3228     DTRACE_PRINTLN3("AwtComponent::IsNumPadKey  vkey = %d = 0x%x  extended = %d",
3229       vkey, vkey, extended);
3230 
3231     switch (vkey) {
3232       case VK_CLEAR:  // numpad 5 with numlock off
3233       case VK_NUMPAD0:
3234       case VK_NUMPAD1:
3235       case VK_NUMPAD2:
3236       case VK_NUMPAD3:
3237       case VK_NUMPAD4:
3238       case VK_NUMPAD5:
3239       case VK_NUMPAD6:
3240       case VK_NUMPAD7:
3241       case VK_NUMPAD8:
3242       case VK_NUMPAD9:
3243       case VK_MULTIPLY:
3244       case VK_ADD:
3245       case VK_SEPARATOR:  // numpad ,  not on US kbds
3246       case VK_SUBTRACT:
3247       case VK_DECIMAL:
3248       case VK_DIVIDE:
3249       case VK_NUMLOCK:
3250         return TRUE;
3251         break;
3252       case VK_END:
3253       case VK_PRIOR:  // PageUp
3254       case VK_NEXT:  // PageDown
3255       case VK_HOME:
3256       case VK_LEFT:
3257       case VK_UP:
3258       case VK_RIGHT:
3259       case VK_DOWN:
3260       case VK_INSERT:
3261       case VK_DELETE:
3262         // extended if non-numpad
3263         return (!extended);
3264         break;
3265       case VK_RETURN:  // extended if on numpad
3266         return (extended);
3267         break;
3268       default:
3269         break;
3270     }
3271 
3272     return FALSE;
3273 }
3274 static void
3275 resetKbdState( BYTE kstate[256]) {
3276     BYTE tmpState[256];
3277     WCHAR wc[2];
3278     memmove(tmpState, kstate, sizeof(kstate));
3279     tmpState[VK_SHIFT] = 0;
3280     tmpState[VK_CONTROL] = 0;
3281     tmpState[VK_MENU] = 0;
3282 
3283     ::ToUnicodeEx(VK_SPACE,::MapVirtualKey(VK_SPACE, 0), tmpState, wc, 2, 0,  GetKeyboardLayout(0));
3284 }
3285 
3286 // XXX in the update releases this is an addition to the unchanged existing code
3287 // After the call, a table will have a unicode associated with a windows virtual keycode
3288 // sans modifiers. With some further simplification, one can
3289 // derive java keycode from it, and anyway we will pass this unicode value
3290 // all the way up in a comment to a KeyEvent.
3291 void
3292 AwtComponent::BuildPrimaryDynamicTable() {
3293     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3294     // XXX: how about that?
3295     //CriticalSection::Lock l(GetLock());
3296     //if (GetPeer(env) == NULL) {
3297     //    /* event received during termination. */
3298     //    return;
3299     //}
3300 
3301     HKL hkl = GetKeyboardLayout();
3302     UINT sc = 0;
3303     BYTE kbdState[AwtToolkit::KB_STATE_SIZE];
3304     memset(kbdState, 0, sizeof (kbdState));
3305 
3306     // Use JNI call to obtain java key code. We should keep a list
3307     // of currently available keycodes in a single place.
3308     static jclass extKeyCodesCls;
3309     if( extKeyCodesCls == NULL) {
3310         jclass extKeyCodesClsLocal = env->FindClass("sun/awt/ExtendedKeyCodes");
3311         DASSERT(extKeyCodesClsLocal);
3312         if (extKeyCodesClsLocal == NULL) {
3313             /* exception already thrown */
3314             return;
3315         }
3316         extKeyCodesCls = (jclass)env->NewGlobalRef(extKeyCodesClsLocal);
3317         env->DeleteLocalRef(extKeyCodesClsLocal);
3318     }
3319     static jmethodID getExtendedKeyCodeForChar;
3320     if (getExtendedKeyCodeForChar == NULL) {
3321         getExtendedKeyCodeForChar =
3322                   env->GetStaticMethodID(extKeyCodesCls, "getExtendedKeyCodeForChar", "(I)I");
3323         DASSERT(getExtendedKeyCodeForChar);
3324     }
3325     jint extJKC; //extended Java key code
3326 
3327     for (UINT i = 0; i < 256; i++) {
3328         dynPrimaryKeymap[i].wkey = i;
3329         dynPrimaryKeymap[i].jkey = java_awt_event_KeyEvent_VK_UNDEFINED;
3330         dynPrimaryKeymap[i].unicode = 0;
3331 
3332         if ((sc = MapVirtualKey (i, 0)) == 0) {
3333             dynPrimaryKeymap[i].scancode = 0;
3334             continue;
3335         }
3336         dynPrimaryKeymap[i].scancode = sc;
3337 
3338         // XXX process cases like VK_SHIFT etc.
3339         kbdState[i] = 0x80; // "key pressed".
3340         WCHAR wc[16];
3341         int k = ::ToUnicodeEx(i, sc, kbdState, wc, 16, 0, hkl);
3342         if (k == 1) {
3343             // unicode
3344             dynPrimaryKeymap[i].unicode = wc[0];
3345             if (dynPrimaryKeymap[i].jkey == java_awt_event_KeyEvent_VK_UNDEFINED) {
3346             // Convert unicode to java keycode.
3347                 //dynPrimaryKeymap[i].jkey = ((UINT)(wc[0]) + 0x01000000);
3348                 //
3349                 //XXX If this key in on the keypad, we should force a special value equal to
3350                 //XXX an old java keycode: but how to say if it is a keypad key?
3351                 //XXX We'll do it in WmKeyUp/Down.
3352                 extJKC = env->CallStaticIntMethod(extKeyCodesCls,
3353                                                   getExtendedKeyCodeForChar, (jint)(wc[0]));
3354                 dynPrimaryKeymap[i].jkey = extJKC;
3355             }
3356         }else if (k == -1) {
3357             // dead key: use charToDeadVKTable
3358             dynPrimaryKeymap[i].unicode = wc[0];
3359             resetKbdState( kbdState );
3360             for (const CharToVKEntry *map = charToDeadVKTable;  map->c != 0;  ++map) {
3361                 if (wc[0] == map->c) {
3362                     dynPrimaryKeymap[i].jkey = map->javaKey;
3363                     break;
3364                 }
3365             }
3366         } else if (k == 0) {
3367             // reset
3368             resetKbdState( kbdState );
3369         }else {
3370             // k > 1: this key does generate multiple characters. Ignore it.
3371             // An example: Arabic Lam and Alef ligature.
3372             // There will be no extended keycode and thus shortcuts for this  key.
3373             // XXX shouldn't we reset the kbd state?
3374 #ifdef DEBUG
3375             DTRACE_PRINTLN2("wkey 0x%02X (%d)", i,i);
3376 #endif
3377         }
3378         kbdState[i] = 0; // "key unpressed"
3379     }
3380 }
3381 void
3382 AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers)
3383 {
3384     if( wkey && wkey < 256 ) {
3385         if(keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD) {
3386             // At the creation time,
3387             // dynPrimaryKeymap cannot distinguish between e.g. "/" and "NumPad /"
3388             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3389         }
3390         if(dynPrimaryKeymap[wkey].jkey ==  java_awt_event_KeyEvent_VK_UNDEFINED) {
3391             // E.g. it is non-unicode key
3392             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3393         }
3394     }
3395 }
3396 
3397 UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, BOOL &isDeadKey)
3398 {
3399     static Hashtable transTable("VKEY translations");
3400     static Hashtable deadKeyFlagTable("Dead Key Flags");
3401     isDeadKey = FALSE;
3402 
3403     // Try to translate using last saved translation
3404     if (ops == LOAD) {
3405        void* deadKeyFlag = deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3406        void* value = transTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3407        if (value != NULL) {
3408            isDeadKey = static_cast<BOOL>(reinterpret_cast<INT_PTR>(deadKeyFlag));
3409            return static_cast<UINT>(reinterpret_cast<INT_PTR>(value));
3410        }
3411     }
3412 
3413     // If the windows key is a return, wkey will equal 13 ('\r')
3414     // In this case, we want to return 10 ('\n')
3415     // Since ToAscii would convert VK_RETURN to '\r', we need
3416     // to have a special case here.
3417     if (wkey == VK_RETURN)
3418         return '\n';
3419 
3420     // high order bit in keyboardState indicates whether the key is down
3421     static const BYTE KEY_STATE_DOWN = 0x80;
3422     BYTE    keyboardState[AwtToolkit::KB_STATE_SIZE];
3423     AwtToolkit::GetKeyboardState(keyboardState);
3424 
3425     // apply modifiers to keyboard state if necessary
3426     if (modifiers) {
3427         BOOL shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK;
3428         BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK;
3429         BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK;
3430 
3431         // Windows treats AltGr as Ctrl+Alt
3432         if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
3433             altIsDown = TRUE;
3434             ctrlIsDown = TRUE;
3435         }
3436 
3437         if (shiftIsDown) {
3438             keyboardState[VK_SHIFT] |= KEY_STATE_DOWN;
3439         }
3440 
3441         // fix for 4623376,4737679,4501485,4740906,4708221 (4173679/4122715)
3442         // Here we try to resolve a conflict with ::ToAsciiEx's translating
3443         // ALT+number key combinations. kdm@sarc.spb.su
3444         // yan: Do it for navigation keys only, otherwise some AltGr deadkeys fail.
3445         if( IsNavigationKey(wkey) ) {
3446             keyboardState[VK_MENU] &= ~KEY_STATE_DOWN;
3447         }
3448 
3449         if (ctrlIsDown)
3450         {
3451             if (altIsDown) {
3452                 // bugid 4215009: don't mess with AltGr == Ctrl + Alt
3453                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3454             }
3455             else {
3456                 // bugid 4098210: old event model doesn't have KEY_TYPED
3457                 // events, so try to provide a meaningful character for
3458                 // Ctrl+<key>.  Take Ctrl into account only when we know
3459                 // that Ctrl+<key> will be an ASCII control.  Ignore by
3460                 // default.
3461                 keyboardState[VK_CONTROL] &= ~KEY_STATE_DOWN;
3462 
3463                 // Letters have Ctrl+<letter> counterparts.  According to
3464                 // <winuser.h> VK_A through VK_Z are the same as ASCII
3465                 // 'A' through 'Z'.
3466                 if (wkey >= 'A' && wkey <= 'Z') {
3467                     keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3468                 }
3469                 else {
3470                     // Non-letter controls 033 to 037 are:
3471                     // ^[ (ESC), ^\ (FS), ^] (GS), ^^ (RS), and ^_ (US)
3472 
3473                     // Shift state bits returned by ::VkKeyScan in HIBYTE
3474                     static const UINT _VKS_SHIFT_MASK = 0x01;
3475                     static const UINT _VKS_CTRL_MASK = 0x02;
3476                     static const UINT _VKS_ALT_MASK = 0x04;
3477 
3478                     // Check to see whether there is a meaningful translation
3479                     TCHAR ch;
3480                     short vk;
3481                     for (ch = _T('\033'); ch < _T('\040'); ch++) {
3482                         vk = ::VkKeyScan(ch);
3483                         if (wkey == LOBYTE(vk)) {
3484                             UINT shiftState = HIBYTE(vk);
3485                             if ((shiftState & _VKS_CTRL_MASK) ||
3486                                 (!(shiftState & _VKS_SHIFT_MASK)
3487                                 == !shiftIsDown))
3488                             {
3489                                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3490                             }
3491                             break;
3492                         }
3493                     }
3494                 }
3495             } // ctrlIsDown && altIsDown
3496         } // ctrlIsDown
3497     } // modifiers
3498 
3499     // instead of creating our own conversion tables, I'll let Win32
3500     // convert the character for me.
3501     WORD wChar[2];
3502     UINT scancode = ::MapVirtualKey(wkey, 0);
3503     int converted = ::ToUnicodeEx(wkey, scancode, keyboardState,
3504                                   wChar, 2, 0, GetKeyboardLayout());
3505 
3506     UINT translation;
3507     BOOL deadKeyFlag = (converted == 2);
3508 
3509     // Dead Key
3510     if (converted < 0) {
3511         translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3512     } else
3513     // No translation available -- try known conversions or else punt.
3514     if (converted == 0) {
3515         if (wkey == VK_DELETE) {
3516             translation = '\177';
3517         } else
3518         if (wkey >= VK_NUMPAD0 && wkey <= VK_NUMPAD9) {
3519             translation = '0' + wkey - VK_NUMPAD0;
3520         } else {
3521             translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3522         }
3523     } else
3524     // the caller expects a Unicode character.
3525     if (converted > 0) {
3526         translation = wChar[0];
3527     }
3528     if (ops == SAVE) {
3529         transTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3530                        reinterpret_cast<void*>(static_cast<INT_PTR>(translation)));
3531         if (deadKeyFlag) {
3532             deadKeyFlagTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3533                          reinterpret_cast<void*>(static_cast<INT_PTR>(deadKeyFlag)));
3534         } else {
3535             deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3536         }
3537     }
3538 
3539     isDeadKey = deadKeyFlag;
3540     return translation;
3541 }
3542 
3543 MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt,
3544                                    UINT flags, BOOL system)
3545 {
3546     // VK_PROCESSKEY is a special value which means
3547     //          "Current IME wants to consume this KeyEvent"
3548     // Real key code is saved by IMM32.DLL and can be retrieved by
3549     // calling ImmGetVirtualKey();
3550     if (wkey == VK_PROCESSKEY) {
3551         return mrDoDefault;
3552     }
3553     MSG msg;
3554     InitMessage(&msg, (system ? WM_SYSKEYDOWN : WM_KEYDOWN),
3555                              wkey, MAKELPARAM(repCnt, flags));
3556 
3557     UINT modifiers = GetJavaModifiers();
3558     jint keyLocation = GetKeyLocation(wkey, flags);
3559     BOOL isDeadKey = FALSE;
3560     UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE, isDeadKey);
3561     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3562     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3563 
3564 
3565     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
3566                              TimeHelper::windowsToUTC(msg.time), jkey, character,
3567                              modifiers, keyLocation, (jlong)wkey, &msg);
3568 
3569     // bugid 4724007: Windows does not create a WM_CHAR for the Del key
3570     // for some reason, so we need to create the KEY_TYPED event on the
3571     // WM_KEYDOWN.  Use null msg so the character doesn't get sent back
3572     // to the native window for processing (this event is synthesized
3573     // for Java - we don't want Windows trying to process it).
3574     if (jkey == java_awt_event_KeyEvent_VK_DELETE) {
3575         SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3576                                  TimeHelper::windowsToUTC(msg.time),
3577                                  java_awt_event_KeyEvent_VK_UNDEFINED,
3578                                  character, modifiers,
3579                                  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
3580     }
3581 
3582     return mrConsume;
3583 }
3584 
3585 MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt,
3586                                  UINT flags, BOOL system)
3587 {
3588 
3589     // VK_PROCESSKEY is a special value which means
3590     //          "Current IME wants to consume this KeyEvent"
3591     // Real key code is saved by IMM32.DLL and can be retrieved by
3592     // calling ImmGetVirtualKey();
3593     if (wkey == VK_PROCESSKEY) {
3594         return mrDoDefault;
3595     }
3596     MSG msg;
3597     InitMessage(&msg, (system ? WM_SYSKEYUP : WM_KEYUP),
3598                              wkey, MAKELPARAM(repCnt, flags));
3599 
3600     UINT modifiers = GetJavaModifiers();
3601     jint keyLocation = GetKeyLocation(wkey, flags);
3602     BOOL isDeadKey = FALSE;
3603     UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD, isDeadKey);
3604     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3605     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3606 
3607     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
3608                              TimeHelper::windowsToUTC(msg.time), jkey, character,
3609                              modifiers, keyLocation, (jlong)wkey, &msg);
3610     return mrConsume;
3611 }
3612 
3613 MsgRouting AwtComponent::WmInputLangChange(UINT charset, HKL hKeyboardLayout)
3614 {
3615     // Normally we would be able to use charset and TranslateCharSetInfo
3616     // to get a code page that should be associated with this keyboard
3617     // layout change. However, there seems to be an NT 4.0 bug associated
3618     // with the WM_INPUTLANGCHANGE message, which makes the charset parameter
3619     // unreliable, especially on Asian systems. Our workaround uses the
3620     // keyboard layout handle instead.
3621     m_hkl = hKeyboardLayout;
3622     m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID
3623     m_CodePage = LangToCodePage(m_idLang);
3624     BuildDynamicKeyMapTable();  // compute new mappings for VK_OEM
3625     BuildPrimaryDynamicTable();
3626     return mrConsume;           // do not propagate to children
3627 }
3628 
3629 // Convert Language ID to CodePage
3630 UINT AwtComponent::LangToCodePage(LANGID idLang)
3631 {
3632     TCHAR strCodePage[MAX_ACP_STR_LEN];
3633     // use the LANGID to create a LCID
3634     LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
3635     // get the ANSI code page associated with this locale
3636     if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE, strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
3637         return _ttoi(strCodePage);
3638     else
3639         return GetACP();
3640 }
3641 
3642 
3643 MsgRouting AwtComponent::WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL system)
3644 {
3645     // We will simply create Java events here.
3646     WCHAR unicodeChar = character;
3647     MSG msg;
3648     InitMessage(&msg, WM_IME_CHAR, character,
3649                               MAKELPARAM(repCnt, flags));
3650 
3651     jint modifiers = GetJavaModifiers();
3652     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3653                              TimeHelper::windowsToUTC(msg.time),
3654                              java_awt_event_KeyEvent_VK_UNDEFINED,
3655                              unicodeChar, modifiers,
3656                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
3657                              &msg);
3658     return mrConsume;
3659 }
3660 
3661 MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags,
3662                                 BOOL system)
3663 {
3664     // Will only get WmChar messages with DBCS if we create them for
3665     // an Edit class in the WmForwardChar method. These synthesized
3666     // DBCS chars are ok to pass on directly to the default window
3667     // procedure. They've already been filtered through the Java key
3668     // event queue. We will never get the trail byte since the edit
3669     // class will PeekMessage(&msg, hwnd, WM_CHAR, WM_CHAR,
3670     // PM_REMOVE).  I would like to be able to pass this character off
3671     // via WM_AWT_FORWARD_BYTE, but the Edit classes don't seem to
3672     // like that.
3673 
3674     // We will simply create Java events here.
3675     UINT message = system ? WM_SYSCHAR : WM_CHAR;
3676 
3677     // The Alt modifier is reported in the 29th bit of the lParam,
3678     // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
3679     bool alt_is_down = (flags & (1<<13)) != 0;
3680 
3681     // Fix for bug 4141621, corrected by fix for bug 6223726: Alt+space doesn't invoke system menu
3682     // We should not pass this particular combination to Java.
3683 
3684     if (system && alt_is_down) {
3685         if (character == VK_SPACE) {
3686             return mrDoDefault;
3687         }
3688     }
3689 
3690     // If this is a WM_CHAR (non-system) message, then the Alt flag
3691     // indicates that the character was typed using an AltGr key
3692     // (which Windows treats as Ctrl+Alt), so in this case we do NOT
3693     // pass the Ctrl and Alt modifiers to Java, but instead we
3694     // replace them with Java's AltGraph modifier.  Note: the AltGraph
3695     // modifier does not exist in 1.1.x releases.
3696     jint modifiers = GetJavaModifiers();
3697     if (!system && alt_is_down) {
3698         // character typed with AltGraph
3699         modifiers &= ~(java_awt_event_InputEvent_ALT_DOWN_MASK
3700                        | java_awt_event_InputEvent_CTRL_DOWN_MASK);
3701         modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK;
3702     }
3703 
3704     WCHAR unicodeChar = character;
3705 
3706     // Kludge: Combine pending single byte with this char for some Chinese IMEs
3707     if (m_PendingLeadByte != 0) {
3708         character = (m_PendingLeadByte & 0x00ff) | (character << 8);
3709         m_PendingLeadByte = 0;
3710         ::MultiByteToWideChar(GetCodePage(), 0, (CHAR*)&character, 2,
3711                           &unicodeChar, 1);
3712     }
3713 
3714     if (unicodeChar == VK_RETURN) {
3715         // Enter key generates \r in windows, but \n is required in java
3716         unicodeChar = java_awt_event_KeyEvent_VK_ENTER;
3717     }
3718     MSG msg;
3719     InitMessage(&msg, message, character,
3720                               MAKELPARAM(repCnt, flags));
3721     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3722                              TimeHelper::windowsToUTC(msg.time),
3723                              java_awt_event_KeyEvent_VK_UNDEFINED,
3724                              unicodeChar, modifiers,
3725                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
3726                              &msg);
3727     return mrConsume;
3728 }
3729 
3730 MsgRouting AwtComponent::WmForwardChar(WCHAR character, LPARAM lParam,
3731                                        BOOL synthetic)
3732 {
3733     // just post WM_CHAR with unicode key value
3734     DefWindowProc(WM_CHAR, (WPARAM)character, lParam);
3735     return mrConsume;
3736 }
3737 
3738 MsgRouting AwtComponent::WmPaste()
3739 {
3740     return mrDoDefault;
3741 }
3742 
3743 // support IME Composition messages
3744 void AwtComponent::SetCompositionWindow(RECT& r)
3745 {
3746     HWND hwnd = ImmGetHWnd();
3747     HIMC hIMC = ImmGetContext(hwnd);
3748     if (hIMC == NULL) {
3749         return;
3750     }
3751     COMPOSITIONFORM cf = {CFS_DEFAULT, {0, 0}, {0, 0, 0, 0}};
3752     ImmSetCompositionWindow(hIMC, &cf);
3753     ImmReleaseContext(hwnd, hIMC);
3754 }
3755 
3756 void AwtComponent::OpenCandidateWindow(int x, int y)
3757 {
3758     UINT bits = 1;
3759     RECT rc;
3760     GetWindowRect(GetHWnd(), &rc);
3761 
3762     for (int iCandType=0; iCandType<32; iCandType++, bits<<=1) {
3763         if ( m_bitsCandType & bits )
3764             SetCandidateWindow(iCandType, x-rc.left, y-rc.top);
3765     }
3766     if (m_bitsCandType != 0) {
3767         // REMIND: is there any chance GetProxyFocusOwner() returns NULL here?
3768         ::DefWindowProc(ImmGetHWnd(),
3769                         WM_IME_NOTIFY, IMN_OPENCANDIDATE, m_bitsCandType);
3770     }
3771 }
3772 
3773 void AwtComponent::SetCandidateWindow(int iCandType, int x, int y)
3774 {
3775     HWND hwnd = ImmGetHWnd();
3776     HIMC hIMC = ImmGetContext(hwnd);
3777     CANDIDATEFORM cf;
3778     cf.dwIndex = iCandType;
3779     cf.dwStyle = CFS_CANDIDATEPOS;
3780     cf.ptCurrentPos.x = x;
3781     cf.ptCurrentPos.y = y;
3782 
3783     ImmSetCandidateWindow(hIMC, &cf);
3784     ImmReleaseContext(hwnd, hIMC);
3785 }
3786 
3787 MsgRouting AwtComponent::WmImeSetContext(BOOL fSet, LPARAM *lplParam)
3788 {
3789     // If the Windows input context is disabled, do not let Windows
3790     // display any UIs.
3791     HWND hwnd = ImmGetHWnd();
3792     HIMC hIMC = ImmGetContext(hwnd);
3793     if (hIMC == NULL) {
3794         *lplParam = 0;
3795         return mrDoDefault;
3796     }
3797     ImmReleaseContext(hwnd, hIMC);
3798 
3799     if (fSet) {
3800         LPARAM lParam = *lplParam;
3801         if (!m_useNativeCompWindow) {
3802             // stop to draw native composing window.
3803             *lplParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
3804         }
3805     }
3806     return mrDoDefault;
3807 }
3808 
3809 MsgRouting AwtComponent::WmImeNotify(WPARAM subMsg, LPARAM bitsCandType)
3810 {
3811     if (!m_useNativeCompWindow && subMsg == IMN_OPENCANDIDATE) {
3812         m_bitsCandType = bitsCandType;
3813         InquireCandidatePosition();
3814         return mrConsume;
3815     }
3816     return mrDoDefault;
3817 }
3818 
3819 MsgRouting AwtComponent::WmImeStartComposition()
3820 {
3821     if (m_useNativeCompWindow) {
3822         RECT rc;
3823         ::GetClientRect(GetHWnd(), &rc);
3824         SetCompositionWindow(rc);
3825         return mrDoDefault;
3826     } else
3827         return mrConsume;
3828 }
3829 
3830 MsgRouting AwtComponent::WmImeEndComposition()
3831 {
3832     if (m_useNativeCompWindow)   return mrDoDefault;
3833 
3834     SendInputMethodEvent(
3835         java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3836         NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0 );
3837     return mrConsume;
3838 }
3839 
3840 MsgRouting AwtComponent::WmImeComposition(WORD wChar, LPARAM flags)
3841 {
3842     if (m_useNativeCompWindow)   return mrDoDefault;
3843 
3844     int*      bndClauseW = NULL;
3845     jstring*  readingClauseW = NULL;
3846     int*      bndAttrW = NULL;
3847     BYTE*     valAttrW = NULL;
3848     int       cClauseW = 0;
3849     AwtInputTextInfor* textInfor = NULL;
3850 
3851     try {
3852         HWND hwnd = ImmGetHWnd();
3853         HIMC hIMC = ImmGetContext(hwnd);
3854         DASSERT(hIMC!=0);
3855 
3856         textInfor = new AwtInputTextInfor;
3857         textInfor->GetContextData(hIMC, flags);
3858         ImmReleaseContext(hwnd, hIMC);
3859 
3860         jstring jtextString = textInfor->GetText();
3861         /* The conditions to send the input method event to AWT EDT are:
3862            1. Whenever there is a composition message sent regarding whether
3863            the composition text is NULL or not. See details at bug 6222692.
3864            2. When there is a committed message sent, in which case, we have to
3865            check whether the committed string is NULL or not. If the committed string
3866            is NULL, there is no need to send any input method event.
3867            (Minor note: 'jtextString' returned is the merged string in the case of
3868            partial commit.)
3869         */
3870         if ((flags & GCS_RESULTSTR && jtextString != NULL) ||
3871             (flags & GCS_COMPSTR)) {
3872             int       cursorPosW = textInfor->GetCursorPosition();
3873             // In order not to delete the readingClauseW in the catch clause,
3874             // calling GetAttributeInfor before GetClauseInfor.
3875             int       cAttrW = textInfor->GetAttributeInfor(bndAttrW, valAttrW);
3876             cClauseW = textInfor->GetClauseInfor(bndClauseW, readingClauseW);
3877 
3878             /* Send INPUT_METHOD_TEXT_CHANGED event to the WInputMethod which in turn sends
3879                the event to AWT EDT.
3880 
3881                The last two paremeters are set to equal since we don't have recommendations for
3882                the visible position within the current composed text. See details at
3883                java.awt.event.InputMethodEvent.
3884             */
3885             SendInputMethodEvent(java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3886                                  jtextString,
3887                                  cClauseW, bndClauseW, readingClauseW,
3888                                  cAttrW, bndAttrW, valAttrW,
3889                                  textInfor->GetCommittedTextLength(),
3890                                  cursorPosW, cursorPosW);
3891         }
3892     } catch (...) {
3893         // since GetClauseInfor and GetAttributeInfor could throw exception, we have to release
3894         // the pointer here.
3895         delete [] bndClauseW;
3896         delete [] readingClauseW;
3897         delete [] bndAttrW;
3898         delete [] valAttrW;
3899         throw;
3900     }
3901 
3902     /* Free the storage allocated. Since jtextString won't be passed from threads
3903      *  to threads, we just use the local ref and it will be deleted within the destructor
3904      *  of AwtInputTextInfor object.
3905      */
3906     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3907     if (cClauseW && readingClauseW) {
3908         for (int i = 0; i < cClauseW; i ++) {
3909             if (readingClauseW[i]) {
3910                 env->DeleteLocalRef(readingClauseW[i]);
3911             }
3912         }
3913     }
3914     delete [] bndClauseW;
3915     delete [] readingClauseW;
3916     delete [] bndAttrW;
3917     delete [] valAttrW;
3918     delete textInfor;
3919 
3920     return mrConsume;
3921 }
3922 
3923 //
3924 // generate and post InputMethodEvent
3925 //
3926 void AwtComponent::SendInputMethodEvent(jint id, jstring text,
3927                                         int cClause, int* rgClauseBoundary, jstring* rgClauseReading,
3928                                         int cAttrBlock, int* rgAttrBoundary, BYTE *rgAttrValue,
3929                                         int commitedTextLength, int caretPos, int visiblePos)
3930 {
3931     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3932 
3933     // assumption for array type casting
3934     DASSERT(sizeof(int)==sizeof(jint));
3935     DASSERT(sizeof(BYTE)==sizeof(jbyte));
3936 
3937     // caluse information
3938     jintArray clauseBoundary = NULL;
3939     jobjectArray clauseReading = NULL;
3940     if (cClause && rgClauseBoundary && rgClauseReading) {
3941         // convert clause boundary offset array to java array
3942         clauseBoundary = env->NewIntArray(cClause+1);
3943         env->SetIntArrayRegion(clauseBoundary, 0, cClause+1, (jint *)rgClauseBoundary);
3944         DASSERT(!safe_ExceptionOccurred(env));
3945 
3946         // convert clause reading string array to java array
3947         clauseReading = env->NewObjectArray(cClause, JNU_ClassString(env), NULL);
3948         for (int i=0; i<cClause; i++)   env->SetObjectArrayElement(clauseReading, i, rgClauseReading[i]);
3949         DASSERT(!safe_ExceptionOccurred(env));
3950     }
3951 
3952 
3953     // attrubute value definition in WInputMethod.java must be equal to that in IMM.H
3954     DASSERT(ATTR_INPUT==sun_awt_windows_WInputMethod_ATTR_INPUT);
3955     DASSERT(ATTR_TARGET_CONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_CONVERTED);
3956     DASSERT(ATTR_CONVERTED==sun_awt_windows_WInputMethod_ATTR_CONVERTED);
3957     DASSERT(ATTR_TARGET_NOTCONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_NOTCONVERTED);
3958     DASSERT(ATTR_INPUT_ERROR==sun_awt_windows_WInputMethod_ATTR_INPUT_ERROR);
3959 
3960     // attribute information
3961     jintArray attrBoundary = NULL;
3962     jbyteArray attrValue = NULL;
3963     if (cAttrBlock && rgAttrBoundary && rgAttrValue) {
3964         // convert attribute boundary offset array to java array
3965         attrBoundary = env->NewIntArray(cAttrBlock+1);
3966         env->SetIntArrayRegion(attrBoundary, 0, cAttrBlock+1, (jint *)rgAttrBoundary);
3967         DASSERT(!safe_ExceptionOccurred(env));
3968 
3969         // convert attribute value byte array to java array
3970         attrValue = env->NewByteArray(cAttrBlock);
3971         env->SetByteArrayRegion(attrValue, 0, cAttrBlock, (jbyte *)rgAttrValue);
3972         DASSERT(!safe_ExceptionOccurred(env));
3973     }
3974 
3975 
3976     // get global reference of WInputMethod class (run only once)
3977     static jclass wInputMethodCls = NULL;
3978     if (wInputMethodCls == NULL) {
3979         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
3980         DASSERT(wInputMethodClsLocal);
3981         if (wInputMethodClsLocal == NULL) {
3982             /* exception already thrown */
3983             return;
3984         }
3985         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
3986         env->DeleteLocalRef(wInputMethodClsLocal);
3987     }
3988 
3989     // get method ID of sendInputMethodEvent() (run only once)
3990     static jmethodID sendIMEventMid = 0;
3991     if (sendIMEventMid == 0) {
3992         sendIMEventMid =  env->GetMethodID(wInputMethodCls, "sendInputMethodEvent",
3993                                            "(IJLjava/lang/String;[I[Ljava/lang/String;[I[BIII)V");
3994         DASSERT(sendIMEventMid);
3995     }
3996 
3997     // call m_InputMethod.sendInputMethod()
3998     env->CallVoidMethod(m_InputMethod, sendIMEventMid, id, TimeHelper::getMessageTimeUTC(),
3999                         text, clauseBoundary, clauseReading, attrBoundary,
4000                         attrValue, commitedTextLength, caretPos, visiblePos);
4001     if (safe_ExceptionOccurred(env))   env->ExceptionDescribe();
4002     DASSERT(!safe_ExceptionOccurred(env));
4003 
4004 }
4005 
4006 
4007 
4008 //
4009 // Inquires candidate position according to the composed text
4010 //
4011 void AwtComponent::InquireCandidatePosition()
4012 {
4013     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4014 
4015     // get global reference of WInputMethod class (run only once)
4016     static jclass wInputMethodCls = NULL;
4017     if (wInputMethodCls == NULL) {
4018         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
4019         DASSERT(wInputMethodClsLocal);
4020         if (wInputMethodClsLocal == NULL) {
4021             /* exception already thrown */
4022             return;
4023         }
4024         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
4025         env->DeleteLocalRef(wInputMethodClsLocal);
4026     }
4027 
4028     // get method ID of sendInputMethodEvent() (run only once)
4029     static jmethodID inqCandPosMid = 0;
4030     if (inqCandPosMid == 0) {
4031         inqCandPosMid =  env->GetMethodID(wInputMethodCls, "inquireCandidatePosition",
4032                                            "()V");
4033         DASSERT(!safe_ExceptionOccurred(env));
4034         DASSERT(inqCandPosMid);
4035     }
4036 
4037     // call m_InputMethod.sendInputMethod()
4038     jobject candPos = env->CallObjectMethod(m_InputMethod, inqCandPosMid);
4039     DASSERT(!safe_ExceptionOccurred(env));
4040 }
4041 
4042 HWND AwtComponent::ImmGetHWnd()
4043 {
4044     HWND proxy = GetProxyFocusOwner();
4045     return (proxy != NULL) ? proxy : GetHWnd();
4046 }
4047 
4048 HIMC AwtComponent::ImmAssociateContext(HIMC himc)
4049 {
4050     return ::ImmAssociateContext(ImmGetHWnd(), himc);
4051 }
4052 
4053 HWND AwtComponent::GetProxyFocusOwner()
4054 {
4055     AwtWindow *window = GetContainer();
4056     if (window != 0) {
4057         AwtFrame *owner = window->GetOwningFrameOrDialog();
4058         if (owner != 0) {
4059             return owner->GetProxyFocusOwner();
4060         } else if (!window->IsSimpleWindow()) { // isn't an owned simple window
4061             return ((AwtFrame*)window)->GetProxyFocusOwner();
4062         }
4063     }
4064     return (HWND)NULL;
4065 }
4066 
4067 /* Call DefWindowProc for the focus proxy, if any */
4068 void AwtComponent::CallProxyDefWindowProc(UINT message, WPARAM wParam,
4069     LPARAM lParam, LRESULT &retVal, MsgRouting &mr)
4070 {
4071     if (mr != mrConsume)  {
4072         HWND proxy = GetProxyFocusOwner();
4073         if (proxy != NULL) {
4074             retVal = ComCtl32Util::GetInstance().DefWindowProc(NULL, proxy, message, wParam, lParam);
4075             mr = mrConsume;
4076         }
4077     }
4078 }
4079 
4080 MsgRouting AwtComponent::WmCommand(UINT id, HWND hWndChild, UINT notifyCode)
4081 {
4082     /* Menu/Accelerator */
4083     if (hWndChild == 0) {
4084         AwtObject* obj = AwtToolkit::GetInstance().LookupCmdID(id);
4085         if (obj == NULL) {
4086             return mrConsume;
4087         }
4088         DASSERT(((AwtMenuItem*)obj)->GetID() == id);
4089         obj->DoCommand();
4090         return mrConsume;
4091     }
4092     /* Child id notification */
4093     else {
4094         AwtComponent* child = AwtComponent::GetComponent(hWndChild);
4095         if (child) {
4096             child->WmNotify(notifyCode);
4097         }
4098     }
4099     return mrDoDefault;
4100 }
4101 
4102 MsgRouting AwtComponent::WmNotify(UINT notifyCode)
4103 {
4104     return mrDoDefault;
4105 }
4106 
4107 MsgRouting AwtComponent::WmCompareItem(UINT ctrlId,
4108                                        COMPAREITEMSTRUCT &compareInfo,
4109                                        LRESULT &result)
4110 {
4111     AwtComponent* child = AwtComponent::GetComponent(compareInfo.hwndItem);
4112     if (child == this) {
4113         /* DoCallback("handleItemDelete", */
4114     }
4115     else if (child) {
4116         return child->WmCompareItem(ctrlId, compareInfo, result);
4117     }
4118     return mrConsume;
4119 }
4120 
4121 MsgRouting AwtComponent::WmDeleteItem(UINT ctrlId,
4122                                       DELETEITEMSTRUCT &deleteInfo)
4123 {
4124     /*
4125      * Workaround for NT 4.0 bug -- if SetWindowPos is called on a AwtList
4126      * window, a WM_DELETEITEM message is sent to its parent with a window
4127      * handle of one of the list's child windows.  The property lookup
4128      * succeeds, but the HWNDs don't match.
4129      */
4130     if (deleteInfo.hwndItem == NULL) {
4131         return mrConsume;
4132     }
4133     AwtComponent* child = (AwtComponent *)AwtComponent::GetComponent(deleteInfo.hwndItem);
4134 
4135     if (child && child->GetHWnd() != deleteInfo.hwndItem) {
4136         return mrConsume;
4137     }
4138 
4139     if (child == this) {
4140         /*DoCallback("handleItemDelete", */
4141     }
4142     else if (child) {
4143         return child->WmDeleteItem(ctrlId, deleteInfo);
4144     }
4145     return mrConsume;
4146 }
4147 
4148 MsgRouting AwtComponent::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT &drawInfo)
4149 {
4150     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4151 
4152     if (drawInfo.CtlType == ODT_MENU) {
4153         if (drawInfo.itemData != 0) {
4154             AwtMenu* menu = (AwtMenu*)(drawInfo.itemData);
4155             menu->DrawItem(drawInfo);
4156         }
4157     } else {
4158         return OwnerDrawItem(ctrlId, drawInfo);
4159     }
4160     return mrConsume;
4161 }
4162 
4163 MsgRouting AwtComponent::WmMeasureItem(UINT ctrlId,
4164                                        MEASUREITEMSTRUCT &measureInfo)
4165 {
4166     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4167 
4168     if (measureInfo.CtlType == ODT_MENU) {
4169         if (measureInfo.itemData != 0) {
4170             AwtMenu* menu = (AwtMenu*)(measureInfo.itemData);
4171             HDC hDC = ::GetDC(GetHWnd());
4172             /* menu->MeasureItem(env, hDC, measureInfo); */
4173             menu->MeasureItem(hDC, measureInfo);
4174             ::ReleaseDC(GetHWnd(), hDC);
4175         }
4176     } else {
4177         return OwnerMeasureItem(ctrlId, measureInfo);
4178     }
4179     return mrConsume;
4180 }
4181 
4182 MsgRouting AwtComponent::OwnerDrawItem(UINT ctrlId,
4183     DRAWITEMSTRUCT &drawInfo)
4184 {
4185     AwtComponent* child = AwtComponent::GetComponent(drawInfo.hwndItem);
4186     if (child == this) {
4187         /* DoCallback("handleItemDelete", */
4188     } else if (child != NULL) {
4189         return child->WmDrawItem(ctrlId, drawInfo);
4190     }
4191     return mrConsume;
4192 }
4193 
4194 MsgRouting AwtComponent::OwnerMeasureItem(UINT ctrlId,
4195     MEASUREITEMSTRUCT &measureInfo)
4196 {
4197     HWND  hChild = ::GetDlgItem(GetHWnd(), measureInfo.CtlID);
4198     AwtComponent* child = AwtComponent::GetComponent(hChild);
4199     /*
4200      * If the parent cannot find the child's instance from its handle,
4201      * maybe the child is in its creation.  So the child must be searched
4202      * from the list linked before the child's creation.
4203      */
4204     if (child == NULL) {
4205         child = SearchChild((UINT)ctrlId);
4206     }
4207 
4208     if (child == this) {
4209     /* DoCallback("handleItemDelete",  */
4210     }
4211     else if (child) {
4212         return child->WmMeasureItem(ctrlId, measureInfo);
4213     }
4214     return mrConsume;
4215 }
4216 
4217 /* for WmDrawItem method of Label, Button and Checkbox */
4218 void AwtComponent::DrawWindowText(HDC hDC, jobject font, jstring text,
4219                                   int x, int y)
4220 {
4221     int nOldBkMode = ::SetBkMode(hDC,TRANSPARENT);
4222     DASSERT(nOldBkMode != 0);
4223     AwtFont::drawMFString(hDC, font, text, x, y, GetCodePage());
4224     VERIFY(::SetBkMode(hDC,nOldBkMode));
4225 }
4226 
4227 /*
4228  * Draw text in gray (the color being set to COLOR_GRAYTEXT) when the
4229  * component is disabled.  Used only for label, checkbox and button in
4230  * OWNER_DRAW.  It draws the text in emboss.
4231  */
4232 void AwtComponent::DrawGrayText(HDC hDC, jobject font, jstring text,
4233                                 int x, int y)
4234 {
4235     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHILIGHT));
4236     AwtComponent::DrawWindowText(hDC, font, text, x+1, y+1);
4237     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
4238     AwtComponent::DrawWindowText(hDC, font, text, x, y);
4239 }
4240 
4241 /* for WmMeasureItem method of List and Choice */
4242 jstring AwtComponent::GetItemString(JNIEnv *env, jobject target, jint index)
4243 {
4244     jstring str = (jstring)JNU_CallMethodByName(env, NULL, target, "getItemImpl",
4245                                                 "(I)Ljava/lang/String;",
4246                                                 index).l;
4247     DASSERT(!safe_ExceptionOccurred(env));
4248     return str;
4249 }
4250 
4251 /* for WmMeasureItem method of List and Choice */
4252 void AwtComponent::MeasureListItem(JNIEnv *env,
4253                                    MEASUREITEMSTRUCT &measureInfo)
4254 {
4255     if (env->EnsureLocalCapacity(1) < 0) {
4256         return;
4257     }
4258     jobject dimension = PreferredItemSize(env);
4259     DASSERT(dimension);
4260     measureInfo.itemWidth =
4261       env->GetIntField(dimension, AwtDimension::widthID);
4262     measureInfo.itemHeight =
4263       env->GetIntField(dimension, AwtDimension::heightID);
4264     env->DeleteLocalRef(dimension);
4265 }
4266 
4267 /* for WmDrawItem method of List and Choice */
4268 void AwtComponent::DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo)
4269 {
4270     if (env->EnsureLocalCapacity(3) < 0) {
4271         return;
4272     }
4273     jobject peer = GetPeer(env);
4274     jobject target = env->GetObjectField(peer, AwtObject::targetID);
4275 
4276     HDC hDC = drawInfo.hDC;
4277     RECT rect = drawInfo.rcItem;
4278 
4279     BOOL bEnabled = isEnabled();
4280     BOOL unfocusableChoice = (drawInfo.itemState & ODS_COMBOBOXEDIT) && !IsFocusable();
4281     DWORD crBack, crText;
4282     if (drawInfo.itemState & ODS_SELECTED){
4283         /* Set background and text colors for selected item */
4284         crBack = ::GetSysColor (COLOR_HIGHLIGHT);
4285         crText = ::GetSysColor (COLOR_HIGHLIGHTTEXT);
4286     } else {
4287         /* Set background and text colors for unselected item */
4288         crBack = GetBackgroundColor();
4289         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4290     }
4291     if (unfocusableChoice) {
4292         //6190728. Shouldn't draw selection field (edit control) of an owner-drawn combo box.
4293         crBack = GetBackgroundColor();
4294         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4295     }
4296 
4297     /* Fill item rectangle with background color */
4298     HBRUSH hbrBack = ::CreateSolidBrush (crBack);
4299     DASSERT(hbrBack);
4300     /* 6190728. Shouldn't draw any kind of rectangle around selection field
4301      * (edit control) of an owner-drawn combo box while unfocusable
4302      */
4303     if (!unfocusableChoice){
4304         VERIFY(::FillRect (hDC, &rect, hbrBack));
4305     }
4306     VERIFY(::DeleteObject (hbrBack));
4307 
4308     /* Set current background and text colors */
4309     ::SetBkColor (hDC, crBack);
4310     ::SetTextColor (hDC, crText);
4311 
4312     /*draw string (with left margin of 1 point) */
4313     if ((int) (drawInfo.itemID) >= 0) {
4314             jobject font = GET_FONT(target, peer);
4315             jstring text = GetItemString(env, target, drawInfo.itemID);
4316             SIZE size = AwtFont::getMFStringSize(hDC, font, text);
4317             AwtFont::drawMFString(hDC, font, text,
4318                                   (GetRTL()) ? rect.right - size.cx - 1
4319                                              : rect.left + 1,
4320                                   (rect.top + rect.bottom - size.cy) / 2,
4321                                   GetCodePage());
4322             env->DeleteLocalRef(font);
4323             env->DeleteLocalRef(text);
4324     }
4325     if ((drawInfo.itemState & ODS_FOCUS)  &&
4326         (drawInfo.itemAction & (ODA_FOCUS | ODA_DRAWENTIRE))) {
4327       if (!unfocusableChoice){
4328           VERIFY(::DrawFocusRect(hDC, &rect));
4329       }
4330     }
4331     env->DeleteLocalRef(target);
4332 }
4333 
4334 /* for MeasureListItem method and WmDrawItem method of Checkbox */
4335 jint AwtComponent::GetFontHeight(JNIEnv *env)
4336 {
4337     if (env->EnsureLocalCapacity(4) < 0) {
4338         return NULL;
4339     }
4340     jobject self = GetPeer(env);
4341     jobject target = env->GetObjectField(self, AwtObject::targetID);
4342 
4343     jobject font = GET_FONT(target, self);
4344     jobject toolkit = env->CallObjectMethod(target,
4345                                             AwtComponent::getToolkitMID);
4346 
4347     DASSERT(!safe_ExceptionOccurred(env));
4348 
4349     jobject fontMetrics =
4350         env->CallObjectMethod(toolkit, AwtToolkit::getFontMetricsMID, font);
4351 
4352     DASSERT(!safe_ExceptionOccurred(env));
4353 
4354     jint height = env->CallIntMethod(fontMetrics, AwtFont::getHeightMID);
4355     DASSERT(!safe_ExceptionOccurred(env));
4356 
4357     env->DeleteLocalRef(target);
4358     env->DeleteLocalRef(font);
4359     env->DeleteLocalRef(toolkit);
4360     env->DeleteLocalRef(fontMetrics);
4361 
4362     return height;
4363 }
4364 
4365 // If you override WmPrint, make sure to save a copy of the DC on the GDI
4366 // stack to be restored in WmPrintClient. Windows mangles the DC in
4367 // ::DefWindowProc.
4368 MsgRouting AwtComponent::WmPrint(HDC hDC, LPARAM flags)
4369 {
4370     /*
4371      * DefWindowProc for WM_PRINT changes DC parameters, so we have
4372      * to restore it ourselves. Otherwise it will cause problems
4373      * when several components are printed to the same DC.
4374      */
4375     int nOriginalDC = ::SaveDC(hDC);
4376     DASSERT(nOriginalDC != 0);
4377 
4378     if (flags & PRF_NONCLIENT) {
4379 
4380         VERIFY(::SaveDC(hDC));
4381 
4382         DefWindowProc(WM_PRINT, (WPARAM)hDC,
4383                       (flags & (PRF_NONCLIENT
4384                                 | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4385 
4386         VERIFY(::RestoreDC(hDC, -1));
4387 
4388         // Special case for components with a sunken border. Windows does not
4389         // print the border correctly on PCL printers, so we have to do it ourselves.
4390         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4391             RECT r;
4392             VERIFY(::GetWindowRect(GetHWnd(), &r));
4393             VERIFY(::OffsetRect(&r, -r.left, -r.top));
4394             VERIFY(::DrawEdge(hDC, &r, EDGE_SUNKEN, BF_RECT));
4395         }
4396     }
4397 
4398     if (flags & PRF_CLIENT) {
4399 
4400         /*
4401          * Special case for components with a sunken border.
4402          * Windows prints a client area without offset to a border width.
4403          * We will first print the non-client area with the original offset,
4404          * then the client area with a corrected offset.
4405          */
4406         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4407 
4408             int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE);
4409             int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE);
4410 
4411             VERIFY(::OffsetWindowOrgEx(hDC, -nEdgeWidth, -nEdgeHeight, NULL));
4412 
4413             // Save a copy of the DC for WmPrintClient
4414             VERIFY(::SaveDC(hDC));
4415 
4416             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4417                           (flags & (PRF_CLIENT
4418                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4419 
4420             VERIFY(::OffsetWindowOrgEx(hDC, nEdgeWidth, nEdgeHeight, NULL));
4421 
4422         } else {
4423 
4424             // Save a copy of the DC for WmPrintClient
4425             VERIFY(::SaveDC(hDC));
4426             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4427                           (flags & (PRF_CLIENT
4428                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4429         }
4430     }
4431 
4432     if (flags & (PRF_CHILDREN | PRF_OWNED)) {
4433         DefWindowProc(WM_PRINT, (WPARAM) hDC,
4434                       (flags & ~PRF_CLIENT & ~PRF_NONCLIENT));
4435     }
4436 
4437     VERIFY(::RestoreDC(hDC, nOriginalDC));
4438 
4439     return mrConsume;
4440 }
4441 
4442 // If you override WmPrintClient, make sure to obtain a valid copy of
4443 // the DC from the GDI stack. The copy of the DC should have been placed
4444 // there by WmPrint. Windows mangles the DC in ::DefWindowProc.
4445 MsgRouting AwtComponent::WmPrintClient(HDC hDC, LPARAM)
4446 {
4447     // obtain valid DC from GDI stack
4448     ::RestoreDC(hDC, -1);
4449 
4450     return mrDoDefault;
4451 }
4452 
4453 MsgRouting AwtComponent::WmNcCalcSize(BOOL fCalcValidRects,
4454                                       LPNCCALCSIZE_PARAMS lpncsp,
4455                                       LRESULT &retVal)
4456 {
4457     return mrDoDefault;
4458 }
4459 
4460 MsgRouting AwtComponent::WmNcPaint(HRGN hrgn)
4461 {
4462     return mrDoDefault;
4463 }
4464 
4465 MsgRouting AwtComponent::WmNcHitTest(UINT x, UINT y, LRESULT &retVal)
4466 {
4467     return mrDoDefault;
4468 }
4469 
4470 /**
4471  * WmQueryNewPalette is called whenever our component is coming to
4472  * the foreground; this gives us an opportunity to install our
4473  * custom palette.  If this install actually changes entries in
4474  * the system palette, then we get a further call to WmPaletteChanged
4475  * (but note that we only need to realize our palette once).
4476  */
4477 MsgRouting AwtComponent::WmQueryNewPalette(LRESULT &retVal)
4478 {
4479     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4480     m_QueryNewPaletteCalled = TRUE;
4481     HDC hDC = ::GetDC(GetHWnd());
4482     DASSERT(hDC);
4483     AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4484     AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4485     ::ReleaseDC(GetHWnd(), hDC);
4486     // We must realize the palettes of all of our DC's
4487     // There is sometimes a problem where the realization of
4488     // our temporary hDC here does not actually do what
4489     // we want.  Not clear why, but presumably fallout from
4490     // our use of several simultaneous hDC's.
4491     activeDCList.RealizePalettes(screen);
4492     // Do not invalidate here; if the palette
4493     // has not changed we will get an extra repaint
4494     retVal = TRUE;
4495 
4496     return mrDoDefault;
4497 }
4498 
4499 /**
4500  * We should not need to track this event since we handle our
4501  * palette management effectively in the WmQueryNewPalette and
4502  * WmPaletteChanged methods.  However, there seems to be a bug
4503  * on some win32 systems (e.g., NT4) whereby the palette
4504  * immediately after a displayChange is not yet updated to its
4505  * final post-display-change values (hence we adjust our palette
4506  * using the wrong system palette entries), then the palette is
4507  * updated, but a WM_PALETTECHANGED message is never sent.
4508  * By tracking the ISCHANGING message as well (and by tracking
4509  * displayChange events in the AwtToolkit object), we can account
4510  * for this error by forcing our WmPaletteChanged method to be
4511  * called and thereby realizing our logical palette and updating
4512  * our dynamic colorModel object.
4513  */
4514 MsgRouting AwtComponent::WmPaletteIsChanging(HWND hwndPalChg)
4515 {
4516     if (AwtToolkit::GetInstance().HasDisplayChanged()) {
4517         WmPaletteChanged(hwndPalChg);
4518         AwtToolkit::GetInstance().ResetDisplayChanged();
4519     }
4520     return mrDoDefault;
4521 }
4522 
4523 MsgRouting AwtComponent::WmPaletteChanged(HWND hwndPalChg)
4524 {
4525     // We need to re-realize our palette here (unless we're the one
4526     // that was realizing it in the first place).  That will let us match the
4527     // remaining colors in the system palette as best we can.  We always
4528     // invalidate because the palette will have changed when we receive this
4529     // message.
4530 
4531     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4532     if (hwndPalChg != GetHWnd()) {
4533         HDC hDC = ::GetDC(GetHWnd());
4534         DASSERT(hDC);
4535         AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4536         AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4537         ::ReleaseDC(GetHWnd(), hDC);
4538         // We must realize the palettes of all of our DC's
4539         activeDCList.RealizePalettes(screen);
4540     }
4541     if (AwtWin32GraphicsDevice::UpdateSystemPalette(screen)) {
4542         AwtWin32GraphicsDevice::UpdateDynamicColorModel(screen);
4543     }
4544     Invalidate(NULL);
4545     return mrDoDefault;
4546 }
4547 
4548 MsgRouting AwtComponent::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss)
4549 {
4550     DASSERT(!IsBadReadPtr(lpss, sizeof(STYLESTRUCT)));
4551     return mrDoDefault;
4552 }
4553 
4554 MsgRouting AwtComponent::WmSettingChange(UINT wFlag, LPCTSTR pszSection)
4555 {
4556     DASSERT(!IsBadStringPtr(pszSection, 20));
4557     DTRACE_PRINTLN2("WM_SETTINGCHANGE: wFlag=%d pszSection=%s", (int)wFlag, pszSection);
4558     return mrDoDefault;
4559 }
4560 
4561 HDC AwtComponent::GetDCFromComponent()
4562 {
4563     GetDCReturnStruct *hdcStruct =
4564         (GetDCReturnStruct*)SendMessage(WM_AWT_GETDC);
4565     HDC hdc;
4566     if (hdcStruct) {
4567         if (hdcStruct->gdiLimitReached) {
4568             if (jvm != NULL) {
4569                 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4570                 if (env != NULL && !safe_ExceptionOccurred(env)) {
4571                     JNU_ThrowByName(env, "java/awt/AWTError",
4572                         "HDC creation failure - " \
4573                         "exceeded maximum GDI resources");
4574                 }
4575             }
4576         }
4577         hdc = hdcStruct->hDC;
4578         delete hdcStruct;
4579     } else {
4580         hdc = NULL;
4581     }
4582     return hdc;
4583 }
4584 
4585 void AwtComponent::FillBackground(HDC hMemoryDC, SIZE &size)
4586 {
4587     RECT eraseR = { 0, 0, size.cx, size.cy };
4588     VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush()));
4589 }
4590 
4591 void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
4592 {
4593     if (!bitmapBits) {
4594         return;
4595     }
4596 
4597     DWORD* dest = (DWORD*)bitmapBits;
4598     //XXX: might be optimized to use one loop (cy*cx -> 0)
4599     for (int i = 0; i < size.cy; i++ ) {
4600         for (int j = 0; j < size.cx; j++ ) {
4601             ((BYTE*)(dest++))[3] = alpha;
4602         }
4603     }
4604 }
4605 
4606 jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
4607     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4608 
4609     if (!::IsWindowVisible(GetHWnd())) {
4610         return NULL;
4611     }
4612 
4613     HDC hdc = GetDCFromComponent();
4614     if (!hdc) {
4615         return NULL;
4616     }
4617     HDC hMemoryDC = ::CreateCompatibleDC(hdc);
4618     void *bitmapBits = NULL;
4619     HBITMAP hBitmap = BitmapUtil::CreateARGBBitmap(size.cx, size.cy, &bitmapBits);
4620     HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemoryDC, hBitmap);
4621     SendMessage(WM_AWT_RELEASEDC, (WPARAM)hdc);
4622 
4623     FillBackground(hMemoryDC, size);
4624 
4625     VERIFY(::SetWindowOrgEx(hMemoryDC, loc.cx, loc.cy, NULL));
4626 
4627     // Don't bother with PRF_CHECKVISIBLE because we called IsWindowVisible
4628     // above.
4629     SendMessage(WM_PRINT, (WPARAM)hMemoryDC, PRF_CLIENT | PRF_NONCLIENT);
4630 
4631     // First make sure the system completed any drawing to the bitmap.
4632     ::GdiFlush();
4633 
4634     // WM_PRINT does not fill the alpha-channel of the ARGB bitmap
4635     // leaving it equal to zero. Hence we need to fill it manually. Otherwise
4636     // the pixels will be considered transparent when interpreting the data.
4637     FillAlpha(bitmapBits, size, alpha);
4638 
4639     ::SelectObject(hMemoryDC, hOldBitmap);
4640 
4641     BITMAPINFO bmi;
4642     memset(&bmi, 0, sizeof(BITMAPINFO));
4643     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
4644     bmi.bmiHeader.biWidth = size.cx;
4645     bmi.bmiHeader.biHeight = -size.cy;
4646     bmi.bmiHeader.biPlanes = 1;
4647     bmi.bmiHeader.biBitCount = 32;
4648     bmi.bmiHeader.biCompression = BI_RGB;
4649 
4650     jobject localPixelArray = env->NewIntArray(size.cx * size.cy);
4651     jintArray pixelArray = NULL;
4652     if (localPixelArray != NULL) {
4653         pixelArray = (jintArray)env->NewGlobalRef(localPixelArray);
4654         env->DeleteLocalRef(localPixelArray); localPixelArray = NULL;
4655 
4656         jboolean isCopy;
4657         jint *pixels = env->GetIntArrayElements(pixelArray, &isCopy);
4658 
4659         ::GetDIBits(hMemoryDC, hBitmap, 0, size.cy, (LPVOID)pixels, &bmi,
4660                     DIB_RGB_COLORS);
4661 
4662         env->ReleaseIntArrayElements(pixelArray, pixels, 0);
4663     }
4664 
4665     VERIFY(::DeleteObject(hBitmap));
4666     VERIFY(::DeleteDC(hMemoryDC));
4667 
4668     return pixelArray;
4669 }
4670 
4671 void* AwtComponent::SetNativeFocusOwner(void *self) {
4672     if (self == NULL) {
4673         // It means that the KFM wants to set focus to null
4674         sm_focusOwner = NULL;
4675         return NULL;
4676     }
4677 
4678     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4679 
4680     AwtComponent *c = NULL;
4681     jobject peer = (jobject)self;
4682 
4683     PDATA pData;
4684     JNI_CHECK_NULL_GOTO(peer, "peer", ret);
4685     pData = JNI_GET_PDATA(peer);
4686     if (pData == NULL) {
4687         goto ret;
4688     }
4689     c = (AwtComponent *)pData;
4690 
4691 ret:
4692     if (c && ::IsWindow(c->GetHWnd())) {
4693         sm_focusOwner = c->GetHWnd();
4694     } else {
4695         sm_focusOwner = NULL;
4696     }
4697     env->DeleteGlobalRef(peer);
4698     return NULL;
4699 }
4700 
4701 void* AwtComponent::GetNativeFocusedWindow() {
4702     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4703     AwtComponent *comp =
4704         AwtComponent::GetComponent(AwtComponent::GetFocusedWindow());
4705     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4706 }
4707 
4708 void* AwtComponent::GetNativeFocusOwner() {
4709     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4710     AwtComponent *comp =
4711         AwtComponent::GetComponent(AwtComponent::sm_focusOwner);
4712     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4713 }
4714 
4715 AwtComponent* AwtComponent::SearchChild(UINT id) {
4716     ChildListItem* child;
4717     for (child = m_childList; child != NULL;child = child->m_next) {
4718         if (child->m_ID == id)
4719             return child->m_Component;
4720     }
4721     /*
4722      * DASSERT(FALSE);
4723      * This should not be happend if all children are recorded
4724      */
4725     return NULL;        /* make compiler happy */
4726 }
4727 
4728 void AwtComponent::RemoveChild(UINT id) {
4729     ChildListItem* child = m_childList;
4730     ChildListItem* lastChild = NULL;
4731     while (child != NULL) {
4732         if (child->m_ID == id) {
4733             if (lastChild == NULL) {
4734                 m_childList = child->m_next;
4735             } else {
4736                 lastChild->m_next = child->m_next;
4737             }
4738             child->m_next = NULL;
4739             DASSERT(child != NULL);
4740             delete child;
4741             return;
4742         }
4743         lastChild = child;
4744         child = child->m_next;
4745     }
4746 }
4747 
4748 void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked,
4749                                 jint modifiers, jint keyLocation, jlong nativeCode, MSG *pMsg)
4750 {
4751     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4752     CriticalSection::Lock l(GetLock());
4753     if (GetPeer(env) == NULL) {
4754         /* event received during termination. */
4755         return;
4756     }
4757 
4758     static jclass keyEventCls;
4759     if (keyEventCls == NULL) {
4760         jclass keyEventClsLocal = env->FindClass("java/awt/event/KeyEvent");
4761         DASSERT(keyEventClsLocal);
4762         if (keyEventClsLocal == NULL) {
4763             /* exception already thrown */
4764             return;
4765         }
4766         keyEventCls = (jclass)env->NewGlobalRef(keyEventClsLocal);
4767         env->DeleteLocalRef(keyEventClsLocal);
4768     }
4769 
4770     static jmethodID keyEventConst;
4771     if (keyEventConst == NULL) {
4772         keyEventConst =  env->GetMethodID(keyEventCls, "<init>",
4773                                           "(Ljava/awt/Component;IJIICI)V");
4774         DASSERT(keyEventConst);
4775     }
4776     if (env->EnsureLocalCapacity(2) < 0) {
4777         return;
4778     }
4779     jobject target = GetTarget(env);
4780     jobject keyEvent = env->NewObject(keyEventCls, keyEventConst, target,
4781                                       id, when, modifiers, raw, cooked,
4782                                       keyLocation);
4783     if (safe_ExceptionOccurred(env)) env->ExceptionDescribe();
4784     DASSERT(!safe_ExceptionOccurred(env));
4785     DASSERT(keyEvent != NULL);
4786     env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode);
4787     if( nativeCode && nativeCode < 256 ) {
4788         env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode));
4789         env->SetLongField(keyEvent, AwtKeyEvent::extendedKeyCodeID, (jlong)(dynPrimaryKeymap[nativeCode].jkey));
4790         if( nativeCode < 255 ) {
4791             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(dynPrimaryKeymap[nativeCode].scancode));
4792         }else if( pMsg != NULL ) {
4793             // unknown key with virtual keycode 0xFF.
4794             // Its scancode is not in the table, pickup it from the message.
4795             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(HIWORD(pMsg->lParam) & 0xFF));
4796         }
4797     }
4798     if (pMsg != NULL) {
4799         AwtAWTEvent::saveMSG(env, pMsg, keyEvent);
4800     }
4801     SendEvent(keyEvent);
4802 
4803     env->DeleteLocalRef(keyEvent);
4804     env->DeleteLocalRef(target);
4805 }
4806 
4807 void
4808 AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when,
4809                                        jint raw, jint cooked,
4810                                        jint modifiers, jint keyLocation,
4811                                        jlong nativeCode,
4812                                        MSG *msg)
4813 {
4814     /*
4815      * if focus owner is null, but focused window isn't
4816      * we will send key event to focused window
4817      */
4818     HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : AwtComponent::GetFocusedWindow());
4819 
4820     if (hwndTarget == GetHWnd()) {
4821         SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, nativeCode, msg);
4822     } else {
4823         AwtComponent *target = NULL;
4824         if (hwndTarget != NULL) {
4825             target = AwtComponent::GetComponent(hwndTarget);
4826             if (target == NULL) {
4827                 target = this;
4828             }
4829         }
4830         if (target != NULL) {
4831             target->SendKeyEvent(id, when, raw, cooked, modifiers,
4832               keyLocation, nativeCode, msg);
4833         }
4834     }
4835 }
4836 
4837 void AwtComponent::SetDragCapture(UINT flags)
4838 {
4839     // don't want to interfere with other controls
4840     if (::GetCapture() == NULL) {
4841         ::SetCapture(GetHWnd());
4842     }
4843 }
4844 
4845 void AwtComponent::ReleaseDragCapture(UINT flags)
4846 {
4847     if ((::GetCapture() == GetHWnd()) && ((flags & ALL_MK_BUTTONS) == 0)) {
4848         // user has released all buttons, so release the capture
4849         ::ReleaseCapture();
4850     }
4851 }
4852 
4853 void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y,
4854                                   jint modifiers, jint clickCount,
4855                                   jboolean popupTrigger, jint button,
4856                                   MSG *pMsg)
4857 {
4858     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4859     CriticalSection::Lock l(GetLock());
4860     if (GetPeer(env) == NULL) {
4861         /* event received during termination. */
4862         return;
4863     }
4864 
4865     static jclass mouseEventCls;
4866     if (mouseEventCls == NULL) {
4867         jclass mouseEventClsLocal =
4868             env->FindClass("java/awt/event/MouseEvent");
4869         if (!mouseEventClsLocal) {
4870             /* exception already thrown */
4871             return;
4872         }
4873         mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal);
4874         env->DeleteLocalRef(mouseEventClsLocal);
4875     }
4876     RECT insets;
4877     GetInsets(&insets);
4878 
4879     static jmethodID mouseEventConst;
4880     if (mouseEventConst == NULL) {
4881         mouseEventConst =
4882             env->GetMethodID(mouseEventCls, "<init>",
4883                  "(Ljava/awt/Component;IJIIIIIIZI)V");
4884         DASSERT(mouseEventConst);
4885     }
4886     if (env->EnsureLocalCapacity(2) < 0) {
4887         return;
4888     }
4889     jobject target = GetTarget(env);
4890     DWORD curMousePos = ::GetMessagePos();
4891     int xAbs = GET_X_LPARAM(curMousePos);
4892     int yAbs = GET_Y_LPARAM(curMousePos);
4893     jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
4894                                         target,
4895                                         id, when, modifiers,
4896                                         x+insets.left, y+insets.top,
4897                     xAbs, yAbs,
4898                                         clickCount, popupTrigger, button);
4899 
4900     if (safe_ExceptionOccurred(env)) {
4901         env->ExceptionDescribe();
4902         env->ExceptionClear();
4903     }
4904 
4905     DASSERT(mouseEvent != NULL);
4906     if (pMsg != 0) {
4907         AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
4908     }
4909     SendEvent(mouseEvent);
4910 
4911     env->DeleteLocalRef(mouseEvent);
4912     env->DeleteLocalRef(target);
4913 }
4914 
4915 void
4916 AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
4917                                   jint modifiers, jint clickCount,
4918                                   jboolean popupTrigger, jint scrollType,
4919                                   jint scrollAmount, jint roundedWheelRotation,
4920                                   jdouble preciseWheelRotation, MSG *pMsg)
4921 {
4922     /* Code based not so loosely on AwtComponent::SendMouseEvent */
4923     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4924     CriticalSection::Lock l(GetLock());
4925     if (GetPeer(env) == NULL) {
4926         /* event received during termination. */
4927         return;
4928     }
4929 
4930     static jclass mouseWheelEventCls;
4931     if (mouseWheelEventCls == NULL) {
4932         jclass mouseWheelEventClsLocal =
4933             env->FindClass("java/awt/event/MouseWheelEvent");
4934         if (!mouseWheelEventClsLocal) {
4935             /* exception already thrown */
4936             return;
4937         }
4938         mouseWheelEventCls = (jclass)env->NewGlobalRef(mouseWheelEventClsLocal);
4939         env->DeleteLocalRef(mouseWheelEventClsLocal);
4940     }
4941     RECT insets;
4942     GetInsets(&insets);
4943 
4944     static jmethodID mouseWheelEventConst;
4945     if (mouseWheelEventConst == NULL) {
4946         mouseWheelEventConst =
4947             env->GetMethodID(mouseWheelEventCls, "<init>",
4948                            "(Ljava/awt/Component;IJIIIIIIZIIID)V");
4949         DASSERT(mouseWheelEventConst);
4950     }
4951     if (env->EnsureLocalCapacity(2) < 0) {
4952         return;
4953     }
4954     jobject target = GetTarget(env);
4955     DTRACE_PRINTLN("creating MWE in JNI");
4956 
4957     jobject mouseWheelEvent = env->NewObject(mouseWheelEventCls,
4958                                              mouseWheelEventConst,
4959                                              target,
4960                                              id, when, modifiers,
4961                                              x+insets.left, y+insets.top,
4962                                              0, 0,
4963                                              clickCount, popupTrigger,
4964                                              scrollType, scrollAmount,
4965                                              roundedWheelRotation, preciseWheelRotation);
4966     if (safe_ExceptionOccurred(env)) {
4967         env->ExceptionDescribe();
4968         env->ExceptionClear();
4969     }
4970     DASSERT(mouseWheelEvent != NULL);
4971     if (pMsg != NULL) {
4972         AwtAWTEvent::saveMSG(env, pMsg, mouseWheelEvent);
4973     }
4974     SendEvent(mouseWheelEvent);
4975 
4976     env->DeleteLocalRef(mouseWheelEvent);
4977     env->DeleteLocalRef(target);
4978 }
4979 
4980 void AwtComponent::SendFocusEvent(jint id, HWND opposite)
4981 {
4982     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4983 
4984     CriticalSection::Lock l(GetLock());
4985     if (GetPeer(env) == NULL) {
4986         /* event received during termination. */
4987         return;
4988     }
4989 
4990     static jclass focusEventCls;
4991     if (focusEventCls == NULL) {
4992         jclass focusEventClsLocal
4993             = env->FindClass("java/awt/event/FocusEvent");
4994         DASSERT(focusEventClsLocal);
4995         if (focusEventClsLocal == NULL) {
4996             /* exception already thrown */
4997             return;
4998         }
4999         focusEventCls = (jclass)env->NewGlobalRef(focusEventClsLocal);
5000         env->DeleteLocalRef(focusEventClsLocal);
5001     }
5002 
5003     static jmethodID focusEventConst;
5004     if (focusEventConst == NULL) {
5005         focusEventConst =
5006             env->GetMethodID(focusEventCls, "<init>",
5007                              "(Ljava/awt/Component;IZLjava/awt/Component;)V");
5008         DASSERT(focusEventConst);
5009     }
5010 
5011     static jclass sequencedEventCls;
5012     if (sequencedEventCls == NULL) {
5013         jclass sequencedEventClsLocal =
5014             env->FindClass("java/awt/SequencedEvent");
5015         DASSERT(sequencedEventClsLocal);
5016         if (sequencedEventClsLocal == NULL) {
5017             /* exception already thrown */
5018             return;
5019         }
5020         sequencedEventCls =
5021             (jclass)env->NewGlobalRef(sequencedEventClsLocal);
5022         env->DeleteLocalRef(sequencedEventClsLocal);
5023     }
5024 
5025     static jmethodID sequencedEventConst;
5026     if (sequencedEventConst == NULL) {
5027         sequencedEventConst =
5028             env->GetMethodID(sequencedEventCls, "<init>",
5029                              "(Ljava/awt/AWTEvent;)V");
5030     }
5031 
5032     if (env->EnsureLocalCapacity(3) < 0) {
5033         return;
5034     }
5035 
5036     jobject target = GetTarget(env);
5037     jobject jOpposite = NULL;
5038     if (opposite != NULL) {
5039         AwtComponent *awtOpposite = AwtComponent::GetComponent(opposite);
5040         if (awtOpposite != NULL) {
5041             jOpposite = awtOpposite->GetTarget(env);
5042         }
5043     }
5044     jobject focusEvent = env->NewObject(focusEventCls, focusEventConst,
5045                                         target, id, JNI_FALSE, jOpposite);
5046     DASSERT(!safe_ExceptionOccurred(env));
5047     DASSERT(focusEvent != NULL);
5048     if (jOpposite != NULL) {
5049         env->DeleteLocalRef(jOpposite); jOpposite = NULL;
5050     }
5051     env->DeleteLocalRef(target); target = NULL;
5052 
5053     jobject sequencedEvent = env->NewObject(sequencedEventCls,
5054                                             sequencedEventConst,
5055                                             focusEvent);
5056     DASSERT(!safe_ExceptionOccurred(env));
5057     DASSERT(sequencedEvent != NULL);
5058     env->DeleteLocalRef(focusEvent); focusEvent = NULL;
5059 
5060     SendEvent(sequencedEvent);
5061 
5062     env->DeleteLocalRef(sequencedEvent);
5063 }
5064 
5065 /*
5066  * Forward a filtered event directly to the subclassed window.
5067  * This method is needed so that DefWindowProc is invoked on the
5068  * component's owning thread.
5069  */
5070 MsgRouting AwtComponent::HandleEvent(MSG *msg, BOOL)
5071 {
5072     DefWindowProc(msg->message, msg->wParam, msg->lParam);
5073     delete msg;
5074     return mrConsume;
5075 }
5076 
5077 /* Post a WM_AWT_HANDLE_EVENT message which invokes HandleEvent
5078    on the toolkit thread. This method may pre-filter the messages. */
5079 BOOL AwtComponent::PostHandleEventMessage(MSG *msg, BOOL synthetic)
5080 {
5081     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5082     // We should cut off keyboard events to disabled components
5083     // to avoid the components responding visually to keystrokes when disabled.
5084     // we shouldn't cut off WM_SYS* messages as they aren't used for normal activity
5085     // but to activate menus, close windows, etc
5086     switch(msg->message) {
5087         case WM_KEYDOWN:
5088         case WM_KEYUP:
5089         case WM_CHAR:
5090         case WM_DEADCHAR:
5091             {
5092                 if (!isRecursivelyEnabled()) {
5093                     goto quit;
5094                 }
5095                 break;
5096             }
5097     }
5098     if (PostMessage(GetHWnd(), WM_AWT_HANDLE_EVENT,
5099         (WPARAM) synthetic, (LPARAM) msg)) {
5100             return TRUE;
5101     } else {
5102         JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5103     }
5104 quit:
5105     delete msg;
5106     return FALSE;
5107 }
5108 
5109 void AwtComponent::SynthesizeKeyMessage(JNIEnv *env, jobject keyEvent)
5110 {
5111     jint id = (env)->GetIntField(keyEvent, AwtAWTEvent::idID);
5112     UINT message;
5113     switch (id) {
5114       case java_awt_event_KeyEvent_KEY_PRESSED:
5115           message = WM_KEYDOWN;
5116           break;
5117       case java_awt_event_KeyEvent_KEY_RELEASED:
5118           message = WM_KEYUP;
5119           break;
5120       case java_awt_event_KeyEvent_KEY_TYPED:
5121           message = WM_CHAR;
5122           break;
5123       default:
5124           return;
5125     }
5126 
5127     /*
5128      * KeyEvent.modifiers aren't supported -- the Java apppwd must send separate
5129      * KEY_PRESSED and KEY_RELEASED events for the modifier virtual keys.
5130      */
5131     if (id == java_awt_event_KeyEvent_KEY_TYPED) {
5132         // WM_CHAR message must be posted using WM_AWT_FORWARD_CHAR
5133         // (for Edit control)
5134         jchar keyChar = (jchar)
5135           (env)->GetCharField(keyEvent, AwtKeyEvent::keyCharID);
5136 
5137         // Bugid 4724007.  If it is a Delete character, don't send the fake
5138         // KEY_TYPED we created back to the native window: Windows doesn't
5139         // expect a WM_CHAR for Delete in TextFields, so it tries to enter a
5140         // character after deleting.
5141         if (keyChar == '\177') { // the Delete character
5142             return;
5143         }
5144 
5145         // Disable forwarding WM_CHAR messages to disabled components
5146         if (isRecursivelyEnabled()) {
5147             if (!::PostMessage(GetHWnd(), WM_AWT_FORWARD_CHAR,
5148                 MAKEWPARAM(keyChar, TRUE), 0)) {
5149                 JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5150             }
5151         }
5152     } else {
5153         jint keyCode =
5154           (env)->GetIntField(keyEvent, AwtKeyEvent::keyCodeID);
5155         UINT key, modifiers;
5156         AwtComponent::JavaKeyToWindowsKey(keyCode, &key, &modifiers);
5157         MSG* msg = CreateMessage(message, key, 0);
5158         PostHandleEventMessage(msg, TRUE);
5159     }
5160 }
5161 
5162 void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent)
5163 {
5164     /*    DebugBreak(); */
5165     jint button = (env)->GetIntField(mouseEvent, AwtMouseEvent::buttonID);
5166     jint modifiers = (env)->GetIntField(mouseEvent, AwtInputEvent::modifiersID);
5167 
5168     WPARAM wParam = 0;
5169     WORD wLow = 0;
5170     jint wheelAmt = 0;
5171     jint id = (env)->GetIntField(mouseEvent, AwtAWTEvent::idID);
5172     UINT message;
5173     switch (id) {
5174       case java_awt_event_MouseEvent_MOUSE_PRESSED: {
5175           switch (button) {
5176             case java_awt_event_MouseEvent_BUTTON1:
5177                 message = WM_LBUTTONDOWN; break;
5178             case java_awt_event_MouseEvent_BUTTON3:
5179                 message = WM_MBUTTONDOWN; break;
5180             case java_awt_event_MouseEvent_BUTTON2:
5181                 message = WM_RBUTTONDOWN; break;
5182           }
5183           break;
5184       }
5185       case java_awt_event_MouseEvent_MOUSE_RELEASED: {
5186           switch (button) {
5187             case java_awt_event_MouseEvent_BUTTON1:
5188                 message = WM_LBUTTONUP; break;
5189             case java_awt_event_MouseEvent_BUTTON3:
5190                 message = WM_MBUTTONUP; break;
5191             case java_awt_event_MouseEvent_BUTTON2:
5192                 message = WM_RBUTTONUP; break;
5193           }
5194           break;
5195       }
5196       case java_awt_event_MouseEvent_MOUSE_MOVED:
5197           /* MOUSE_DRAGGED events must first have sent a MOUSE_PRESSED event. */
5198       case java_awt_event_MouseEvent_MOUSE_DRAGGED:
5199           message = WM_MOUSEMOVE;
5200           break;
5201       case java_awt_event_MouseEvent_MOUSE_WHEEL:
5202           if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
5203               wLow |= MK_CONTROL;
5204           }
5205           if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
5206               wLow |= MK_SHIFT;
5207           }
5208           if (modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
5209               wLow |= MK_LBUTTON;
5210           }
5211           if (modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) {
5212               wLow |= MK_RBUTTON;
5213           }
5214           if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) {
5215               wLow |= MK_MBUTTON;
5216           }
5217           if (modifiers & X1_BUTTON) {
5218               wLow |= GetButtonMK(X1_BUTTON);
5219           }
5220           if (modifiers & X2_BUTTON) {
5221               wLow |= GetButtonMK(X2_BUTTON);
5222           }
5223 
5224           wheelAmt = (jint)JNU_CallMethodByName(env,
5225                                                NULL,
5226                                                mouseEvent,
5227                                                "getWheelRotation",
5228                                                "()I").i;
5229           DASSERT(!safe_ExceptionOccurred(env));
5230           //DASSERT(wheelAmt);
5231           DTRACE_PRINTLN1("wheelAmt = %i\n", wheelAmt);
5232 
5233           // convert Java wheel amount value to Win32
5234           wheelAmt *= -1 * WHEEL_DELTA;
5235 
5236           message = WM_MOUSEWHEEL;
5237           wParam = MAKEWPARAM(wLow, wheelAmt);
5238 
5239           break;
5240       default:
5241           return;
5242     }
5243     jint x = (env)->GetIntField(mouseEvent, AwtMouseEvent::xID);
5244     jint y = (env)->GetIntField(mouseEvent, AwtMouseEvent::yID);
5245     MSG* msg = CreateMessage(message, wParam, MAKELPARAM(x, y), x, y);
5246     PostHandleEventMessage(msg, TRUE);
5247 }
5248 
5249 BOOL AwtComponent::InheritsNativeMouseWheelBehavior() {return false;}
5250 
5251 void AwtComponent::Invalidate(RECT* r)
5252 {
5253     ::InvalidateRect(GetHWnd(), r, FALSE);
5254 }
5255 
5256 void AwtComponent::BeginValidate()
5257 {
5258     DASSERT(m_validationNestCount >= 0 &&
5259            m_validationNestCount < 1000); // sanity check
5260 
5261     if (m_validationNestCount == 0) {
5262     // begin deferred window positioning if we're not inside
5263     // another Begin/EndValidate pair
5264         DASSERT(m_hdwp == NULL);
5265         m_hdwp = ::BeginDeferWindowPos(32);
5266     }
5267 
5268     m_validationNestCount++;
5269 }
5270 
5271 void AwtComponent::EndValidate()
5272 {
5273     DASSERT(m_validationNestCount > 0 &&
5274            m_validationNestCount < 1000); // sanity check
5275     DASSERT(m_hdwp != NULL);
5276 
5277     m_validationNestCount--;
5278     if (m_validationNestCount == 0) {
5279     // if this call to EndValidate is not nested inside another
5280     // Begin/EndValidate pair, end deferred window positioning
5281         ::EndDeferWindowPos(m_hdwp);
5282         m_hdwp = NULL;
5283     }
5284 }
5285 
5286 /**
5287  * HWND, AwtComponent and Java Peer interaction
5288  */
5289 
5290 /*
5291  *Link the C++, Java peer, and HWNDs together.
5292  */
5293 void AwtComponent::LinkObjects(JNIEnv *env, jobject peer)
5294 {
5295     /*
5296      * Bind all three objects together thru this C++ object, two-way to each:
5297      *     JavaPeer <-> C++ <-> HWND
5298      *
5299      * C++ -> JavaPeer
5300      */
5301     if (m_peerObject == NULL) {
5302         // This may have already been set up by CreateHWnd
5303         // And we don't want to create two references so we
5304         // will leave the prior one alone
5305         m_peerObject = env->NewGlobalRef(peer);
5306     }
5307     /* JavaPeer -> HWND */
5308     env->SetLongField(peer, AwtComponent::hwndID, reinterpret_cast<jlong>(m_hwnd));
5309 
5310     /* JavaPeer -> C++ */
5311     JNI_SET_PDATA(peer, this);
5312 
5313     /* HWND -> C++ */
5314     SetComponentInHWND();
5315 }
5316 
5317 /* Cleanup above linking */
5318 void AwtComponent::UnlinkObjects()
5319 {
5320     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5321     if (m_peerObject) {
5322         env->SetLongField(m_peerObject, AwtComponent::hwndID, 0);
5323         JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL));
5324         JNI_SET_DESTROYED(m_peerObject);
5325         env->DeleteGlobalRef(m_peerObject);
5326         m_peerObject = NULL;
5327     }
5328 }
5329 
5330 void AwtComponent::Enable(BOOL bEnable)
5331 {
5332     if (bEnable && IsTopLevel()) {
5333         // we should not enable blocked toplevels
5334         bEnable = !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()));
5335     }
5336     // Shouldn't trigger native focus change
5337     // (only the proxy may be the native focus owner).
5338     ::EnableWindow(GetHWnd(), bEnable);
5339 
5340     CriticalSection::Lock l(GetLock());
5341     VerifyState();
5342 }
5343 
5344 /*
5345  * associate an AwtDropTarget with this AwtComponent
5346  */
5347 
5348 AwtDropTarget* AwtComponent::CreateDropTarget(JNIEnv* env) {
5349     m_dropTarget = new AwtDropTarget(env, this);
5350     m_dropTarget->RegisterTarget(TRUE);
5351     return m_dropTarget;
5352 }
5353 
5354 /*
5355  * disassociate an AwtDropTarget with this AwtComponent
5356  */
5357 
5358 void AwtComponent::DestroyDropTarget() {
5359     if (m_dropTarget != NULL) {
5360         m_dropTarget->RegisterTarget(FALSE);
5361         m_dropTarget->Release();
5362         m_dropTarget = NULL;
5363     }
5364 }
5365 
5366 BOOL AwtComponent::IsFocusingMouseMessage(MSG *pMsg) {
5367     return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
5368 }
5369 
5370 BOOL AwtComponent::IsFocusingKeyMessage(MSG *pMsg) {
5371     return pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_SPACE;
5372 }
5373 
5374 void AwtComponent::_Show(void *param)
5375 {
5376     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5377 
5378     jobject self = (jobject)param;
5379 
5380     AwtComponent *p;
5381 
5382     PDATA pData;
5383     JNI_CHECK_PEER_GOTO(self, ret);
5384     p = (AwtComponent *)pData;
5385     if (::IsWindow(p->GetHWnd()))
5386     {
5387         p->SendMessage(WM_AWT_COMPONENT_SHOW);
5388     }
5389 ret:
5390     env->DeleteGlobalRef(self);
5391 }
5392 
5393 void AwtComponent::_Hide(void *param)
5394 {
5395     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5396 
5397     jobject self = (jobject)param;
5398 
5399     AwtComponent *p;
5400 
5401     PDATA pData;
5402     JNI_CHECK_PEER_GOTO(self, ret);
5403     p = (AwtComponent *)pData;
5404     if (::IsWindow(p->GetHWnd()))
5405     {
5406         p->SendMessage(WM_AWT_COMPONENT_HIDE);
5407     }
5408 ret:
5409     env->DeleteGlobalRef(self);
5410 }
5411 
5412 void AwtComponent::_Enable(void *param)
5413 {
5414     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5415 
5416     jobject self = (jobject)param;
5417 
5418     AwtComponent *p;
5419 
5420     PDATA pData;
5421     JNI_CHECK_PEER_GOTO(self, ret);
5422     p = (AwtComponent *)pData;
5423     if (::IsWindow(p->GetHWnd()))
5424     {
5425         p->Enable(TRUE);
5426     }
5427 ret:
5428     env->DeleteGlobalRef(self);
5429 }
5430 
5431 void AwtComponent::_Disable(void *param)
5432 {
5433     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5434 
5435     jobject self = (jobject)param;
5436 
5437     AwtComponent *p;
5438 
5439     PDATA pData;
5440     JNI_CHECK_PEER_GOTO(self, ret);
5441     p = (AwtComponent *)pData;
5442     if (::IsWindow(p->GetHWnd()))
5443     {
5444         p->Enable(FALSE);
5445     }
5446 ret:
5447     env->DeleteGlobalRef(self);
5448 }
5449 
5450 jobject AwtComponent::_GetLocationOnScreen(void *param)
5451 {
5452     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5453 
5454     jobject self = (jobject)param;
5455 
5456     jobject result = NULL;
5457     AwtComponent *p;
5458 
5459     PDATA pData;
5460     JNI_CHECK_PEER_GOTO(self, ret);
5461     p = (AwtComponent *)pData;
5462     if (::IsWindow(p->GetHWnd()))
5463     {
5464         RECT rect;
5465         VERIFY(::GetWindowRect(p->GetHWnd(),&rect));
5466         result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
5467             rect.left, rect.top);
5468     }
5469 ret:
5470     env->DeleteGlobalRef(self);
5471 
5472     if (result != NULL)
5473     {
5474         jobject resultGlobalRef = env->NewGlobalRef(result);
5475         env->DeleteLocalRef(result);
5476         return resultGlobalRef;
5477     }
5478     else
5479     {
5480         return NULL;
5481     }
5482 }
5483 
5484 void AwtComponent::_Reshape(void *param)
5485 {
5486     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5487 
5488     ReshapeStruct *rs = (ReshapeStruct*)param;
5489     jobject self = rs->component;
5490     jint x = rs->x;
5491     jint y = rs->y;
5492     jint w = rs->w;
5493     jint h = rs->h;
5494 
5495     AwtComponent *p;
5496 
5497     PDATA pData;
5498     JNI_CHECK_PEER_GOTO(self, ret);
5499     p = (AwtComponent *)pData;
5500     if (::IsWindow(p->GetHWnd()))
5501     {
5502         RECT* r = new RECT;
5503         ::SetRect(r, x, y, x + w, y + h);
5504         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, CHECK_EMBEDDED, (LPARAM)r);
5505     }
5506 ret:
5507     env->DeleteGlobalRef(self);
5508 
5509     delete rs;
5510 }
5511 
5512 void AwtComponent::_ReshapeNoCheck(void *param)
5513 {
5514     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5515 
5516     ReshapeStruct *rs = (ReshapeStruct*)param;
5517     jobject self = rs->component;
5518     jint x = rs->x;
5519     jint y = rs->y;
5520     jint w = rs->w;
5521     jint h = rs->h;
5522 
5523     AwtComponent *p;
5524 
5525     PDATA pData;
5526     JNI_CHECK_PEER_GOTO(self, ret);
5527     p = (AwtComponent *)pData;
5528     if (::IsWindow(p->GetHWnd()))
5529     {
5530         RECT* r = new RECT;
5531         ::SetRect(r, x, y, x + w, y + h);
5532         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, DONT_CHECK_EMBEDDED, (LPARAM)r);
5533     }
5534 ret:
5535     env->DeleteGlobalRef(self);
5536 
5537     delete rs;
5538 }
5539 
5540 void AwtComponent::_NativeHandleEvent(void *param)
5541 {
5542     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5543 
5544     NativeHandleEventStruct *nhes = (NativeHandleEventStruct *)param;
5545     jobject self = nhes->component;
5546     jobject event = nhes->event;
5547 
5548     AwtComponent *p;
5549 
5550     PDATA pData;
5551     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5552     pData = JNI_GET_PDATA(self);
5553     if (pData == NULL) {
5554         env->DeleteGlobalRef(self);
5555         if (event != NULL) {
5556             env->DeleteGlobalRef(event);
5557         }
5558         delete nhes;
5559         return;
5560     }
5561     JNI_CHECK_NULL_GOTO(event, "null AWTEvent", ret);
5562 
5563     p = (AwtComponent *)pData;
5564     if (::IsWindow(p->GetHWnd()))
5565     {
5566         if (env->EnsureLocalCapacity(1) < 0) {
5567             env->DeleteGlobalRef(self);
5568             env->DeleteGlobalRef(event);
5569             delete nhes;
5570             return;
5571         }
5572         jbyteArray bdata = (jbyteArray)(env)->GetObjectField(event, AwtAWTEvent::bdataID);
5573         int id = (env)->GetIntField(event, AwtAWTEvent::idID);
5574         DASSERT(!safe_ExceptionOccurred(env));
5575         if (bdata != 0) {
5576             MSG msg;
5577             (env)->GetByteArrayRegion(bdata, 0, sizeof(MSG), (jbyte *)&msg);
5578             (env)->DeleteLocalRef(bdata);
5579             static BOOL keyDownConsumed = FALSE;
5580             static BOOL bCharChanged = FALSE;
5581             static WCHAR modifiedChar;
5582             WCHAR unicodeChar;
5583 
5584             /* Remember if a KEY_PRESSED event is consumed, as an old model
5585              * program won't consume a subsequent KEY_TYPED event.
5586              */
5587             jboolean consumed =
5588                 (env)->GetBooleanField(event, AwtAWTEvent::consumedID);
5589             DASSERT(!safe_ExceptionOccurred(env));
5590 
5591             if (consumed) {
5592                 keyDownConsumed = (id == java_awt_event_KeyEvent_KEY_PRESSED);
5593                 env->DeleteGlobalRef(self);
5594                 env->DeleteGlobalRef(event);
5595                 delete nhes;
5596                 return;
5597 
5598             } else if (id == java_awt_event_KeyEvent_KEY_PRESSED) {
5599                 // Fix for 6637607: reset consuming
5600                 keyDownConsumed = FALSE;
5601             }
5602 
5603             /* Consume a KEY_TYPED event if a KEY_PRESSED had been, to support
5604              * the old model.
5605              */
5606             if ((id == java_awt_event_KeyEvent_KEY_TYPED) && keyDownConsumed) {
5607                 keyDownConsumed = FALSE;
5608                 env->DeleteGlobalRef(self);
5609                 env->DeleteGlobalRef(event);
5610                 delete nhes;
5611                 return;
5612             }
5613 
5614             /* Modify any event parameters, if necessary. */
5615             if (self && pData &&
5616                 id >= java_awt_event_KeyEvent_KEY_FIRST &&
5617                 id <= java_awt_event_KeyEvent_KEY_LAST) {
5618 
5619                     AwtComponent* p = (AwtComponent*)pData;
5620 
5621                     jint keyCode =
5622                       (env)->GetIntField(event, AwtKeyEvent::keyCodeID);
5623                     jchar keyChar =
5624                       (env)->GetCharField(event, AwtKeyEvent::keyCharID);
5625                     jint modifiers =
5626                       (env)->GetIntField(event, AwtInputEvent::modifiersID);
5627 
5628                     DASSERT(!safe_ExceptionOccurred(env));
5629 
5630                 /* Check to see whether the keyCode or modifiers were changed
5631                    on the keyPressed event, and tweak the following keyTyped
5632                    event (if any) accodingly.  */
5633                 switch (id) {
5634                 case java_awt_event_KeyEvent_KEY_PRESSED:
5635                 {
5636                     UINT winKey = (UINT)msg.wParam;
5637                     bCharChanged = FALSE;
5638 
5639                     if (winKey == VK_PROCESSKEY) {
5640                         // Leave it up to IME
5641                         break;
5642                     }
5643 
5644                     if (keyCode != java_awt_event_KeyEvent_VK_UNDEFINED) {
5645                         UINT newWinKey, ignored;
5646                         p->JavaKeyToWindowsKey(keyCode, &newWinKey, &ignored, winKey);
5647                         if (newWinKey != 0) {
5648                             winKey = newWinKey;
5649                         }
5650                     }
5651 
5652                     BOOL isDeadKey = FALSE;
5653                     modifiedChar = p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE, isDeadKey);
5654                     bCharChanged = (keyChar != modifiedChar);
5655                 }
5656                 break;
5657 
5658                 case java_awt_event_KeyEvent_KEY_RELEASED:
5659                 {
5660                     keyDownConsumed = FALSE;
5661                     bCharChanged = FALSE;
5662                 }
5663                 break;
5664 
5665                 case java_awt_event_KeyEvent_KEY_TYPED:
5666                 {
5667                     if (bCharChanged)
5668                     {
5669                         unicodeChar = modifiedChar;
5670                     }
5671                     else
5672                     {
5673                         unicodeChar = keyChar;
5674                     }
5675                     bCharChanged = FALSE;
5676 
5677                     // Disable forwarding KEY_TYPED messages to peers of
5678                     // disabled components
5679                     if (p->isRecursivelyEnabled()) {
5680                         // send the character back to the native window for
5681                         // processing. The WM_AWT_FORWARD_CHAR handler will send
5682                         // this character to DefWindowProc
5683                         if (!::PostMessage(p->GetHWnd(), WM_AWT_FORWARD_CHAR,
5684                             MAKEWPARAM(unicodeChar, FALSE), msg.lParam)) {
5685                             JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5686                         }
5687                     }
5688                     env->DeleteGlobalRef(self);
5689                     env->DeleteGlobalRef(event);
5690                     delete nhes;
5691                     return;
5692                 }
5693                 break;
5694 
5695                 default:
5696                     break;
5697                 }
5698             }
5699 
5700             // ignore all InputMethodEvents
5701             if (self && (pData = JNI_GET_PDATA(self)) &&
5702                 id >= java_awt_event_InputMethodEvent_INPUT_METHOD_FIRST &&
5703                 id <= java_awt_event_InputMethodEvent_INPUT_METHOD_LAST) {
5704                 env->DeleteGlobalRef(self);
5705                 env->DeleteGlobalRef(event);
5706                 delete nhes;
5707                 return;
5708             }
5709 
5710             // Create copy for local msg
5711             MSG* pCopiedMsg = new MSG;
5712             memmove(pCopiedMsg, &msg, sizeof(MSG));
5713             // Event handler deletes msg
5714             p->PostHandleEventMessage(pCopiedMsg, FALSE);
5715 
5716             env->DeleteGlobalRef(self);
5717             env->DeleteGlobalRef(event);
5718             delete nhes;
5719             return;
5720         }
5721 
5722         /* Forward any valid synthesized events.  Currently only mouse and
5723          * key events are supported.
5724          */
5725         if (self == NULL || (pData = JNI_GET_PDATA(self)) == NULL) {
5726             env->DeleteGlobalRef(self);
5727             env->DeleteGlobalRef(event);
5728             delete nhes;
5729             return;
5730         }
5731 
5732         AwtComponent* p = (AwtComponent*)pData;
5733         if (id >= java_awt_event_KeyEvent_KEY_FIRST &&
5734             id <= java_awt_event_KeyEvent_KEY_LAST) {
5735             p->SynthesizeKeyMessage(env, event);
5736         } else if (id >= java_awt_event_MouseEvent_MOUSE_FIRST &&
5737                    id <= java_awt_event_MouseEvent_MOUSE_LAST) {
5738             p->SynthesizeMouseMessage(env, event);
5739         }
5740     }
5741 
5742 ret:
5743     if (self != NULL) {
5744         env->DeleteGlobalRef(self);
5745     }
5746     if (event != NULL) {
5747         env->DeleteGlobalRef(event);
5748     }
5749 
5750     delete nhes;
5751 }
5752 
5753 void AwtComponent::_SetForeground(void *param)
5754 {
5755     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5756 
5757     SetColorStruct *scs = (SetColorStruct *)param;
5758     jobject self = scs->component;
5759     jint rgb = scs->rgb;
5760 
5761     AwtComponent *c = NULL;
5762 
5763     PDATA pData;
5764     JNI_CHECK_PEER_GOTO(self, ret);
5765     c = (AwtComponent *)pData;
5766     if (::IsWindow(c->GetHWnd()))
5767     {
5768         c->SetColor(PALETTERGB((rgb>>16)&0xff,
5769                                (rgb>>8)&0xff,
5770                                (rgb)&0xff));
5771         c->VerifyState();
5772     }
5773 ret:
5774     env->DeleteGlobalRef(self);
5775 
5776     delete scs;
5777 }
5778 
5779 void AwtComponent::_SetBackground(void *param)
5780 {
5781     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5782 
5783     SetColorStruct *scs = (SetColorStruct *)param;
5784     jobject self = scs->component;
5785     jint rgb = scs->rgb;
5786 
5787     AwtComponent *c = NULL;
5788 
5789     PDATA pData;
5790     JNI_CHECK_PEER_GOTO(self, ret);
5791     c = (AwtComponent *)pData;
5792     if (::IsWindow(c->GetHWnd()))
5793     {
5794         c->SetBackgroundColor(PALETTERGB((rgb>>16)&0xff,
5795                                          (rgb>>8)&0xff,
5796                                          (rgb)&0xff));
5797         c->VerifyState();
5798     }
5799 ret:
5800     env->DeleteGlobalRef(self);
5801 
5802     delete scs;
5803 }
5804 
5805 void AwtComponent::_SetFont(void *param)
5806 {
5807     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5808 
5809     SetFontStruct *sfs = (SetFontStruct *)param;
5810     jobject self = sfs->component;
5811     jobject font = sfs->font;
5812 
5813     AwtComponent *c = NULL;
5814 
5815     PDATA pData;
5816     JNI_CHECK_PEER_GOTO(self, ret);
5817     JNI_CHECK_NULL_GOTO(font, "null font", ret);
5818     c = (AwtComponent *)pData;
5819     if (::IsWindow(c->GetHWnd()))
5820     {
5821         AwtFont *awtFont = (AwtFont *)env->GetLongField(font, AwtFont::pDataID);
5822         if (awtFont == NULL) {
5823             /*arguments of AwtFont::Create are changed for multifont component */
5824             awtFont = AwtFont::Create(env, font);
5825         }
5826         env->SetLongField(font, AwtFont::pDataID, (jlong)awtFont);
5827 
5828         c->SetFont(awtFont);
5829     }
5830 ret:
5831     env->DeleteGlobalRef(self);
5832     env->DeleteGlobalRef(font);
5833 
5834     delete sfs;
5835 }
5836 
5837 // Sets or kills focus for a component.
5838 void AwtComponent::_SetFocus(void *param)
5839 {
5840     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5841 
5842     SetFocusStruct *sfs = (SetFocusStruct *)param;
5843     jobject self = sfs->component;
5844     jboolean doSetFocus = sfs->doSetFocus;
5845 
5846     AwtComponent *c = NULL;
5847 
5848     PDATA pData;
5849     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5850     pData = JNI_GET_PDATA(self);
5851     if (pData == NULL) {
5852         // do nothing just return false
5853         goto ret;
5854     }
5855 
5856     c = (AwtComponent *)pData;
5857     if (::IsWindow(c->GetHWnd())) {
5858         c->SendMessage(WM_AWT_COMPONENT_SETFOCUS, (WPARAM)doSetFocus, 0);
5859     }
5860 ret:
5861     env->DeleteGlobalRef(self);
5862 
5863     delete sfs;
5864 }
5865 
5866 void AwtComponent::_Start(void *param)
5867 {
5868     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5869 
5870     jobject self = (jobject)param;
5871 
5872     AwtComponent *c = NULL;
5873 
5874     PDATA pData;
5875     JNI_CHECK_PEER_GOTO(self, ret);
5876     c = (AwtComponent *)pData;
5877     if (::IsWindow(c->GetHWnd()))
5878     {
5879         jobject target = c->GetTarget(env);
5880 
5881         /* Disable window if specified -- windows are enabled by default. */
5882         jboolean enabled = (jboolean)env->GetBooleanField(target,
5883                                                           AwtComponent::enabledID);
5884         if (!enabled) {
5885             ::EnableWindow(c->GetHWnd(), FALSE);
5886         }
5887 
5888         /* The peer is now ready for callbacks, since this is the last
5889          * initialization call
5890          */
5891         c->EnableCallbacks(TRUE);
5892 
5893         // Fix 4745222: we need to invalidate region since we validated it before initialization.
5894         ::InvalidateRgn(c->GetHWnd(), NULL, FALSE);
5895 
5896         // Fix 4530093: WM_PAINT after EnableCallbacks
5897         ::UpdateWindow(c->GetHWnd());
5898 
5899         env->DeleteLocalRef(target);
5900     }
5901 ret:
5902     env->DeleteGlobalRef(self);
5903 }
5904 
5905 void AwtComponent::_BeginValidate(void *param)
5906 {
5907     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5908     if (AwtToolkit::IsMainThread()) {
5909         jobject self = (jobject)param;
5910         if (self != NULL) {
5911             PDATA pData = JNI_GET_PDATA(self);
5912             if (pData) {
5913                 AwtComponent *c = (AwtComponent *)pData;
5914                 if (::IsWindow(c->GetHWnd())) {
5915                     c->SendMessage(WM_AWT_BEGIN_VALIDATE);
5916                 }
5917             }
5918             env->DeleteGlobalRef(self);
5919         }
5920     } else {
5921         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_BeginValidate, param);
5922     }
5923 }
5924 
5925 void AwtComponent::_EndValidate(void *param)
5926 {
5927     if (AwtToolkit::IsMainThread()) {
5928         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5929         jobject self = (jobject)param;
5930         if (self != NULL) {
5931             PDATA pData = JNI_GET_PDATA(self);
5932             if (pData) {
5933                 AwtComponent *c = (AwtComponent *)pData;
5934                 if (::IsWindow(c->GetHWnd())) {
5935                     c->SendMessage(WM_AWT_END_VALIDATE);
5936                 }
5937             }
5938             env->DeleteGlobalRef(self);
5939         }
5940     } else {
5941         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_EndValidate, param);
5942     }
5943 }
5944 
5945 void AwtComponent::_UpdateWindow(void *param)
5946 {
5947     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5948     if (AwtToolkit::IsMainThread()) {
5949         jobject self = (jobject)param;
5950         AwtComponent *c = NULL;
5951         PDATA pData;
5952         JNI_CHECK_PEER_GOTO(self, ret);
5953         c = (AwtComponent *)pData;
5954         if (::IsWindow(c->GetHWnd())) {
5955             ::UpdateWindow(c->GetHWnd());
5956         }
5957 ret:
5958         env->DeleteGlobalRef(self);
5959     } else {
5960         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_UpdateWindow, param);
5961     }
5962 }
5963 
5964 jlong AwtComponent::_AddNativeDropTarget(void *param)
5965 {
5966     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5967 
5968     jobject self = (jobject)param;
5969 
5970     jlong result = 0;
5971     AwtComponent *c = NULL;
5972 
5973     PDATA pData;
5974     JNI_CHECK_PEER_GOTO(self, ret);
5975     c = (AwtComponent *)pData;
5976     if (::IsWindow(c->GetHWnd()))
5977     {
5978         result = (jlong)(c->CreateDropTarget(env));
5979     }
5980 ret:
5981     env->DeleteGlobalRef(self);
5982 
5983     return result;
5984 }
5985 
5986 void AwtComponent::_RemoveNativeDropTarget(void *param)
5987 {
5988     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5989 
5990     jobject self = (jobject)param;
5991 
5992     AwtComponent *c = NULL;
5993 
5994     PDATA pData;
5995     JNI_CHECK_PEER_GOTO(self, ret);
5996     c = (AwtComponent *)pData;
5997     if (::IsWindow(c->GetHWnd()))
5998     {
5999         c->DestroyDropTarget();
6000     }
6001 ret:
6002     env->DeleteGlobalRef(self);
6003 }
6004 
6005 jintArray AwtComponent::_CreatePrintedPixels(void *param)
6006 {
6007     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6008 
6009     CreatePrintedPixelsStruct *cpps = (CreatePrintedPixelsStruct *)param;
6010     jobject self = cpps->component;
6011 
6012     jintArray result = NULL;
6013     AwtComponent *c = NULL;
6014 
6015     PDATA pData;
6016     JNI_CHECK_PEER_GOTO(self, ret);
6017     c = (AwtComponent *)pData;
6018     if (::IsWindow(c->GetHWnd()))
6019     {
6020         result = (jintArray)c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)cpps, 0);
6021     }
6022 ret:
6023     env->DeleteGlobalRef(self);
6024 
6025     delete cpps;
6026     return result; // this reference is global
6027 }
6028 
6029 jboolean AwtComponent::_IsObscured(void *param)
6030 {
6031     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6032 
6033     jobject self = (jobject)param;
6034 
6035     jboolean result = JNI_FALSE;
6036     AwtComponent *c = NULL;
6037 
6038     PDATA pData;
6039     JNI_CHECK_PEER_GOTO(self, ret);
6040 
6041     c = (AwtComponent *)pData;
6042 
6043     if (::IsWindow(c->GetHWnd()))
6044     {
6045         HWND hWnd = c->GetHWnd();
6046         HDC hDC = ::GetDC(hWnd);
6047         RECT clipbox;
6048         int callresult = ::GetClipBox(hDC, &clipbox);
6049         switch(callresult) {
6050             case NULLREGION :
6051                 result = JNI_FALSE;
6052                 break;
6053             case SIMPLEREGION : {
6054                 RECT windowRect;
6055                 if (!::GetClientRect(hWnd, &windowRect)) {
6056                     result = JNI_TRUE;
6057                 } else {
6058                     result  = (jboolean)((clipbox.bottom != windowRect.bottom)
6059                         || (clipbox.left != windowRect.left)
6060                         || (clipbox.right != windowRect.right)
6061                         || (clipbox.top != windowRect.top));
6062                 }
6063                 break;
6064             }
6065             case COMPLEXREGION :
6066             default :
6067                 result = JNI_TRUE;
6068                 break;
6069         }
6070         ::ReleaseDC(hWnd, hDC);
6071     }
6072 ret:
6073     env->DeleteGlobalRef(self);
6074 
6075     return result;
6076 }
6077 
6078 jboolean AwtComponent::_NativeHandlesWheelScrolling(void *param)
6079 {
6080     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6081 
6082     jobject self = (jobject)param;
6083 
6084     jboolean result = JNI_FALSE;
6085     AwtComponent *c = NULL;
6086 
6087     PDATA pData;
6088     JNI_CHECK_PEER_GOTO(self, ret);
6089     c = (AwtComponent *)pData;
6090     if (::IsWindow(c->GetHWnd()))
6091     {
6092         result = (jboolean)c->InheritsNativeMouseWheelBehavior();
6093     }
6094 ret:
6095     env->DeleteGlobalRef(self);
6096 
6097     return result;
6098 }
6099 
6100 void AwtComponent::SetParent(void * param) {
6101     if (AwtToolkit::IsMainThread()) {
6102         AwtComponent** comps = (AwtComponent**)param;
6103         if ((comps[0] != NULL) && (comps[1] != NULL)) {
6104             HWND selfWnd = comps[0]->GetHWnd();
6105             HWND parentWnd = comps[1]->GetHWnd();
6106             if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) {
6107                 // Shouldn't trigger native focus change
6108                 // (only the proxy may be the native focus owner).
6109                 ::SetParent(selfWnd, parentWnd);
6110             }
6111         }
6112         delete[] comps;
6113     } else {
6114         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::SetParent, param);
6115     }
6116 }
6117 
6118 void AwtComponent::_SetRectangularShape(void *param)
6119 {
6120     if (!AwtToolkit::IsMainThread()) {
6121         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetRectangularShape, param);
6122     } else {
6123         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6124 
6125         SetRectangularShapeStruct *data = (SetRectangularShapeStruct *)param;
6126         jobject self = data->component;
6127         jint x1 = data->x1;
6128         jint x2 = data->x2;
6129         jint y1 = data->y1;
6130         jint y2 = data->y2;
6131         jobject region = data->region;
6132 
6133         AwtComponent *c = NULL;
6134 
6135         PDATA pData;
6136         JNI_CHECK_PEER_GOTO(self, ret);
6137 
6138         c = (AwtComponent *)pData;
6139         if (::IsWindow(c->GetHWnd())) {
6140             HRGN hRgn = NULL;
6141 
6142             // If all the params are zeros, the shape must be simply reset.
6143             // Otherwise, convert it into a region.
6144             if (region || x1 || x2 || y1 || y2) {
6145                 RECT_T rects[256];
6146                 RECT_T *pRect = rects;
6147 
6148                 const int numrects = RegionToYXBandedRectangles(env, x1, y1, x2, y2,
6149                         region, &pRect, sizeof(rects)/sizeof(rects[0]));
6150                 if (!pRect) {
6151                     // RegionToYXBandedRectangles doesn't use safe_Malloc(),
6152                     // so throw the exception explicitly
6153                     throw std::bad_alloc();
6154                 }
6155 
6156                 RGNDATA *pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc,
6157                         sizeof(RGNDATAHEADER), sizeof(RECT_T), numrects);
6158                 memcpy((BYTE*)pRgnData + sizeof(RGNDATAHEADER), pRect, sizeof(RECT_T) * numrects);
6159                 if (pRect != rects) {
6160                     free(pRect);
6161                 }
6162                 pRect = NULL;
6163 
6164                 RGNDATAHEADER *pRgnHdr = (RGNDATAHEADER *) pRgnData;
6165                 pRgnHdr->dwSize = sizeof(RGNDATAHEADER);
6166                 pRgnHdr->iType = RDH_RECTANGLES;
6167                 pRgnHdr->nRgnSize = 0;
6168                 pRgnHdr->rcBound.top = 0;
6169                 pRgnHdr->rcBound.left = 0;
6170                 pRgnHdr->rcBound.bottom = LONG(y2 - y1);
6171                 pRgnHdr->rcBound.right = LONG(x2 - x1);
6172                 pRgnHdr->nCount = numrects;
6173 
6174                 hRgn = ::ExtCreateRegion(NULL,
6175                         sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, pRgnData);
6176 
6177                 free(pRgnData);
6178             }
6179 
6180             ::SetWindowRgn(c->GetHWnd(), hRgn, TRUE);
6181         }
6182 
6183 ret:
6184         env->DeleteGlobalRef(self);
6185         if (region) {
6186             env->DeleteGlobalRef(region);
6187         }
6188 
6189         delete data;
6190     }
6191 }
6192 
6193 void AwtComponent::_SetZOrder(void *param) {
6194     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6195 
6196     SetZOrderStruct *data = (SetZOrderStruct *)param;
6197     jobject self = data->component;
6198     HWND above = HWND_TOP;
6199     if (data->above != 0) {
6200         above = reinterpret_cast<HWND>(data->above);
6201     }
6202 
6203     AwtComponent *c = NULL;
6204 
6205     PDATA pData;
6206     JNI_CHECK_PEER_GOTO(self, ret);
6207 
6208     c = (AwtComponent *)pData;
6209     if (::IsWindow(c->GetHWnd())) {
6210         ::SetWindowPos(c->GetHWnd(), above, 0, 0, 0, 0,
6211                        SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS);
6212     }
6213 
6214 ret:
6215     env->DeleteGlobalRef(self);
6216 
6217     delete data;
6218 }
6219 
6220 void AwtComponent::PostUngrabEvent() {
6221     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6222     jobject target = GetTarget(env);
6223     jobject event = JNU_NewObjectByName(env, "sun/awt/UngrabEvent", "(Ljava/awt/Component;)V",
6224                                         target);
6225     if (safe_ExceptionOccurred(env)) {
6226         env->ExceptionDescribe();
6227         env->ExceptionClear();
6228     }
6229     env->DeleteLocalRef(target);
6230     if (event != NULL) {
6231         SendEvent(event);
6232         env->DeleteLocalRef(event);
6233     }
6234 }
6235 
6236 void AwtComponent::SetFocusedWindow(HWND window)
6237 {
6238     HWND old = sm_focusedWindow;
6239     sm_focusedWindow = window;
6240 
6241     AwtWindow::FocusedWindowChanged(old, window);
6242 }
6243 
6244 /************************************************************************
6245  * Component native methods
6246  */
6247 
6248 extern "C" {
6249 
6250 /**
6251  * This method is called from the WGL pipeline when it needs to retrieve
6252  * the HWND associated with a ComponentPeer's C++ level object.
6253  */
6254 HWND
6255 AwtComponent_GetHWnd(JNIEnv *env, jlong pData)
6256 {
6257     AwtComponent *p = (AwtComponent *)jlong_to_ptr(pData);
6258     if (p == NULL) {
6259         return (HWND)0;
6260     }
6261     return p->GetHWnd();
6262 }
6263 
6264 static void _GetInsets(void* param)
6265 {
6266     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6267 
6268     GetInsetsStruct *gis = (GetInsetsStruct *)param;
6269     jobject self = gis->window;
6270 
6271     gis->insets->left = gis->insets->top =
6272         gis->insets->right = gis->insets->bottom = 0;
6273 
6274     PDATA pData;
6275     JNI_CHECK_PEER_GOTO(self, ret);
6276     AwtComponent *component = (AwtComponent *)pData;
6277 
6278     component->GetInsets(gis->insets);
6279 
6280   ret:
6281     env->DeleteGlobalRef(self);
6282     delete gis;
6283 }
6284 
6285 /**
6286  * This method is called from the WGL pipeline when it needs to retrieve
6287  * the insets associated with a ComponentPeer's C++ level object.
6288  */
6289 void AwtComponent_GetInsets(JNIEnv *env, jobject peer, RECT *insets)
6290 {
6291     TRY;
6292 
6293     GetInsetsStruct *gis = new GetInsetsStruct;
6294     gis->window = env->NewGlobalRef(peer);
6295     gis->insets = insets;
6296 
6297     AwtToolkit::GetInstance().InvokeFunction(_GetInsets, gis);
6298     // global refs and mds are deleted in _UpdateWindow
6299 
6300     CATCH_BAD_ALLOC;
6301 
6302 }
6303 
6304 JNIEXPORT void JNICALL
6305 Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls)
6306 {
6307     TRY;
6308     jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent");
6309     jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I");
6310     jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID);
6311     jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE);
6312 
6313     jsize len = env->GetArrayLength(obj);
6314     AwtComponent::masks = SAFE_SIZE_NEW_ARRAY(jint, len);
6315     for (int i = 0; i < len; i++) {
6316         AwtComponent::masks[i] = tmp[i];
6317     }
6318     env->ReleaseIntArrayElements(obj, tmp, 0);
6319     env->DeleteLocalRef(obj);
6320 
6321     /* class ids */
6322     jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer");
6323 
6324     DASSERT(peerCls);
6325 
6326     /* field ids */
6327     AwtComponent::peerID =
6328       env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;");
6329     AwtComponent::xID = env->GetFieldID(cls, "x", "I");
6330     AwtComponent::yID = env->GetFieldID(cls, "y", "I");
6331     AwtComponent::heightID = env->GetFieldID(cls, "height", "I");
6332     AwtComponent::widthID = env->GetFieldID(cls, "width", "I");
6333     AwtComponent::visibleID = env->GetFieldID(cls, "visible", "Z");
6334     AwtComponent::backgroundID =
6335         env->GetFieldID(cls, "background", "Ljava/awt/Color;");
6336     AwtComponent::foregroundID =
6337         env->GetFieldID(cls, "foreground", "Ljava/awt/Color;");
6338     AwtComponent::enabledID = env->GetFieldID(cls, "enabled", "Z");
6339     AwtComponent::parentID = env->GetFieldID(cls, "parent", "Ljava/awt/Container;");
6340     AwtComponent::graphicsConfigID =
6341      env->GetFieldID(cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;");
6342     AwtComponent::focusableID = env->GetFieldID(cls, "focusable", "Z");
6343 
6344     AwtComponent::appContextID = env->GetFieldID(cls, "appContext",
6345                                                  "Lsun/awt/AppContext;");
6346 
6347     AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig",
6348                                         "Lsun/awt/Win32GraphicsConfig;");
6349 
6350     AwtComponent::hwndID = env->GetFieldID(peerCls, "hwnd", "J");
6351 
6352     AwtComponent::cursorID = env->GetFieldID(cls, "cursor", "Ljava/awt/Cursor;");
6353 
6354     /* method ids */
6355     AwtComponent::getFontMID =
6356         env->GetMethodID(cls, "getFont_NoClientCode", "()Ljava/awt/Font;");
6357     AwtComponent::getToolkitMID =
6358         env->GetMethodID(cls, "getToolkitImpl", "()Ljava/awt/Toolkit;");
6359     AwtComponent::isEnabledMID = env->GetMethodID(cls, "isEnabledImpl", "()Z");
6360     AwtComponent::getLocationOnScreenMID =
6361         env->GetMethodID(cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;");
6362     AwtComponent::replaceSurfaceDataMID =
6363         env->GetMethodID(peerCls, "replaceSurfaceData", "()V");
6364     AwtComponent::replaceSurfaceDataLaterMID =
6365         env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V");
6366     AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
6367 
6368     DASSERT(AwtComponent::xID);
6369     DASSERT(AwtComponent::yID);
6370     DASSERT(AwtComponent::heightID);
6371     DASSERT(AwtComponent::widthID);
6372     DASSERT(AwtComponent::visibleID);
6373     DASSERT(AwtComponent::backgroundID);
6374     DASSERT(AwtComponent::foregroundID);
6375     DASSERT(AwtComponent::enabledID);
6376     DASSERT(AwtComponent::parentID);
6377     DASSERT(AwtComponent::hwndID);
6378 
6379     DASSERT(AwtComponent::getFontMID);
6380     DASSERT(AwtComponent::getToolkitMID);
6381     DASSERT(AwtComponent::isEnabledMID);
6382     DASSERT(AwtComponent::getLocationOnScreenMID);
6383     DASSERT(AwtComponent::replaceSurfaceDataMID);
6384     DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
6385     DASSERT(AwtComponent::disposeLaterMID);
6386 
6387 
6388     CATCH_BAD_ALLOC;
6389 }
6390 
6391 } /* extern "C" */
6392 
6393 
6394 /************************************************************************
6395  * ComponentPeer native methods
6396  */
6397 
6398 extern "C" {
6399 
6400 /*
6401  * Class:     sun_awt_windows_WComponentPeer
6402  * Method:    pShow
6403  * Signature: ()V
6404  */
6405 JNIEXPORT void JNICALL
6406 Java_sun_awt_windows_WComponentPeer_pShow(JNIEnv *env, jobject self)
6407 {
6408     TRY;
6409 
6410     jobject selfGlobalRef = env->NewGlobalRef(self);
6411 
6412     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Show, (void *)selfGlobalRef);
6413     // selfGlobalRef is deleted in _Show
6414 
6415     CATCH_BAD_ALLOC;
6416 }
6417 
6418 /*
6419  * Class:     sun_awt_windows_WComponentPeer
6420  * Method:    hide
6421  * Signature: ()V
6422  */
6423 JNIEXPORT void JNICALL
6424 Java_sun_awt_windows_WComponentPeer_hide(JNIEnv *env, jobject self)
6425 {
6426     TRY;
6427 
6428     jobject selfGlobalRef = env->NewGlobalRef(self);
6429 
6430     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Hide, (void *)selfGlobalRef);
6431     // selfGlobalRef is deleted in _Hide
6432 
6433     CATCH_BAD_ALLOC;
6434 }
6435 
6436 /*
6437  * Class:     sun_awt_windows_WComponentPeer
6438  * Method:    enable
6439  * Signature: ()V
6440  */
6441 JNIEXPORT void JNICALL
6442 Java_sun_awt_windows_WComponentPeer_enable(JNIEnv *env, jobject self)
6443 {
6444     TRY;
6445 
6446     jobject selfGlobalRef = env->NewGlobalRef(self);
6447 
6448     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Enable, (void *)selfGlobalRef);
6449     // selfGlobalRef is deleted in _Enable
6450 
6451     CATCH_BAD_ALLOC;
6452 }
6453 
6454 /*
6455  * Class:     sun_awt_windows_WComponentPeer
6456  * Method:    disable
6457  * Signature: ()V
6458  */
6459 JNIEXPORT void JNICALL
6460 Java_sun_awt_windows_WComponentPeer_disable(JNIEnv *env, jobject self)
6461 {
6462     TRY;
6463 
6464     jobject selfGlobalRef = env->NewGlobalRef(self);
6465 
6466     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Disable, (void *)selfGlobalRef);
6467     // selfGlobalRef is deleted in _Disable
6468 
6469     CATCH_BAD_ALLOC;
6470 }
6471 
6472 /*
6473  * Class:     sun_awt_windows_WComponentPeer
6474  * Method:    getLocationOnScreen
6475  * Signature: ()Ljava/awt/Point;
6476  */
6477 JNIEXPORT jobject JNICALL
6478 Java_sun_awt_windows_WComponentPeer_getLocationOnScreen(JNIEnv *env, jobject self)
6479 {
6480     TRY;
6481 
6482     jobject selfGlobalRef = env->NewGlobalRef(self);
6483 
6484     jobject resultGlobalRef = (jobject)AwtToolkit::GetInstance().SyncCall(
6485         (void*(*)(void*))AwtComponent::_GetLocationOnScreen, (void *)selfGlobalRef);
6486     // selfGlobalRef is deleted in _GetLocationOnScreen
6487     if (resultGlobalRef != NULL)
6488     {
6489         jobject resultLocalRef = env->NewLocalRef(resultGlobalRef);
6490         env->DeleteGlobalRef(resultGlobalRef);
6491         return resultLocalRef;
6492     }
6493 
6494     return NULL;
6495 
6496     CATCH_BAD_ALLOC_RET(NULL);
6497 }
6498 
6499 /*
6500  * Class:     sun_awt_windows_WComponentPeer
6501  * Method:    reshape
6502  * Signature: (IIII)V
6503  */
6504 JNIEXPORT void JNICALL
6505 Java_sun_awt_windows_WComponentPeer_reshape(JNIEnv *env, jobject self,
6506                                             jint x, jint y, jint w, jint h)
6507 {
6508     TRY;
6509 
6510     ReshapeStruct *rs = new ReshapeStruct;
6511     rs->component = env->NewGlobalRef(self);
6512     rs->x = x;
6513     rs->y = y;
6514     rs->w = w;
6515     rs->h = h;
6516 
6517     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Reshape, rs);
6518     // global ref and rs are deleted in _Reshape
6519 
6520     CATCH_BAD_ALLOC;
6521 }
6522 
6523 /*
6524  * Class:     sun_awt_windows_WComponentPeer
6525  * Method:    reshape
6526  * Signature: (IIII)V
6527  */
6528 JNIEXPORT void JNICALL
6529 Java_sun_awt_windows_WComponentPeer_reshapeNoCheck(JNIEnv *env, jobject self,
6530                                             jint x, jint y, jint w, jint h)
6531 {
6532     TRY;
6533 
6534     ReshapeStruct *rs = new ReshapeStruct;
6535     rs->component = env->NewGlobalRef(self);
6536     rs->x = x;
6537     rs->y = y;
6538     rs->w = w;
6539     rs->h = h;
6540 
6541     AwtToolkit::GetInstance().SyncCall(AwtComponent::_ReshapeNoCheck, rs);
6542     // global ref and rs are deleted in _ReshapeNoCheck
6543 
6544     CATCH_BAD_ALLOC;
6545 }
6546 
6547 
6548 /*
6549  * Class:     sun_awt_windows_WComponentPeer
6550  * Method:    nativeHandleEvent
6551  * Signature: (Ljava/awt/AWTEvent;)V
6552  */
6553 JNIEXPORT void JNICALL
6554 Java_sun_awt_windows_WComponentPeer_nativeHandleEvent(JNIEnv *env,
6555                                                       jobject self,
6556                                                       jobject event)
6557 {
6558     TRY;
6559 
6560     jobject selfGlobalRef = env->NewGlobalRef(self);
6561     jobject eventGlobalRef = env->NewGlobalRef(event);
6562 
6563     NativeHandleEventStruct *nhes = new NativeHandleEventStruct;
6564     nhes->component = selfGlobalRef;
6565     nhes->event = eventGlobalRef;
6566 
6567     AwtToolkit::GetInstance().SyncCall(AwtComponent::_NativeHandleEvent, nhes);
6568     // global refs and nhes are deleted in _NativeHandleEvent
6569 
6570     CATCH_BAD_ALLOC;
6571 }
6572 
6573 /*
6574  * Class:     sun_awt_windows_WComponentPeer
6575  * Method:    _dispose
6576  * Signature: ()V
6577  */
6578 JNIEXPORT void JNICALL
6579 Java_sun_awt_windows_WComponentPeer__1dispose(JNIEnv *env, jobject self)
6580 {
6581     TRY_NO_HANG;
6582 
6583     AwtObject::_Dispose(self);
6584 
6585     CATCH_BAD_ALLOC;
6586 }
6587 
6588 /*
6589  * Class:     sun_awt_windows_WComponentPeer
6590  * Method:    _setForeground
6591  * Signature: (I)V
6592  */
6593 JNIEXPORT void JNICALL
6594 Java_sun_awt_windows_WComponentPeer__1setForeground(JNIEnv *env, jobject self,
6595                                                     jint rgb)
6596 {
6597     TRY;
6598 
6599     jobject selfGlobalRef = env->NewGlobalRef(self);
6600 
6601     SetColorStruct *scs = new SetColorStruct;
6602     scs->component = selfGlobalRef;
6603     scs->rgb = rgb;
6604 
6605     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetForeground, scs);
6606     // selfGlobalRef and scs are deleted in _SetForeground()
6607 
6608     CATCH_BAD_ALLOC;
6609 }
6610 
6611 /*
6612  * Class:     sun_awt_windows_WComponentPeer
6613  * Method:    _setBackground
6614  * Signature: (I)V
6615  */
6616 JNIEXPORT void JNICALL
6617 Java_sun_awt_windows_WComponentPeer__1setBackground(JNIEnv *env, jobject self,
6618                                                     jint rgb)
6619 {
6620     TRY;
6621 
6622     jobject selfGlobalRef = env->NewGlobalRef(self);
6623 
6624     SetColorStruct *scs = new SetColorStruct;
6625     scs->component = selfGlobalRef;
6626     scs->rgb = rgb;
6627 
6628     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetBackground, scs);
6629     // selfGlobalRef and scs are deleted in _SetBackground()
6630 
6631     CATCH_BAD_ALLOC;
6632 }
6633 
6634 /*
6635  * Class:     sun_awt_windows_WComponentPeer
6636  * Method:    _setFont
6637  * Signature: (Ljava/awt/Font;)V
6638  */
6639 JNIEXPORT void JNICALL
6640 Java_sun_awt_windows_WComponentPeer__1setFont(JNIEnv *env, jobject self,
6641                         jobject font)
6642 {
6643     TRY;
6644 
6645     jobject selfGlobalRef = env->NewGlobalRef(self);
6646     jobject fontGlobalRef = env->NewGlobalRef(font);
6647 
6648     SetFontStruct *sfs = new SetFontStruct;
6649     sfs->component = selfGlobalRef;
6650     sfs->font = fontGlobalRef;
6651 
6652     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetFont, sfs);
6653     // global refs and sfs are deleted in _SetFont()
6654 
6655     CATCH_BAD_ALLOC;
6656 }
6657 
6658 /*
6659  * Class:     sun_awt_windows_WComponentPeer
6660  * Method:    focusGained
6661  * Signature: (Z)
6662  */
6663 JNIEXPORT void JNICALL Java_sun_awt_windows_WComponentPeer_setFocus
6664     (JNIEnv *env, jobject self, jboolean doSetFocus)
6665 {
6666     TRY;
6667 
6668     jobject selfGlobalRef = env->NewGlobalRef(self);
6669 
6670     SetFocusStruct *sfs = new SetFocusStruct;
6671     sfs->component = selfGlobalRef;
6672     sfs->doSetFocus = doSetFocus;
6673 
6674     AwtToolkit::GetInstance().SyncCall(
6675         (void*(*)(void*))AwtComponent::_SetFocus, sfs);
6676     // global refs and self are deleted in _SetFocus
6677 
6678     CATCH_BAD_ALLOC;
6679 }
6680 
6681 /*
6682  * Class:     sun_awt_windows_WComponentPeer
6683  * Method:    start
6684  * Signature: ()V
6685  */
6686 JNIEXPORT void JNICALL
6687 Java_sun_awt_windows_WComponentPeer_start(JNIEnv *env, jobject self)
6688 {
6689     TRY;
6690 
6691     jobject selfGlobalRef = env->NewGlobalRef(self);
6692 
6693     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Start, (void *)selfGlobalRef);
6694     // selfGlobalRef is deleted in _Start
6695 
6696     CATCH_BAD_ALLOC;
6697 }
6698 
6699 /*
6700  * Class:     sun_awt_windows_WComponentPeer
6701  * Method:    beginValidate
6702  * Signature: ()V
6703  */
6704 JNIEXPORT void JNICALL
6705 Java_sun_awt_windows_WComponentPeer_beginValidate(JNIEnv *env, jobject self)
6706 {
6707     TRY;
6708 
6709     jobject selfGlobalRef = env->NewGlobalRef(self);
6710 
6711     AwtToolkit::GetInstance().SyncCall(AwtComponent::_BeginValidate, (void *)selfGlobalRef);
6712     // selfGlobalRef is deleted in _BeginValidate
6713 
6714     CATCH_BAD_ALLOC;
6715 }
6716 
6717 /*
6718  * Class:     sun_awt_windows_WComponentPeer
6719  * Method:    endValidate
6720  * Signature: ()V
6721  */
6722 JNIEXPORT void JNICALL
6723 Java_sun_awt_windows_WComponentPeer_endValidate(JNIEnv *env, jobject self)
6724 {
6725     TRY;
6726 
6727     jobject selfGlobalRef = env->NewGlobalRef(self);
6728 
6729     AwtToolkit::GetInstance().SyncCall(AwtComponent::_EndValidate, (void *)selfGlobalRef);
6730     // selfGlobalRef is deleted in _EndValidate
6731 
6732     CATCH_BAD_ALLOC;
6733 }
6734 
6735 JNIEXPORT void JNICALL
6736 Java_sun_awt_windows_WComponentPeer_updateWindow(JNIEnv *env, jobject self)
6737 {
6738     TRY;
6739 
6740     jobject selfGlobalRef = env->NewGlobalRef(self);
6741 
6742     AwtToolkit::GetInstance().SyncCall(AwtComponent::_UpdateWindow, (void *)selfGlobalRef);
6743     // selfGlobalRef is deleted in _UpdateWindow
6744 
6745     CATCH_BAD_ALLOC;
6746 }
6747 
6748 /*
6749  * Class:     sun_awt_windows_WComponentPeer
6750  * Method:    addNativeDropTarget
6751  * Signature: ()L
6752  */
6753 
6754 JNIEXPORT jlong JNICALL
6755 Java_sun_awt_windows_WComponentPeer_addNativeDropTarget(JNIEnv *env,
6756                                                         jobject self)
6757 {
6758     TRY;
6759 
6760     jobject selfGlobalRef = env->NewGlobalRef(self);
6761 
6762     return ptr_to_jlong(AwtToolkit::GetInstance().SyncCall(
6763         (void*(*)(void*))AwtComponent::_AddNativeDropTarget,
6764         (void *)selfGlobalRef));
6765     // selfGlobalRef is deleted in _AddNativeDropTarget
6766 
6767     CATCH_BAD_ALLOC_RET(0);
6768 }
6769 
6770 /*
6771  * Class:     sun_awt_windows_WComponentPeer
6772  * Method:    removeNativeDropTarget
6773  * Signature: ()V
6774  */
6775 
6776 JNIEXPORT void JNICALL
6777 Java_sun_awt_windows_WComponentPeer_removeNativeDropTarget(JNIEnv *env,
6778                                                            jobject self)
6779 {
6780     TRY;
6781 
6782     jobject selfGlobalRef = env->NewGlobalRef(self);
6783 
6784     AwtToolkit::GetInstance().SyncCall(
6785         AwtComponent::_RemoveNativeDropTarget, (void *)selfGlobalRef);
6786     // selfGlobalRef is deleted in _RemoveNativeDropTarget
6787 
6788     CATCH_BAD_ALLOC;
6789 }
6790 
6791 /*
6792  * Class:     sun_awt_windows_WComponentPeer
6793  * Method:    getTargetGC
6794  * Signature: ()Ljava/awt/GraphicsConfiguration;
6795  */
6796 JNIEXPORT jobject JNICALL
6797 Java_sun_awt_windows_WComponentPeer_getTargetGC(JNIEnv* env, jobject theThis)
6798 {
6799     TRY;
6800 
6801     jobject targetObj;
6802     jobject gc = 0;
6803 
6804     targetObj = env->GetObjectField(theThis, AwtObject::targetID);
6805     DASSERT(targetObj);
6806 
6807     gc = env->GetObjectField(targetObj, AwtComponent::graphicsConfigID);
6808     return gc;
6809 
6810     CATCH_BAD_ALLOC_RET(NULL);
6811 }
6812 
6813 /*
6814  * Class:     sun_awt_windows_WComponentPeer
6815  * Method:    createPrintedPixels
6816  * Signature: (IIIIII)I[
6817  */
6818 JNIEXPORT jintArray JNICALL
6819 Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env,
6820     jobject self, jint srcX, jint srcY, jint srcW, jint srcH, jint alpha)
6821 {
6822     TRY;
6823 
6824     jobject selfGlobalRef = env->NewGlobalRef(self);
6825 
6826     CreatePrintedPixelsStruct *cpps = new CreatePrintedPixelsStruct;
6827     cpps->component = selfGlobalRef;
6828     cpps->srcx = srcX;
6829     cpps->srcy = srcY;
6830     cpps->srcw = srcW;
6831     cpps->srch = srcH;
6832     cpps->alpha = alpha;
6833 
6834     jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall(
6835         (void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps);
6836     // selfGlobalRef and cpps are deleted in _CreatePrintedPixels
6837     if (globalRef != NULL)
6838     {
6839         jintArray localRef = (jintArray)env->NewLocalRef(globalRef);
6840         env->DeleteGlobalRef(globalRef);
6841         return localRef;
6842     }
6843     else
6844     {
6845         return NULL;
6846     }
6847 
6848     CATCH_BAD_ALLOC_RET(NULL);
6849 }
6850 
6851 /*
6852  * Class:     sun_awt_windows_WComponentPeer
6853  * Method:    nativeHandlesWheelScrolling
6854  * Signature: ()Z
6855  */
6856 JNIEXPORT jboolean JNICALL
6857 Java_sun_awt_windows_WComponentPeer_nativeHandlesWheelScrolling (JNIEnv* env,
6858     jobject self)
6859 {
6860     TRY;
6861 
6862     return (jboolean)AwtToolkit::GetInstance().SyncCall(
6863         (void *(*)(void *))AwtComponent::_NativeHandlesWheelScrolling,
6864         env->NewGlobalRef(self));
6865     // global ref is deleted in _NativeHandlesWheelScrolling
6866 
6867     CATCH_BAD_ALLOC_RET(NULL);
6868 }
6869 
6870 /*
6871  * Class:     sun_awt_windows_WComponentPeer
6872  * Method:    isObscured
6873  * Signature: ()Z
6874  */
6875 JNIEXPORT jboolean JNICALL
6876 Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv* env,
6877     jobject self)
6878 {
6879     TRY;
6880 
6881     jobject selfGlobalRef = env->NewGlobalRef(self);
6882 
6883     return (jboolean)AwtToolkit::GetInstance().SyncCall(
6884         (void*(*)(void*))AwtComponent::_IsObscured,
6885         (void *)selfGlobalRef);
6886     // selfGlobalRef is deleted in _IsObscured
6887 
6888     CATCH_BAD_ALLOC_RET(NULL);
6889 }
6890 
6891 JNIEXPORT void JNICALL
6892 Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv* env, jobject self, jobject parent) {
6893     TRY;
6894 
6895     typedef AwtComponent* PComponent;
6896     AwtComponent** comps = new PComponent[2];
6897     AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(self);
6898     AwtComponent* parentComp = (AwtComponent*)JNI_GET_PDATA(parent);
6899     comps[0] = comp;
6900     comps[1] = parentComp;
6901 
6902     AwtToolkit::GetInstance().SyncCall(AwtComponent::SetParent, comps);
6903     // comps is deleted in SetParent
6904 
6905     CATCH_BAD_ALLOC;
6906 }
6907 
6908 JNIEXPORT void JNICALL
6909 Java_sun_awt_windows_WComponentPeer_setRectangularShape(JNIEnv* env, jobject self,
6910         jint x1, jint y1, jint x2, jint y2, jobject region)
6911 {
6912     TRY;
6913 
6914     SetRectangularShapeStruct * data = new SetRectangularShapeStruct;
6915     data->component = env->NewGlobalRef(self);
6916     data->x1 = x1;
6917     data->x2 = x2;
6918     data->y1 = y1;
6919     data->y2 = y2;
6920     if (region) {
6921         data->region = env->NewGlobalRef(region);
6922     } else {
6923         data->region = NULL;
6924     }
6925 
6926     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetRectangularShape, data);
6927     // global refs and data are deleted in _SetRectangularShape
6928 
6929     CATCH_BAD_ALLOC;
6930 }
6931 
6932 JNIEXPORT void JNICALL
6933 Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv* env, jobject self, jlong above)
6934 {
6935     TRY;
6936 
6937     SetZOrderStruct * data = new SetZOrderStruct;
6938     data->component = env->NewGlobalRef(self);
6939     data->above = above;
6940 
6941     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetZOrder, data);
6942     // global refs and data are deleted in _SetLower
6943 
6944     CATCH_BAD_ALLOC;
6945 }
6946 
6947 } /* extern "C" */
6948 
6949 
6950 /************************************************************************
6951  * Diagnostic routines
6952  */
6953 
6954 #ifdef DEBUG
6955 
6956 void AwtComponent::VerifyState()
6957 {
6958     if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) {
6959         return;
6960     }
6961 
6962     if (m_callbacksEnabled == FALSE) {
6963         /* Component is not fully setup yet. */
6964         return;
6965     }
6966 
6967     /* Get target bounds. */
6968     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6969     if (env->PushLocalFrame(10) < 0)
6970         return;
6971 
6972     jobject target = GetTarget(env);
6973 
6974     jint x = env->GetIntField(target, AwtComponent::xID);
6975     jint y = env->GetIntField(target, AwtComponent::yID);
6976     jint width = env->GetIntField(target, AwtComponent::widthID);
6977     jint height = env->GetIntField(target, AwtComponent::heightID);
6978 
6979     /* Convert target origin to absolute coordinates */
6980     while (TRUE) {
6981 
6982         jobject parent = env->GetObjectField(target, AwtComponent::parentID);
6983         if (parent == NULL) {
6984             break;
6985         }
6986         x += env->GetIntField(parent, AwtComponent::xID);
6987         y += env->GetIntField(parent, AwtComponent::yID);
6988 
6989         /* If this component has insets, factor them in, but ignore
6990          * top-level windows.
6991          */
6992         jobject parent2 = env->GetObjectField(parent, AwtComponent::parentID);
6993         if (parent2 != NULL) {
6994             jobject peer = GetPeerForTarget(env, parent);
6995             if (peer != NULL &&
6996                 JNU_IsInstanceOfByName(env, peer,
6997                                        "sun/awt/windows/WPanelPeer") > 0) {
6998                 jobject insets =
6999                     JNU_CallMethodByName(env, NULL, peer,"insets",
7000                                          "()Ljava/awt/Insets;").l;
7001                 x += (env)->GetIntField(insets, AwtInsets::leftID);
7002                 y += (env)->GetIntField(insets, AwtInsets::topID);
7003             }
7004         }
7005         env->DeleteLocalRef(target);
7006         target = parent;
7007     }
7008 
7009     // Test whether component's bounds match the native window's
7010     RECT rect;
7011     VERIFY(::GetWindowRect(GetHWnd(), &rect));
7012 #if 0
7013     DASSERT( (x == rect.left) &&
7014             (y == rect.top) &&
7015             (width == (rect.right-rect.left)) &&
7016             (height == (rect.bottom-rect.top)) );
7017 #else
7018     BOOL fSizeValid = ( (x == rect.left) &&
7019             (y == rect.top) &&
7020             (width == (rect.right-rect.left)) &&
7021             (height == (rect.bottom-rect.top)) );
7022 #endif
7023 
7024     // See if visible state matches
7025     BOOL wndVisible = ::IsWindowVisible(GetHWnd());
7026     jboolean targetVisible;
7027     // To avoid possibly running client code on the toolkit thread, don't
7028     // do the following check if we're running on the toolkit thread.
7029     if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7030         targetVisible = JNU_CallMethodByName(env, NULL, GetTarget(env),
7031                                                   "isShowing", "()Z").z;
7032         DASSERT(!safe_ExceptionOccurred(env));
7033     } else {
7034         targetVisible = wndVisible ? 1 : 0;
7035     }
7036 #if 0
7037     DASSERT( (targetVisible && wndVisible) ||
7038             (!targetVisible && !wndVisible) );
7039 #else
7040     BOOL fVisibleValid = ( (targetVisible && wndVisible) ||
7041             (!targetVisible && !wndVisible) );
7042 #endif
7043 
7044     // Check enabled state
7045     BOOL wndEnabled = ::IsWindowEnabled(GetHWnd());
7046     jboolean enabled = (jboolean)env->GetBooleanField(target,
7047                                                       AwtComponent::enabledID);
7048 #if 0
7049     DASSERT( (enabled && wndEnabled) ||
7050             (!enabled && !wndEnabled) );
7051 #else
7052     BOOL fEnabledValid = ((enabled && wndEnabled) ||
7053                           (!(enabled && !wndEnabled) ));
7054 
7055     if (!fSizeValid || !fVisibleValid || !fEnabledValid) {
7056         printf("AwtComponent::ValidateState() failed:\n");
7057         // To avoid possibly running client code on the toolkit thread, don't
7058         // do the following call if we're running on the toolkit thread.
7059         if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7060             jstring targetStr =
7061                 (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),
7062                                               "getName",
7063                                               "()Ljava/lang/String;").l;
7064             DASSERT(!safe_ExceptionOccurred(env));
7065             LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
7066             printf("\t%S\n", targetStrW);
7067             JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
7068         }
7069         printf("\twas:       [%d,%d,%dx%d]\n", x, y, width, height);
7070         if (!fSizeValid) {
7071             printf("\tshould be: [%d,%d,%dx%d]\n", rect.left, rect.top,
7072                    rect.right-rect.left, rect.bottom-rect.top);
7073         }
7074         if (!fVisibleValid) {
7075             printf("\tshould be: %s\n",
7076                    (targetVisible) ? "visible" : "hidden");
7077         }
7078         if (!fEnabledValid) {
7079             printf("\tshould be: %s\n",
7080                    enabled ? "enabled" : "disabled");
7081         }
7082     }
7083 #endif
7084     env->PopLocalFrame(0);
7085 }
7086 #endif //DEBUG
7087 
7088 // Methods for globally managed DC list
7089 
7090 /**
7091  * Add a new DC to the DC list for this component.
7092  */
7093 void DCList::AddDC(HDC hDC, HWND hWnd)
7094 {
7095     DCItem *newItem = new DCItem;
7096     newItem->hDC = hDC;
7097     newItem->hWnd = hWnd;
7098     AddDCItem(newItem);
7099 }
7100 
7101 void DCList::AddDCItem(DCItem *newItem)
7102 {
7103     listLock.Enter();
7104     newItem->next = head;
7105     head = newItem;
7106     listLock.Leave();
7107 }
7108 
7109 /**
7110  * Given a DC, remove it from the DC list and return
7111  * TRUE if it exists on the current list.  Otherwise
7112  * return FALSE.
7113  * A DC may not exist on the list because it has already
7114  * been released elsewhere (for example, the window
7115  * destruction process may release a DC while a rendering
7116  * thread may also want to release a DC when it notices that
7117  * its DC is obsolete for the current window).
7118  */
7119 DCItem *DCList::RemoveDC(HDC hDC)
7120 {
7121     listLock.Enter();
7122     DCItem **prevPtrPtr = &head;
7123     DCItem *listPtr = head;
7124     while (listPtr) {
7125         DCItem *nextPtr = listPtr->next;
7126         if (listPtr->hDC == hDC) {
7127             *prevPtrPtr = nextPtr;
7128             break;
7129         }
7130         prevPtrPtr = &listPtr->next;
7131         listPtr = nextPtr;
7132     }
7133     listLock.Leave();
7134     return listPtr;
7135 }
7136 
7137 /**
7138  * Remove all DCs from the DC list which are associated with
7139  * the same window as hWnd.  Return the list of those
7140  * DC's to the caller (which will then probably want to
7141  * call ReleaseDC() for the returned DCs).
7142  */
7143 DCItem *DCList::RemoveAllDCs(HWND hWnd)
7144 {
7145     listLock.Enter();
7146     DCItem **prevPtrPtr = &head;
7147     DCItem *listPtr = head;
7148     DCItem *newListPtr = NULL;
7149     BOOL ret = FALSE;
7150     while (listPtr) {
7151         DCItem *nextPtr = listPtr->next;
7152         if (listPtr->hWnd == hWnd) {
7153             *prevPtrPtr = nextPtr;
7154             listPtr->next = newListPtr;
7155             newListPtr = listPtr;
7156         } else {
7157             prevPtrPtr = &listPtr->next;
7158         }
7159         listPtr = nextPtr;
7160     }
7161     listLock.Leave();
7162     return newListPtr;
7163 }
7164 
7165 
7166 /**
7167  * Realize palettes of all existing HDC objects
7168  */
7169 void DCList::RealizePalettes(int screen)
7170 {
7171     listLock.Enter();
7172     DCItem *listPtr = head;
7173     while (listPtr) {
7174         AwtWin32GraphicsDevice::RealizePalette(listPtr->hDC, screen);
7175         listPtr = listPtr->next;
7176     }
7177     listLock.Leave();
7178 }
7179 
7180 void MoveDCToPassiveList(HDC hDC) {
7181     DCItem *removedDC;
7182     if ((removedDC = activeDCList.RemoveDC(hDC)) != NULL) {
7183         passiveDCList.AddDCItem(removedDC);
7184     }
7185 }
7186 
7187 void ReleaseDCList(HWND hwnd, DCList &list) {
7188     DCItem *removedDCs = list.RemoveAllDCs(hwnd);
7189     while (removedDCs) {
7190         DCItem *tmpDCList = removedDCs;
7191         DASSERT(::GetObjectType(tmpDCList->hDC) == OBJ_DC);
7192         int retValue = ::ReleaseDC(tmpDCList->hWnd, tmpDCList->hDC);
7193         VERIFY(retValue != 0);
7194         if (retValue != 0) {
7195             // Valid ReleaseDC call; need to decrement GDI object counter
7196             AwtGDIObject::Decrement();
7197         }
7198         removedDCs = removedDCs->next;
7199         delete tmpDCList;
7200     }
7201 }
7202