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