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