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