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