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