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