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