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