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