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