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