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