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