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