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 }
3853 
3854 void AwtComponent::SetCandidateWindow(int iCandType, int x, int y)
3855 {
3856     HWND hwnd = ImmGetHWnd();
3857     HIMC hIMC = ImmGetContext(hwnd);
3858     if (hIMC) {
3859         CANDIDATEFORM cf;
3860         cf.dwStyle = CFS_POINT;
3861         ImmGetCandidateWindow(hIMC, 0, &cf);
3862         if (x != cf.ptCurrentPos.x || y != cf.ptCurrentPos.y) {
3863             cf.dwIndex = iCandType;
3864             cf.dwStyle = CFS_POINT;
3865             cf.ptCurrentPos.x = x;
3866             cf.ptCurrentPos.y = y;
3867             cf.rcArea.left = cf.rcArea.top = cf.rcArea.right = cf.rcArea.bottom = 0;
3868             ImmSetCandidateWindow(hIMC, &cf);
3869         }
3870         COMPOSITIONFORM cfr;
3871         cfr.dwStyle = CFS_POINT;
3872         ImmGetCompositionWindow(hIMC, &cfr);
3873         if (x != cfr.ptCurrentPos.x || y != cfr.ptCurrentPos.y) {
3874             cfr.dwStyle = CFS_POINT;
3875             cfr.ptCurrentPos.x = x;
3876             cfr.ptCurrentPos.y = y;
3877             cf.rcArea.left = cf.rcArea.top = cf.rcArea.right = cf.rcArea.bottom = 0;
3878             ImmSetCompositionWindow(hIMC, &cfr);
3879         }
3880         ImmReleaseContext(hwnd, hIMC);
3881     }
3882 }
3883 
3884 MsgRouting AwtComponent::WmImeSetContext(BOOL fSet, LPARAM *lplParam)
3885 {
3886     // If the Windows input context is disabled, do not let Windows
3887     // display any UIs.
3888     HWND hwnd = ImmGetHWnd();
3889     HIMC hIMC = ImmGetContext(hwnd);
3890     if (hIMC == NULL) {
3891         *lplParam = 0;
3892         return mrDoDefault;
3893     }
3894     ImmReleaseContext(hwnd, hIMC);
3895 
3896     if (fSet) {
3897         LPARAM lParam = *lplParam;
3898         if (!m_useNativeCompWindow) {
3899             // stop to draw native composing window.
3900             *lplParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
3901         }
3902     }
3903     return mrDoDefault;
3904 }
3905 
3906 MsgRouting AwtComponent::WmImeNotify(WPARAM subMsg, LPARAM bitsCandType)
3907 {
3908     if (!m_useNativeCompWindow) {
3909         if (subMsg == IMN_OPENCANDIDATE || subMsg == IMN_CHANGECANDIDATE) {
3910             m_bitsCandType = bitsCandType;
3911             InquireCandidatePosition();
3912         } else if (subMsg == IMN_OPENSTATUSWINDOW ||
3913                    subMsg == WM_IME_STARTCOMPOSITION ||
3914                    subMsg == IMN_SETCANDIDATEPOS) {
3915             InquireCandidatePosition();
3916         }
3917     }
3918     return mrDoDefault;
3919 }
3920 
3921 MsgRouting AwtComponent::WmImeStartComposition()
3922 {
3923     if (m_useNativeCompWindow) {
3924         RECT rc;
3925         ::GetClientRect(GetHWnd(), &rc);
3926         SetCompositionWindow(rc);
3927         return mrDoDefault;
3928     } else
3929         return mrConsume;
3930 }
3931 
3932 MsgRouting AwtComponent::WmImeEndComposition()
3933 {
3934     if (m_useNativeCompWindow)   return mrDoDefault;
3935 
3936     SendInputMethodEvent(
3937         java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3938         NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0 );
3939     return mrConsume;
3940 }
3941 
3942 MsgRouting AwtComponent::WmImeComposition(WORD wChar, LPARAM flags)
3943 {
3944     if (m_useNativeCompWindow)   return mrDoDefault;
3945 
3946     int*      bndClauseW = NULL;
3947     jstring*  readingClauseW = NULL;
3948     int*      bndAttrW = NULL;
3949     BYTE*     valAttrW = NULL;
3950     int       cClauseW = 0;
3951     AwtInputTextInfor* textInfor = NULL;
3952 
3953     try {
3954         HWND hwnd = ImmGetHWnd();
3955         HIMC hIMC = ImmGetContext(hwnd);
3956         DASSERT(hIMC!=0);
3957 
3958         textInfor = new AwtInputTextInfor;
3959         textInfor->GetContextData(hIMC, flags);
3960         ImmReleaseContext(hwnd, hIMC);
3961 
3962         jstring jtextString = textInfor->GetText();
3963         /* The conditions to send the input method event to AWT EDT are:
3964            1. Whenever there is a composition message sent regarding whether
3965            the composition text is NULL or not. See details at bug 6222692.
3966            2. When there is a committed message sent, in which case, we have to
3967            check whether the committed string is NULL or not. If the committed string
3968            is NULL, there is no need to send any input method event.
3969            (Minor note: 'jtextString' returned is the merged string in the case of
3970            partial commit.)
3971         */
3972         if ((flags & GCS_RESULTSTR && jtextString != NULL) ||
3973             (flags & GCS_COMPSTR)) {
3974             int       cursorPosW = textInfor->GetCursorPosition();
3975             // In order not to delete the readingClauseW in the catch clause,
3976             // calling GetAttributeInfor before GetClauseInfor.
3977             int       cAttrW = textInfor->GetAttributeInfor(bndAttrW, valAttrW);
3978             cClauseW = textInfor->GetClauseInfor(bndClauseW, readingClauseW);
3979 
3980             /* Send INPUT_METHOD_TEXT_CHANGED event to the WInputMethod which in turn sends
3981                the event to AWT EDT.
3982 
3983                The last two paremeters are set to equal since we don't have recommendations for
3984                the visible position within the current composed text. See details at
3985                java.awt.event.InputMethodEvent.
3986             */
3987             SendInputMethodEvent(java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3988                                  jtextString,
3989                                  cClauseW, bndClauseW, readingClauseW,
3990                                  cAttrW, bndAttrW, valAttrW,
3991                                  textInfor->GetCommittedTextLength(),
3992                                  cursorPosW, cursorPosW);
3993         }
3994     } catch (...) {
3995         // since GetClauseInfor and GetAttributeInfor could throw exception, we have to release
3996         // the pointer here.
3997         delete [] bndClauseW;
3998         delete [] readingClauseW;
3999         delete [] bndAttrW;
4000         delete [] valAttrW;
4001         throw;
4002     }
4003 
4004     /* Free the storage allocated. Since jtextString won't be passed from threads
4005      *  to threads, we just use the local ref and it will be deleted within the destructor
4006      *  of AwtInputTextInfor object.
4007      */
4008     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4009     if (cClauseW && readingClauseW) {
4010         for (int i = 0; i < cClauseW; i ++) {
4011             if (readingClauseW[i]) {
4012                 env->DeleteLocalRef(readingClauseW[i]);
4013             }
4014         }
4015     }
4016     delete [] bndClauseW;
4017     delete [] readingClauseW;
4018     delete [] bndAttrW;
4019     delete [] valAttrW;
4020     delete textInfor;
4021 
4022     return mrConsume;
4023 }
4024 
4025 //
4026 // generate and post InputMethodEvent
4027 //
4028 void AwtComponent::SendInputMethodEvent(jint id, jstring text,
4029                                         int cClause, int* rgClauseBoundary, jstring* rgClauseReading,
4030                                         int cAttrBlock, int* rgAttrBoundary, BYTE *rgAttrValue,
4031                                         int commitedTextLength, int caretPos, int visiblePos)
4032 {
4033     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4034 
4035     // assumption for array type casting
4036     DASSERT(sizeof(int)==sizeof(jint));
4037     DASSERT(sizeof(BYTE)==sizeof(jbyte));
4038 
4039     // caluse information
4040     jintArray clauseBoundary = NULL;
4041     jobjectArray clauseReading = NULL;
4042     if (cClause && rgClauseBoundary && rgClauseReading) {
4043         // convert clause boundary offset array to java array
4044         clauseBoundary = env->NewIntArray(cClause+1);
4045         DASSERT(clauseBoundary);
4046         CHECK_NULL(clauseBoundary);
4047         env->SetIntArrayRegion(clauseBoundary, 0, cClause+1, (jint *)rgClauseBoundary);
4048         DASSERT(!safe_ExceptionOccurred(env));
4049 
4050         // convert clause reading string array to java array
4051         jclass stringCls = JNU_ClassString(env);
4052         DASSERT(stringCls);
4053         CHECK_NULL(stringCls);
4054         clauseReading = env->NewObjectArray(cClause, stringCls, NULL);
4055         DASSERT(clauseReading);
4056         CHECK_NULL(clauseReading);
4057         for (int i=0; i<cClause; i++)   env->SetObjectArrayElement(clauseReading, i, rgClauseReading[i]);
4058         DASSERT(!safe_ExceptionOccurred(env));
4059     }
4060 
4061 
4062     // attrubute value definition in WInputMethod.java must be equal to that in IMM.H
4063     DASSERT(ATTR_INPUT==sun_awt_windows_WInputMethod_ATTR_INPUT);
4064     DASSERT(ATTR_TARGET_CONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_CONVERTED);
4065     DASSERT(ATTR_CONVERTED==sun_awt_windows_WInputMethod_ATTR_CONVERTED);
4066     DASSERT(ATTR_TARGET_NOTCONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_NOTCONVERTED);
4067     DASSERT(ATTR_INPUT_ERROR==sun_awt_windows_WInputMethod_ATTR_INPUT_ERROR);
4068 
4069     // attribute information
4070     jintArray attrBoundary = NULL;
4071     jbyteArray attrValue = NULL;
4072     if (cAttrBlock && rgAttrBoundary && rgAttrValue) {
4073         // convert attribute boundary offset array to java array
4074         attrBoundary = env->NewIntArray(cAttrBlock+1);
4075         DASSERT(attrBoundary);
4076         CHECK_NULL(attrBoundary);
4077         env->SetIntArrayRegion(attrBoundary, 0, cAttrBlock+1, (jint *)rgAttrBoundary);
4078         DASSERT(!safe_ExceptionOccurred(env));
4079 
4080         // convert attribute value byte array to java array
4081         attrValue = env->NewByteArray(cAttrBlock);
4082         DASSERT(attrValue);
4083         CHECK_NULL(attrValue);
4084         env->SetByteArrayRegion(attrValue, 0, cAttrBlock, (jbyte *)rgAttrValue);
4085         DASSERT(!safe_ExceptionOccurred(env));
4086     }
4087 
4088 
4089     // get global reference of WInputMethod class (run only once)
4090     static jclass wInputMethodCls = NULL;
4091     if (wInputMethodCls == NULL) {
4092         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
4093         DASSERT(wInputMethodClsLocal);
4094         CHECK_NULL(wInputMethodClsLocal);
4095         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
4096         env->DeleteLocalRef(wInputMethodClsLocal);
4097     }
4098 
4099     // get method ID of sendInputMethodEvent() (run only once)
4100     static jmethodID sendIMEventMid = 0;
4101     if (sendIMEventMid == 0) {
4102         sendIMEventMid =  env->GetMethodID(wInputMethodCls, "sendInputMethodEvent",
4103                                            "(IJLjava/lang/String;[I[Ljava/lang/String;[I[BIII)V");
4104         DASSERT(sendIMEventMid);
4105         CHECK_NULL(sendIMEventMid);
4106     }
4107 
4108     // call m_InputMethod.sendInputMethod()
4109     env->CallVoidMethod(m_InputMethod, sendIMEventMid, id, TimeHelper::getMessageTimeUTC(),
4110                         text, clauseBoundary, clauseReading, attrBoundary,
4111                         attrValue, commitedTextLength, caretPos, visiblePos);
4112     if (safe_ExceptionOccurred(env))   env->ExceptionDescribe();
4113     DASSERT(!safe_ExceptionOccurred(env));
4114 
4115 }
4116 
4117 
4118 
4119 //
4120 // Inquires candidate position according to the composed text
4121 //
4122 void AwtComponent::InquireCandidatePosition()
4123 {
4124     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4125 
4126     // get global reference of WInputMethod class (run only once)
4127     static jclass wInputMethodCls = NULL;
4128     if (wInputMethodCls == NULL) {
4129         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
4130         DASSERT(wInputMethodClsLocal);
4131         CHECK_NULL(wInputMethodClsLocal);
4132         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
4133         env->DeleteLocalRef(wInputMethodClsLocal);
4134     }
4135 
4136     // get method ID of sendInputMethodEvent() (run only once)
4137     static jmethodID inqCandPosMid = 0;
4138     if (inqCandPosMid == 0) {
4139         inqCandPosMid =  env->GetMethodID(wInputMethodCls, "inquireCandidatePosition", "()V");
4140         DASSERT(!safe_ExceptionOccurred(env));
4141         DASSERT(inqCandPosMid);
4142         CHECK_NULL(inqCandPosMid);
4143     }
4144 
4145     // call m_InputMethod.sendInputMethod()
4146     jobject candPos = env->CallObjectMethod(m_InputMethod, inqCandPosMid);
4147     DASSERT(!safe_ExceptionOccurred(env));
4148 }
4149 
4150 HWND AwtComponent::ImmGetHWnd()
4151 {
4152     HWND proxy = GetProxyFocusOwner();
4153     return (proxy != NULL) ? proxy : GetHWnd();
4154 }
4155 
4156 HIMC AwtComponent::ImmAssociateContext(HIMC himc)
4157 {
4158     return ::ImmAssociateContext(ImmGetHWnd(), himc);
4159 }
4160 
4161 HWND AwtComponent::GetProxyFocusOwner()
4162 {
4163     AwtWindow *window = GetContainer();
4164     if (window != 0) {
4165         AwtFrame *owner = window->GetOwningFrameOrDialog();
4166         if (owner != 0) {
4167             return owner->GetProxyFocusOwner();
4168         } else if (!window->IsSimpleWindow()) { // isn't an owned simple window
4169             return ((AwtFrame*)window)->GetProxyFocusOwner();
4170         }
4171     }
4172     return (HWND)NULL;
4173 }
4174 
4175 /* Redirects message to the focus proxy, if any */
4176 void AwtComponent::CallProxyDefWindowProc(UINT message, WPARAM wParam,
4177     LPARAM lParam, LRESULT &retVal, MsgRouting &mr)
4178 {
4179     if (mr != mrConsume)  {
4180         HWND proxy = GetProxyFocusOwner();
4181         if (proxy != NULL && ::IsWindowEnabled(proxy)) {
4182             retVal = ::DefWindowProc(proxy, message, wParam, lParam);
4183             mr = mrConsume;
4184         }
4185     }
4186 }
4187 
4188 MsgRouting AwtComponent::WmCommand(UINT id, HWND hWndChild, UINT notifyCode)
4189 {
4190     /* Menu/Accelerator */
4191     if (hWndChild == 0) {
4192         AwtObject* obj = AwtToolkit::GetInstance().LookupCmdID(id);
4193         if (obj == NULL) {
4194             return mrConsume;
4195         }
4196         DASSERT(((AwtMenuItem*)obj)->GetID() == id);
4197         obj->DoCommand();
4198         return mrConsume;
4199     }
4200     /* Child id notification */
4201     else {
4202         AwtComponent* child = AwtComponent::GetComponent(hWndChild);
4203         if (child) {
4204             child->WmNotify(notifyCode);
4205         }
4206     }
4207     return mrDoDefault;
4208 }
4209 
4210 MsgRouting AwtComponent::WmNotify(UINT notifyCode)
4211 {
4212     return mrDoDefault;
4213 }
4214 
4215 MsgRouting AwtComponent::WmCompareItem(UINT ctrlId,
4216                                        COMPAREITEMSTRUCT &compareInfo,
4217                                        LRESULT &result)
4218 {
4219     AwtComponent* child = AwtComponent::GetComponent(compareInfo.hwndItem);
4220     if (child == this) {
4221         /* DoCallback("handleItemDelete", */
4222     }
4223     else if (child) {
4224         return child->WmCompareItem(ctrlId, compareInfo, result);
4225     }
4226     return mrConsume;
4227 }
4228 
4229 MsgRouting AwtComponent::WmDeleteItem(UINT ctrlId,
4230                                       DELETEITEMSTRUCT &deleteInfo)
4231 {
4232     /*
4233      * Workaround for NT 4.0 bug -- if SetWindowPos is called on a AwtList
4234      * window, a WM_DELETEITEM message is sent to its parent with a window
4235      * handle of one of the list's child windows.  The property lookup
4236      * succeeds, but the HWNDs don't match.
4237      */
4238     if (deleteInfo.hwndItem == NULL) {
4239         return mrConsume;
4240     }
4241     AwtComponent* child = (AwtComponent *)AwtComponent::GetComponent(deleteInfo.hwndItem);
4242 
4243     if (child && child->GetHWnd() != deleteInfo.hwndItem) {
4244         return mrConsume;
4245     }
4246 
4247     if (child == this) {
4248         /*DoCallback("handleItemDelete", */
4249     }
4250     else if (child) {
4251         return child->WmDeleteItem(ctrlId, deleteInfo);
4252     }
4253     return mrConsume;
4254 }
4255 
4256 MsgRouting AwtComponent::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT &drawInfo)
4257 {
4258     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4259 
4260     if (drawInfo.CtlType == ODT_MENU) {
4261         if (IsMenu((HMENU)drawInfo.hwndItem) && drawInfo.itemData != 0) {
4262             AwtMenu* menu = (AwtMenu*)(drawInfo.itemData);
4263             menu->DrawItem(drawInfo);
4264         }
4265     } else {
4266         return OwnerDrawItem(ctrlId, drawInfo);
4267     }
4268     return mrConsume;
4269 }
4270 
4271 MsgRouting AwtComponent::WmMeasureItem(UINT ctrlId,
4272                                        MEASUREITEMSTRUCT &measureInfo)
4273 {
4274     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4275 
4276     if (measureInfo.CtlType == ODT_MENU) {
4277         if (measureInfo.itemData != 0) {
4278             AwtMenu* menu = (AwtMenu*)(measureInfo.itemData);
4279             HDC hDC = ::GetDC(GetHWnd());
4280             /* menu->MeasureItem(env, hDC, measureInfo); */
4281             menu->MeasureItem(hDC, measureInfo);
4282             ::ReleaseDC(GetHWnd(), hDC);
4283         }
4284     } else {
4285         return OwnerMeasureItem(ctrlId, measureInfo);
4286     }
4287     return mrConsume;
4288 }
4289 
4290 MsgRouting AwtComponent::OwnerDrawItem(UINT ctrlId,
4291     DRAWITEMSTRUCT &drawInfo)
4292 {
4293     AwtComponent* child = AwtComponent::GetComponent(drawInfo.hwndItem);
4294     if (child == this) {
4295         /* DoCallback("handleItemDelete", */
4296     } else if (child != NULL) {
4297         return child->WmDrawItem(ctrlId, drawInfo);
4298     }
4299     return mrConsume;
4300 }
4301 
4302 MsgRouting AwtComponent::OwnerMeasureItem(UINT ctrlId,
4303     MEASUREITEMSTRUCT &measureInfo)
4304 {
4305     HWND  hChild = ::GetDlgItem(GetHWnd(), measureInfo.CtlID);
4306     AwtComponent* child = AwtComponent::GetComponent(hChild);
4307     /*
4308      * If the parent cannot find the child's instance from its handle,
4309      * maybe the child is in its creation.  So the child must be searched
4310      * from the list linked before the child's creation.
4311      */
4312     if (child == NULL) {
4313         child = SearchChild((UINT)ctrlId);
4314     }
4315 
4316     if (child == this) {
4317     /* DoCallback("handleItemDelete",  */
4318     }
4319     else if (child) {
4320         return child->WmMeasureItem(ctrlId, measureInfo);
4321     }
4322     return mrConsume;
4323 }
4324 
4325 /* for WmDrawItem method of Label, Button and Checkbox */
4326 void AwtComponent::DrawWindowText(HDC hDC, jobject font, jstring text,
4327                                   int x, int y)
4328 {
4329     int nOldBkMode = ::SetBkMode(hDC,TRANSPARENT);
4330     DASSERT(nOldBkMode != 0);
4331     AwtFont::drawMFString(hDC, font, text, x, y, GetCodePage());
4332     VERIFY(::SetBkMode(hDC,nOldBkMode));
4333 }
4334 
4335 /*
4336  * Draw text in gray (the color being set to COLOR_GRAYTEXT) when the
4337  * component is disabled.  Used only for label, checkbox and button in
4338  * OWNER_DRAW.  It draws the text in emboss.
4339  */
4340 void AwtComponent::DrawGrayText(HDC hDC, jobject font, jstring text,
4341                                 int x, int y)
4342 {
4343     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHILIGHT));
4344     AwtComponent::DrawWindowText(hDC, font, text, x+1, y+1);
4345     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
4346     AwtComponent::DrawWindowText(hDC, font, text, x, y);
4347 }
4348 
4349 /* for WmMeasureItem method of List and Choice */
4350 jstring AwtComponent::GetItemString(JNIEnv *env, jobject target, jint index)
4351 {
4352     jstring str = (jstring)JNU_CallMethodByName(env, NULL, target, "getItemImpl",
4353                                                 "(I)Ljava/lang/String;",
4354                                                 index).l;
4355     DASSERT(!safe_ExceptionOccurred(env));
4356     return str;
4357 }
4358 
4359 /* for WmMeasureItem method of List and Choice */
4360 void AwtComponent::MeasureListItem(JNIEnv *env,
4361                                    MEASUREITEMSTRUCT &measureInfo)
4362 {
4363     if (env->EnsureLocalCapacity(1) < 0) {
4364         return;
4365     }
4366     jobject dimension = PreferredItemSize(env);
4367     DASSERT(dimension);
4368     measureInfo.itemWidth =
4369       env->GetIntField(dimension, AwtDimension::widthID);
4370     measureInfo.itemHeight =
4371       env->GetIntField(dimension, AwtDimension::heightID);
4372     env->DeleteLocalRef(dimension);
4373 }
4374 
4375 /* for WmDrawItem method of List and Choice */
4376 void AwtComponent::DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo)
4377 {
4378     if (env->EnsureLocalCapacity(3) < 0) {
4379         return;
4380     }
4381     jobject peer = GetPeer(env);
4382     jobject target = env->GetObjectField(peer, AwtObject::targetID);
4383 
4384     HDC hDC = drawInfo.hDC;
4385     RECT rect = drawInfo.rcItem;
4386 
4387     BOOL bEnabled = isEnabled();
4388     BOOL unfocusableChoice = (drawInfo.itemState & ODS_COMBOBOXEDIT) && !IsFocusable();
4389     DWORD crBack, crText;
4390     if (drawInfo.itemState & ODS_SELECTED){
4391         /* Set background and text colors for selected item */
4392         crBack = ::GetSysColor (COLOR_HIGHLIGHT);
4393         crText = ::GetSysColor (COLOR_HIGHLIGHTTEXT);
4394     } else {
4395         /* Set background and text colors for unselected item */
4396         crBack = GetBackgroundColor();
4397         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4398     }
4399     if (unfocusableChoice) {
4400         //6190728. Shouldn't draw selection field (edit control) of an owner-drawn combo box.
4401         crBack = GetBackgroundColor();
4402         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4403     }
4404 
4405     /* Fill item rectangle with background color */
4406     HBRUSH hbrBack = ::CreateSolidBrush (crBack);
4407     DASSERT(hbrBack);
4408     /* 6190728. Shouldn't draw any kind of rectangle around selection field
4409      * (edit control) of an owner-drawn combo box while unfocusable
4410      */
4411     if (!unfocusableChoice){
4412         VERIFY(::FillRect (hDC, &rect, hbrBack));
4413     }
4414     VERIFY(::DeleteObject (hbrBack));
4415 
4416     /* Set current background and text colors */
4417     ::SetBkColor (hDC, crBack);
4418     ::SetTextColor (hDC, crText);
4419 
4420     /*draw string (with left margin of 1 point) */
4421     if ((int) (drawInfo.itemID) >= 0) {
4422             jobject font = GET_FONT(target, peer);
4423             jstring text = GetItemString(env, target, drawInfo.itemID);
4424             if (env->ExceptionCheck()) {
4425                 env->DeleteLocalRef(font);
4426                 env->DeleteLocalRef(target);
4427                 return;
4428             }
4429             SIZE size = AwtFont::getMFStringSize(hDC, font, text);
4430             AwtFont::drawMFString(hDC, font, text,
4431                                   (GetRTL()) ? rect.right - size.cx - 1
4432                                              : rect.left + 1,
4433                                   (rect.top + rect.bottom - size.cy) / 2,
4434                                   GetCodePage());
4435             env->DeleteLocalRef(font);
4436             env->DeleteLocalRef(text);
4437     }
4438     if ((drawInfo.itemState & ODS_FOCUS)  &&
4439         (drawInfo.itemAction & (ODA_FOCUS | ODA_DRAWENTIRE))) {
4440       if (!unfocusableChoice){
4441           VERIFY(::DrawFocusRect(hDC, &rect));
4442       }
4443     }
4444     env->DeleteLocalRef(target);
4445 }
4446 
4447 /* for MeasureListItem method and WmDrawItem method of Checkbox */
4448 jint AwtComponent::GetFontHeight(JNIEnv *env)
4449 {
4450     if (env->EnsureLocalCapacity(4) < 0) {
4451         return NULL;
4452     }
4453     jobject self = GetPeer(env);
4454     jobject target = env->GetObjectField(self, AwtObject::targetID);
4455 
4456     jobject font = GET_FONT(target, self);
4457     jobject toolkit = env->CallObjectMethod(target,
4458                                             AwtComponent::getToolkitMID);
4459 
4460     DASSERT(!safe_ExceptionOccurred(env));
4461 
4462     jobject fontMetrics =
4463         env->CallObjectMethod(toolkit, AwtToolkit::getFontMetricsMID, font);
4464 
4465     DASSERT(!safe_ExceptionOccurred(env));
4466 
4467     jint height = env->CallIntMethod(fontMetrics, AwtFont::getHeightMID);
4468     DASSERT(!safe_ExceptionOccurred(env));
4469 
4470     env->DeleteLocalRef(target);
4471     env->DeleteLocalRef(font);
4472     env->DeleteLocalRef(toolkit);
4473     env->DeleteLocalRef(fontMetrics);
4474 
4475     return height;
4476 }
4477 
4478 // If you override WmPrint, make sure to save a copy of the DC on the GDI
4479 // stack to be restored in WmPrintClient. Windows mangles the DC in
4480 // ::DefWindowProc.
4481 MsgRouting AwtComponent::WmPrint(HDC hDC, LPARAM flags)
4482 {
4483     /*
4484      * DefWindowProc for WM_PRINT changes DC parameters, so we have
4485      * to restore it ourselves. Otherwise it will cause problems
4486      * when several components are printed to the same DC.
4487      */
4488     int nOriginalDC = ::SaveDC(hDC);
4489     DASSERT(nOriginalDC != 0);
4490 
4491     if (flags & PRF_NONCLIENT) {
4492 
4493         VERIFY(::SaveDC(hDC));
4494 
4495         DefWindowProc(WM_PRINT, (WPARAM)hDC,
4496                       (flags & (PRF_NONCLIENT
4497                                 | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4498 
4499         VERIFY(::RestoreDC(hDC, -1));
4500 
4501         // Special case for components with a sunken border. Windows does not
4502         // print the border correctly on PCL printers, so we have to do it ourselves.
4503         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4504             RECT r;
4505             VERIFY(::GetWindowRect(GetHWnd(), &r));
4506             VERIFY(::OffsetRect(&r, -r.left, -r.top));
4507             VERIFY(::DrawEdge(hDC, &r, EDGE_SUNKEN, BF_RECT));
4508         }
4509     }
4510 
4511     if (flags & PRF_CLIENT) {
4512 
4513         /*
4514          * Special case for components with a sunken border.
4515          * Windows prints a client area without offset to a border width.
4516          * We will first print the non-client area with the original offset,
4517          * then the client area with a corrected offset.
4518          */
4519         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4520 
4521             int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE);
4522             int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE);
4523 
4524             VERIFY(::OffsetWindowOrgEx(hDC, -nEdgeWidth, -nEdgeHeight, NULL));
4525 
4526             // Save a copy of the DC for WmPrintClient
4527             VERIFY(::SaveDC(hDC));
4528 
4529             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4530                           (flags & (PRF_CLIENT
4531                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4532 
4533             VERIFY(::OffsetWindowOrgEx(hDC, nEdgeWidth, nEdgeHeight, NULL));
4534 
4535         } else {
4536 
4537             // Save a copy of the DC for WmPrintClient
4538             VERIFY(::SaveDC(hDC));
4539             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4540                           (flags & (PRF_CLIENT
4541                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4542         }
4543     }
4544 
4545     if (flags & (PRF_CHILDREN | PRF_OWNED)) {
4546         DefWindowProc(WM_PRINT, (WPARAM) hDC,
4547                       (flags & ~PRF_CLIENT & ~PRF_NONCLIENT));
4548     }
4549 
4550     VERIFY(::RestoreDC(hDC, nOriginalDC));
4551 
4552     return mrConsume;
4553 }
4554 
4555 // If you override WmPrintClient, make sure to obtain a valid copy of
4556 // the DC from the GDI stack. The copy of the DC should have been placed
4557 // there by WmPrint. Windows mangles the DC in ::DefWindowProc.
4558 MsgRouting AwtComponent::WmPrintClient(HDC hDC, LPARAM)
4559 {
4560     // obtain valid DC from GDI stack
4561     ::RestoreDC(hDC, -1);
4562 
4563     return mrDoDefault;
4564 }
4565 
4566 MsgRouting AwtComponent::WmNcCalcSize(BOOL fCalcValidRects,
4567                                       LPNCCALCSIZE_PARAMS lpncsp,
4568                                       LRESULT &retVal)
4569 {
4570     return mrDoDefault;
4571 }
4572 
4573 MsgRouting AwtComponent::WmNcPaint(HRGN hrgn)
4574 {
4575     return mrDoDefault;
4576 }
4577 
4578 MsgRouting AwtComponent::WmNcHitTest(UINT x, UINT y, LRESULT &retVal)
4579 {
4580     return mrDoDefault;
4581 }
4582 
4583 /**
4584  * WmQueryNewPalette is called whenever our component is coming to
4585  * the foreground; this gives us an opportunity to install our
4586  * custom palette.  If this install actually changes entries in
4587  * the system palette, then we get a further call to WmPaletteChanged
4588  * (but note that we only need to realize our palette once).
4589  */
4590 MsgRouting AwtComponent::WmQueryNewPalette(LRESULT &retVal)
4591 {
4592     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4593     m_QueryNewPaletteCalled = TRUE;
4594     HDC hDC = ::GetDC(GetHWnd());
4595     DASSERT(hDC);
4596     AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4597     AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4598     ::ReleaseDC(GetHWnd(), hDC);
4599     // We must realize the palettes of all of our DC's
4600     // There is sometimes a problem where the realization of
4601     // our temporary hDC here does not actually do what
4602     // we want.  Not clear why, but presumably fallout from
4603     // our use of several simultaneous hDC's.
4604     activeDCList.RealizePalettes(screen);
4605     // Do not invalidate here; if the palette
4606     // has not changed we will get an extra repaint
4607     retVal = TRUE;
4608 
4609     return mrDoDefault;
4610 }
4611 
4612 /**
4613  * We should not need to track this event since we handle our
4614  * palette management effectively in the WmQueryNewPalette and
4615  * WmPaletteChanged methods.  However, there seems to be a bug
4616  * on some win32 systems (e.g., NT4) whereby the palette
4617  * immediately after a displayChange is not yet updated to its
4618  * final post-display-change values (hence we adjust our palette
4619  * using the wrong system palette entries), then the palette is
4620  * updated, but a WM_PALETTECHANGED message is never sent.
4621  * By tracking the ISCHANGING message as well (and by tracking
4622  * displayChange events in the AwtToolkit object), we can account
4623  * for this error by forcing our WmPaletteChanged method to be
4624  * called and thereby realizing our logical palette and updating
4625  * our dynamic colorModel object.
4626  */
4627 MsgRouting AwtComponent::WmPaletteIsChanging(HWND hwndPalChg)
4628 {
4629     if (AwtToolkit::GetInstance().HasDisplayChanged()) {
4630         WmPaletteChanged(hwndPalChg);
4631         AwtToolkit::GetInstance().ResetDisplayChanged();
4632     }
4633     return mrDoDefault;
4634 }
4635 
4636 MsgRouting AwtComponent::WmPaletteChanged(HWND hwndPalChg)
4637 {
4638     // We need to re-realize our palette here (unless we're the one
4639     // that was realizing it in the first place).  That will let us match the
4640     // remaining colors in the system palette as best we can.  We always
4641     // invalidate because the palette will have changed when we receive this
4642     // message.
4643 
4644     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4645     if (hwndPalChg != GetHWnd()) {
4646         HDC hDC = ::GetDC(GetHWnd());
4647         DASSERT(hDC);
4648         AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4649         AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4650         ::ReleaseDC(GetHWnd(), hDC);
4651         // We must realize the palettes of all of our DC's
4652         activeDCList.RealizePalettes(screen);
4653     }
4654     if (AwtWin32GraphicsDevice::UpdateSystemPalette(screen)) {
4655         AwtWin32GraphicsDevice::UpdateDynamicColorModel(screen);
4656     }
4657     Invalidate(NULL);
4658     return mrDoDefault;
4659 }
4660 
4661 MsgRouting AwtComponent::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss)
4662 {
4663     DASSERT(!IsBadReadPtr(lpss, sizeof(STYLESTRUCT)));
4664     return mrDoDefault;
4665 }
4666 
4667 MsgRouting AwtComponent::WmSettingChange(UINT wFlag, LPCTSTR pszSection)
4668 {
4669     DASSERT(!IsBadStringPtr(pszSection, 20));
4670     DTRACE_PRINTLN2("WM_SETTINGCHANGE: wFlag=%d pszSection=%s", (int)wFlag, pszSection);
4671     return mrDoDefault;
4672 }
4673 
4674 HDC AwtComponent::GetDCFromComponent()
4675 {
4676     GetDCReturnStruct *hdcStruct =
4677         (GetDCReturnStruct*)SendMessage(WM_AWT_GETDC);
4678     HDC hdc;
4679     if (hdcStruct) {
4680         if (hdcStruct->gdiLimitReached) {
4681             if (jvm != NULL) {
4682                 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4683                 if (env != NULL && !safe_ExceptionOccurred(env)) {
4684                     JNU_ThrowByName(env, "java/awt/AWTError",
4685                         "HDC creation failure - " \
4686                         "exceeded maximum GDI resources");
4687                 }
4688             }
4689         }
4690         hdc = hdcStruct->hDC;
4691         delete hdcStruct;
4692     } else {
4693         hdc = NULL;
4694     }
4695     return hdc;
4696 }
4697 
4698 void AwtComponent::FillBackground(HDC hMemoryDC, SIZE &size)
4699 {
4700     RECT eraseR = { 0, 0, size.cx, size.cy };
4701     VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush()));
4702 }
4703 
4704 void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
4705 {
4706     if (!bitmapBits) {
4707         return;
4708     }
4709 
4710     DWORD* dest = (DWORD*)bitmapBits;
4711     //XXX: might be optimized to use one loop (cy*cx -> 0)
4712     for (int i = 0; i < size.cy; i++ ) {
4713         for (int j = 0; j < size.cx; j++ ) {
4714             ((BYTE*)(dest++))[3] = alpha;
4715         }
4716     }
4717 }
4718 
4719 jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
4720     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4721 
4722     if (!::IsWindowVisible(GetHWnd())) {
4723         return NULL;
4724     }
4725 
4726     HDC hdc = GetDCFromComponent();
4727     if (!hdc) {
4728         return NULL;
4729     }
4730     HDC hMemoryDC = ::CreateCompatibleDC(hdc);
4731     void *bitmapBits = NULL;
4732     HBITMAP hBitmap = BitmapUtil::CreateARGBBitmap(size.cx, size.cy, &bitmapBits);
4733     HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemoryDC, hBitmap);
4734     SendMessage(WM_AWT_RELEASEDC, (WPARAM)hdc);
4735 
4736     FillBackground(hMemoryDC, size);
4737 
4738     VERIFY(::SetWindowOrgEx(hMemoryDC, loc.cx, loc.cy, NULL));
4739 
4740     // Don't bother with PRF_CHECKVISIBLE because we called IsWindowVisible
4741     // above.
4742     SendMessage(WM_PRINT, (WPARAM)hMemoryDC, PRF_CLIENT | PRF_NONCLIENT);
4743 
4744     // First make sure the system completed any drawing to the bitmap.
4745     ::GdiFlush();
4746 
4747     // WM_PRINT does not fill the alpha-channel of the ARGB bitmap
4748     // leaving it equal to zero. Hence we need to fill it manually. Otherwise
4749     // the pixels will be considered transparent when interpreting the data.
4750     FillAlpha(bitmapBits, size, alpha);
4751 
4752     ::SelectObject(hMemoryDC, hOldBitmap);
4753 
4754     BITMAPINFO bmi;
4755     memset(&bmi, 0, sizeof(BITMAPINFO));
4756     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
4757     bmi.bmiHeader.biWidth = size.cx;
4758     bmi.bmiHeader.biHeight = -size.cy;
4759     bmi.bmiHeader.biPlanes = 1;
4760     bmi.bmiHeader.biBitCount = 32;
4761     bmi.bmiHeader.biCompression = BI_RGB;
4762 
4763     jobject localPixelArray = env->NewIntArray(size.cx * size.cy);
4764     jintArray pixelArray = NULL;
4765     if (localPixelArray != NULL) {
4766         pixelArray = (jintArray)env->NewGlobalRef(localPixelArray);
4767         env->DeleteLocalRef(localPixelArray); localPixelArray = NULL;
4768 
4769         jboolean isCopy;
4770         jint *pixels = env->GetIntArrayElements(pixelArray, &isCopy);
4771 
4772         ::GetDIBits(hMemoryDC, hBitmap, 0, size.cy, (LPVOID)pixels, &bmi,
4773                     DIB_RGB_COLORS);
4774 
4775         env->ReleaseIntArrayElements(pixelArray, pixels, 0);
4776     }
4777 
4778     VERIFY(::DeleteObject(hBitmap));
4779     VERIFY(::DeleteDC(hMemoryDC));
4780 
4781     return pixelArray;
4782 }
4783 
4784 void* AwtComponent::SetNativeFocusOwner(void *self) {
4785     if (self == NULL) {
4786         // It means that the KFM wants to set focus to null
4787         sm_focusOwner = NULL;
4788         return NULL;
4789     }
4790 
4791     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4792 
4793     AwtComponent *c = NULL;
4794     jobject peer = (jobject)self;
4795 
4796     PDATA pData;
4797     JNI_CHECK_NULL_GOTO(peer, "peer", ret);
4798     pData = JNI_GET_PDATA(peer);
4799     if (pData == NULL) {
4800         goto ret;
4801     }
4802     c = (AwtComponent *)pData;
4803 
4804 ret:
4805     if (c && ::IsWindow(c->GetHWnd())) {
4806         sm_focusOwner = c->GetHWnd();
4807     } else {
4808         sm_focusOwner = NULL;
4809     }
4810     env->DeleteGlobalRef(peer);
4811     return NULL;
4812 }
4813 
4814 void* AwtComponent::GetNativeFocusedWindow() {
4815     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4816     AwtComponent *comp =
4817         AwtComponent::GetComponent(AwtComponent::GetFocusedWindow());
4818     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4819 }
4820 
4821 void* AwtComponent::GetNativeFocusOwner() {
4822     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4823     AwtComponent *comp =
4824         AwtComponent::GetComponent(AwtComponent::sm_focusOwner);
4825     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4826 }
4827 
4828 AwtComponent* AwtComponent::SearchChild(UINT id) {
4829     ChildListItem* child;
4830     for (child = m_childList; child != NULL;child = child->m_next) {
4831         if (child->m_ID == id)
4832             return child->m_Component;
4833     }
4834     /*
4835      * DASSERT(FALSE);
4836      * This should not be happend if all children are recorded
4837      */
4838     return NULL;        /* make compiler happy */
4839 }
4840 
4841 void AwtComponent::RemoveChild(UINT id) {
4842     ChildListItem* child = m_childList;
4843     ChildListItem* lastChild = NULL;
4844     while (child != NULL) {
4845         if (child->m_ID == id) {
4846             if (lastChild == NULL) {
4847                 m_childList = child->m_next;
4848             } else {
4849                 lastChild->m_next = child->m_next;
4850             }
4851             child->m_next = NULL;
4852             DASSERT(child != NULL);
4853             delete child;
4854             return;
4855         }
4856         lastChild = child;
4857         child = child->m_next;
4858     }
4859 }
4860 
4861 void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked,
4862                                 jint modifiers, jint keyLocation, jlong nativeCode, MSG *pMsg)
4863 {
4864     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4865     CriticalSection::Lock l(GetLock());
4866     if (GetPeer(env) == NULL) {
4867         /* event received during termination. */
4868         return;
4869     }
4870 
4871     static jclass keyEventCls;
4872     if (keyEventCls == NULL) {
4873         jclass keyEventClsLocal = env->FindClass("java/awt/event/KeyEvent");
4874         DASSERT(keyEventClsLocal);
4875         if (keyEventClsLocal == NULL) {
4876             /* exception already thrown */
4877             return;
4878         }
4879         keyEventCls = (jclass)env->NewGlobalRef(keyEventClsLocal);
4880         env->DeleteLocalRef(keyEventClsLocal);
4881     }
4882 
4883     static jmethodID keyEventConst;
4884     if (keyEventConst == NULL) {
4885         keyEventConst =  env->GetMethodID(keyEventCls, "<init>",
4886                                           "(Ljava/awt/Component;IJIICI)V");
4887         DASSERT(keyEventConst);
4888         CHECK_NULL(keyEventConst);
4889     }
4890     if (env->EnsureLocalCapacity(2) < 0) {
4891         return;
4892     }
4893     jobject target = GetTarget(env);
4894     jobject keyEvent = env->NewObject(keyEventCls, keyEventConst, target,
4895                                       id, when, modifiers, raw, cooked,
4896                                       keyLocation);
4897     if (safe_ExceptionOccurred(env)) env->ExceptionDescribe();
4898     DASSERT(!safe_ExceptionOccurred(env));
4899     DASSERT(keyEvent != NULL);
4900     if (keyEvent == NULL) {
4901         env->DeleteLocalRef(target);
4902         return;
4903     }
4904     env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode);
4905     if( nativeCode && nativeCode < 256 ) {
4906         env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode));
4907         env->SetLongField(keyEvent, AwtKeyEvent::extendedKeyCodeID, (jlong)(dynPrimaryKeymap[nativeCode].jkey));
4908         if( nativeCode < 255 ) {
4909             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(dynPrimaryKeymap[nativeCode].scancode));
4910         }else if( pMsg != NULL ) {
4911             // unknown key with virtual keycode 0xFF.
4912             // Its scancode is not in the table, pickup it from the message.
4913             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(HIWORD(pMsg->lParam) & 0xFF));
4914         }
4915     }
4916     if (pMsg != NULL) {
4917         AwtAWTEvent::saveMSG(env, pMsg, keyEvent);
4918     }
4919     SendEvent(keyEvent);
4920 
4921     env->DeleteLocalRef(keyEvent);
4922     env->DeleteLocalRef(target);
4923 }
4924 
4925 void
4926 AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when,
4927                                        jint raw, jint cooked,
4928                                        jint modifiers, jint keyLocation,
4929                                        jlong nativeCode,
4930                                        MSG *msg)
4931 {
4932     /*
4933      * if focus owner is null, but focused window isn't
4934      * we will send key event to focused window
4935      */
4936     HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : AwtComponent::GetFocusedWindow());
4937 
4938     if (hwndTarget == GetHWnd()) {
4939         SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, nativeCode, msg);
4940     } else {
4941         AwtComponent *target = NULL;
4942         if (hwndTarget != NULL) {
4943             target = AwtComponent::GetComponent(hwndTarget);
4944             if (target == NULL) {
4945                 target = this;
4946             }
4947         }
4948         if (target != NULL) {
4949             target->SendKeyEvent(id, when, raw, cooked, modifiers,
4950               keyLocation, nativeCode, msg);
4951         }
4952     }
4953 }
4954 
4955 void AwtComponent::SetDragCapture(UINT flags)
4956 {
4957     // don't want to interfere with other controls
4958     if (::GetCapture() == NULL) {
4959         ::SetCapture(GetHWnd());
4960     }
4961 }
4962 
4963 void AwtComponent::ReleaseDragCapture(UINT flags)
4964 {
4965     if ((::GetCapture() == GetHWnd()) && ((flags & ALL_MK_BUTTONS) == 0)) {
4966         // user has released all buttons, so release the capture
4967         ::ReleaseCapture();
4968     }
4969 }
4970 
4971 void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y,
4972                                   jint modifiers, jint clickCount,
4973                                   jboolean popupTrigger, jint button,
4974                                   MSG *pMsg, BOOL causedByTouchEvent)
4975 {
4976     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4977     CriticalSection::Lock l(GetLock());
4978     if (GetPeer(env) == NULL) {
4979         /* event received during termination. */
4980         return;
4981     }
4982 
4983     static jclass mouseEventCls;
4984     if (mouseEventCls == NULL) {
4985         jclass mouseEventClsLocal =
4986             env->FindClass("java/awt/event/MouseEvent");
4987         CHECK_NULL(mouseEventClsLocal);
4988         mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal);
4989         env->DeleteLocalRef(mouseEventClsLocal);
4990     }
4991     RECT insets;
4992     GetInsets(&insets);
4993 
4994     static jmethodID mouseEventConst;
4995     if (mouseEventConst == NULL) {
4996         mouseEventConst =
4997             env->GetMethodID(mouseEventCls, "<init>",
4998                  "(Ljava/awt/Component;IJIIIIIIZI)V");
4999         DASSERT(mouseEventConst);
5000         CHECK_NULL(mouseEventConst);
5001     }
5002     if (env->EnsureLocalCapacity(2) < 0) {
5003         return;
5004     }
5005     jobject target = GetTarget(env);
5006     DWORD curMousePos = ::GetMessagePos();
5007     int xAbs = GET_X_LPARAM(curMousePos);
5008     int yAbs = GET_Y_LPARAM(curMousePos);
5009     jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
5010                                         target,
5011                                         id, when, modifiers,
5012                                         x+insets.left, y+insets.top,
5013                                         xAbs, yAbs,
5014                                         clickCount, popupTrigger, button);
5015 
5016     if (safe_ExceptionOccurred(env)) {
5017         env->ExceptionDescribe();
5018         env->ExceptionClear();
5019     }
5020 
5021     DASSERT(mouseEvent != NULL);
5022     CHECK_NULL(mouseEvent);
5023     if (causedByTouchEvent) {
5024         env->SetBooleanField(mouseEvent, AwtMouseEvent::causedByTouchEventID,
5025             JNI_TRUE);
5026     }
5027     if (pMsg != 0) {
5028         AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
5029     }
5030     SendEvent(mouseEvent);
5031 
5032     env->DeleteLocalRef(mouseEvent);
5033     env->DeleteLocalRef(target);
5034 }
5035 
5036 void
5037 AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
5038                                   jint modifiers, jint clickCount,
5039                                   jboolean popupTrigger, jint scrollType,
5040                                   jint scrollAmount, jint roundedWheelRotation,
5041                                   jdouble preciseWheelRotation, MSG *pMsg)
5042 {
5043     /* Code based not so loosely on AwtComponent::SendMouseEvent */
5044     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5045     CriticalSection::Lock l(GetLock());
5046     if (GetPeer(env) == NULL) {
5047         /* event received during termination. */
5048         return;
5049     }
5050 
5051     static jclass mouseWheelEventCls;
5052     if (mouseWheelEventCls == NULL) {
5053         jclass mouseWheelEventClsLocal =
5054             env->FindClass("java/awt/event/MouseWheelEvent");
5055         CHECK_NULL(mouseWheelEventClsLocal);
5056         mouseWheelEventCls = (jclass)env->NewGlobalRef(mouseWheelEventClsLocal);
5057         env->DeleteLocalRef(mouseWheelEventClsLocal);
5058     }
5059     RECT insets;
5060     GetInsets(&insets);
5061 
5062     static jmethodID mouseWheelEventConst;
5063     if (mouseWheelEventConst == NULL) {
5064         mouseWheelEventConst =
5065             env->GetMethodID(mouseWheelEventCls, "<init>",
5066                            "(Ljava/awt/Component;IJIIIIIIZIIID)V");
5067         DASSERT(mouseWheelEventConst);
5068         CHECK_NULL(mouseWheelEventConst);
5069     }
5070     if (env->EnsureLocalCapacity(2) < 0) {
5071         return;
5072     }
5073     jobject target = GetTarget(env);
5074     DTRACE_PRINTLN("creating MWE in JNI");
5075 
5076     jobject mouseWheelEvent = env->NewObject(mouseWheelEventCls,
5077                                              mouseWheelEventConst,
5078                                              target,
5079                                              id, when, modifiers,
5080                                              x+insets.left, y+insets.top,
5081                                              0, 0,
5082                                              clickCount, popupTrigger,
5083                                              scrollType, scrollAmount,
5084                                              roundedWheelRotation, preciseWheelRotation);
5085 
5086     DASSERT(mouseWheelEvent != NULL);
5087     if (mouseWheelEvent == NULL || safe_ExceptionOccurred(env)) {
5088         env->ExceptionDescribe();
5089         env->ExceptionClear();
5090         env->DeleteLocalRef(target);
5091         return;
5092     }
5093     if (pMsg != NULL) {
5094         AwtAWTEvent::saveMSG(env, pMsg, mouseWheelEvent);
5095     }
5096     SendEvent(mouseWheelEvent);
5097 
5098     env->DeleteLocalRef(mouseWheelEvent);
5099     env->DeleteLocalRef(target);
5100 }
5101 
5102 void AwtComponent::SendFocusEvent(jint id, HWND opposite)
5103 {
5104     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5105 
5106     CriticalSection::Lock l(GetLock());
5107     if (GetPeer(env) == NULL) {
5108         /* event received during termination. */
5109         return;
5110     }
5111 
5112     static jclass focusEventCls;
5113     if (focusEventCls == NULL) {
5114         jclass focusEventClsLocal
5115             = env->FindClass("java/awt/event/FocusEvent");
5116         DASSERT(focusEventClsLocal);
5117         CHECK_NULL(focusEventClsLocal);
5118         focusEventCls = (jclass)env->NewGlobalRef(focusEventClsLocal);
5119         env->DeleteLocalRef(focusEventClsLocal);
5120     }
5121 
5122     static jmethodID focusEventConst;
5123     if (focusEventConst == NULL) {
5124         focusEventConst =
5125             env->GetMethodID(focusEventCls, "<init>",
5126                              "(Ljava/awt/Component;IZLjava/awt/Component;)V");
5127         DASSERT(focusEventConst);
5128         CHECK_NULL(focusEventConst);
5129     }
5130 
5131     static jclass sequencedEventCls;
5132     if (sequencedEventCls == NULL) {
5133         jclass sequencedEventClsLocal =
5134             env->FindClass("java/awt/SequencedEvent");
5135         DASSERT(sequencedEventClsLocal);
5136         CHECK_NULL(sequencedEventClsLocal);
5137         sequencedEventCls =
5138             (jclass)env->NewGlobalRef(sequencedEventClsLocal);
5139         env->DeleteLocalRef(sequencedEventClsLocal);
5140     }
5141 
5142     static jmethodID sequencedEventConst;
5143     if (sequencedEventConst == NULL) {
5144         sequencedEventConst =
5145             env->GetMethodID(sequencedEventCls, "<init>",
5146                              "(Ljava/awt/AWTEvent;)V");
5147         DASSERT(sequencedEventConst);
5148         CHECK_NULL(sequencedEventConst);
5149     }
5150 
5151     if (env->EnsureLocalCapacity(3) < 0) {
5152         return;
5153     }
5154 
5155     jobject target = GetTarget(env);
5156     jobject jOpposite = NULL;
5157     if (opposite != NULL) {
5158         AwtComponent *awtOpposite = AwtComponent::GetComponent(opposite);
5159         if (awtOpposite != NULL) {
5160             jOpposite = awtOpposite->GetTarget(env);
5161         }
5162     }
5163     jobject focusEvent = env->NewObject(focusEventCls, focusEventConst,
5164                                         target, id, JNI_FALSE, jOpposite);
5165     DASSERT(!safe_ExceptionOccurred(env));
5166     DASSERT(focusEvent != NULL);
5167     if (jOpposite != NULL) {
5168         env->DeleteLocalRef(jOpposite); jOpposite = NULL;
5169     }
5170     env->DeleteLocalRef(target); target = NULL;
5171     CHECK_NULL(focusEvent);
5172 
5173     jobject sequencedEvent = env->NewObject(sequencedEventCls,
5174                                             sequencedEventConst,
5175                                             focusEvent);
5176     DASSERT(!safe_ExceptionOccurred(env));
5177     DASSERT(sequencedEvent != NULL);
5178     env->DeleteLocalRef(focusEvent); focusEvent = NULL;
5179     CHECK_NULL(sequencedEvent);
5180     SendEvent(sequencedEvent);
5181 
5182     env->DeleteLocalRef(sequencedEvent);
5183 }
5184 
5185 /*
5186  * Forward a filtered event directly to the subclassed window.
5187  * This method is needed so that DefWindowProc is invoked on the
5188  * component's owning thread.
5189  */
5190 MsgRouting AwtComponent::HandleEvent(MSG *msg, BOOL)
5191 {
5192     DefWindowProc(msg->message, msg->wParam, msg->lParam);
5193     delete msg;
5194     return mrConsume;
5195 }
5196 
5197 /* Post a WM_AWT_HANDLE_EVENT message which invokes HandleEvent
5198    on the toolkit thread. This method may pre-filter the messages. */
5199 BOOL AwtComponent::PostHandleEventMessage(MSG *msg, BOOL synthetic)
5200 {
5201     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5202     // We should cut off keyboard events to disabled components
5203     // to avoid the components responding visually to keystrokes when disabled.
5204     // we shouldn't cut off WM_SYS* messages as they aren't used for normal activity
5205     // but to activate menus, close windows, etc
5206     switch(msg->message) {
5207         case WM_KEYDOWN:
5208         case WM_KEYUP:
5209         case WM_CHAR:
5210         case WM_DEADCHAR:
5211             {
5212                 if (!isRecursivelyEnabled()) {
5213                     goto quit;
5214                 }
5215                 break;
5216             }
5217     }
5218     if (PostMessage(GetHWnd(), WM_AWT_HANDLE_EVENT,
5219         (WPARAM) synthetic, (LPARAM) msg)) {
5220             return TRUE;
5221     } else {
5222         JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5223     }
5224 quit:
5225     delete msg;
5226     return FALSE;
5227 }
5228 
5229 void AwtComponent::SynthesizeKeyMessage(JNIEnv *env, jobject keyEvent)
5230 {
5231     jint id = (env)->GetIntField(keyEvent, AwtAWTEvent::idID);
5232     UINT message;
5233     switch (id) {
5234       case java_awt_event_KeyEvent_KEY_PRESSED:
5235           message = WM_KEYDOWN;
5236           break;
5237       case java_awt_event_KeyEvent_KEY_RELEASED:
5238           message = WM_KEYUP;
5239           break;
5240       case java_awt_event_KeyEvent_KEY_TYPED:
5241           message = WM_CHAR;
5242           break;
5243       default:
5244           return;
5245     }
5246 
5247     /*
5248      * KeyEvent.modifiers aren't supported -- the Java apppwd must send separate
5249      * KEY_PRESSED and KEY_RELEASED events for the modifier virtual keys.
5250      */
5251     if (id == java_awt_event_KeyEvent_KEY_TYPED) {
5252         // WM_CHAR message must be posted using WM_AWT_FORWARD_CHAR
5253         // (for Edit control)
5254         jchar keyChar = (jchar)
5255           (env)->GetCharField(keyEvent, AwtKeyEvent::keyCharID);
5256 
5257         // Bugid 4724007.  If it is a Delete character, don't send the fake
5258         // KEY_TYPED we created back to the native window: Windows doesn't
5259         // expect a WM_CHAR for Delete in TextFields, so it tries to enter a
5260         // character after deleting.
5261         if (keyChar == '\177') { // the Delete character
5262             return;
5263         }
5264 
5265         // Disable forwarding WM_CHAR messages to disabled components
5266         if (isRecursivelyEnabled()) {
5267             if (!::PostMessage(GetHWnd(), WM_AWT_FORWARD_CHAR,
5268                 MAKEWPARAM(keyChar, TRUE), 0)) {
5269                 JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5270             }
5271         }
5272     } else {
5273         jint keyCode =
5274           (env)->GetIntField(keyEvent, AwtKeyEvent::keyCodeID);
5275         UINT key, modifiers;
5276         AwtComponent::JavaKeyToWindowsKey(keyCode, &key, &modifiers);
5277         MSG* msg = CreateMessage(message, key, 0);
5278         PostHandleEventMessage(msg, TRUE);
5279     }
5280 }
5281 
5282 void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent)
5283 {
5284     /*    DebugBreak(); */
5285     jint button = (env)->GetIntField(mouseEvent, AwtMouseEvent::buttonID);
5286     jint modifiers = (env)->GetIntField(mouseEvent, AwtInputEvent::modifiersID);
5287 
5288     WPARAM wParam = 0;
5289     WORD wLow = 0;
5290     jint wheelAmt = 0;
5291     jint id = (env)->GetIntField(mouseEvent, AwtAWTEvent::idID);
5292     UINT message;
5293     switch (id) {
5294       case java_awt_event_MouseEvent_MOUSE_PRESSED: {
5295           switch (button) {
5296             case java_awt_event_MouseEvent_BUTTON1:
5297                 message = WM_LBUTTONDOWN; break;
5298             case java_awt_event_MouseEvent_BUTTON3:
5299                 message = WM_MBUTTONDOWN; break;
5300             case java_awt_event_MouseEvent_BUTTON2:
5301                 message = WM_RBUTTONDOWN; break;
5302             default:
5303                 return;
5304           }
5305           break;
5306       }
5307       case java_awt_event_MouseEvent_MOUSE_RELEASED: {
5308           switch (button) {
5309             case java_awt_event_MouseEvent_BUTTON1:
5310                 message = WM_LBUTTONUP; break;
5311             case java_awt_event_MouseEvent_BUTTON3:
5312                 message = WM_MBUTTONUP; break;
5313             case java_awt_event_MouseEvent_BUTTON2:
5314                 message = WM_RBUTTONUP; break;
5315             default:
5316                 return;
5317           }
5318           break;
5319       }
5320       case java_awt_event_MouseEvent_MOUSE_MOVED:
5321           /* MOUSE_DRAGGED events must first have sent a MOUSE_PRESSED event. */
5322       case java_awt_event_MouseEvent_MOUSE_DRAGGED:
5323           message = WM_MOUSEMOVE;
5324           break;
5325       case java_awt_event_MouseEvent_MOUSE_WHEEL:
5326           if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
5327               wLow |= MK_CONTROL;
5328           }
5329           if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
5330               wLow |= MK_SHIFT;
5331           }
5332           if (modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
5333               wLow |= MK_LBUTTON;
5334           }
5335           if (modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) {
5336               wLow |= MK_RBUTTON;
5337           }
5338           if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) {
5339               wLow |= MK_MBUTTON;
5340           }
5341           if (modifiers & X1_BUTTON) {
5342               wLow |= GetButtonMK(X1_BUTTON);
5343           }
5344           if (modifiers & X2_BUTTON) {
5345               wLow |= GetButtonMK(X2_BUTTON);
5346           }
5347 
5348           wheelAmt = (jint)JNU_CallMethodByName(env,
5349                                                NULL,
5350                                                mouseEvent,
5351                                                "getWheelRotation",
5352                                                "()I").i;
5353           DASSERT(!safe_ExceptionOccurred(env));
5354           JNU_CHECK_EXCEPTION(env);
5355           DTRACE_PRINTLN1("wheelAmt = %i\n", wheelAmt);
5356 
5357           // convert Java wheel amount value to Win32
5358           wheelAmt *= -1 * WHEEL_DELTA;
5359 
5360           message = WM_MOUSEWHEEL;
5361           wParam = MAKEWPARAM(wLow, wheelAmt);
5362 
5363           break;
5364       default:
5365           return;
5366     }
5367     jint x = (env)->GetIntField(mouseEvent, AwtMouseEvent::xID);
5368     jint y = (env)->GetIntField(mouseEvent, AwtMouseEvent::yID);
5369     MSG* msg = CreateMessage(message, wParam, MAKELPARAM(x, y), x, y);
5370     PostHandleEventMessage(msg, TRUE);
5371 }
5372 
5373 BOOL AwtComponent::InheritsNativeMouseWheelBehavior() {return false;}
5374 
5375 void AwtComponent::Invalidate(RECT* r)
5376 {
5377     ::InvalidateRect(GetHWnd(), r, FALSE);
5378 }
5379 
5380 void AwtComponent::BeginValidate()
5381 {
5382     DASSERT(m_validationNestCount >= 0 &&
5383            m_validationNestCount < 1000); // sanity check
5384 
5385     if (m_validationNestCount == 0) {
5386     // begin deferred window positioning if we're not inside
5387     // another Begin/EndValidate pair
5388         DASSERT(m_hdwp == NULL);
5389         m_hdwp = ::BeginDeferWindowPos(32);
5390     }
5391 
5392     m_validationNestCount++;
5393 }
5394 
5395 void AwtComponent::EndValidate()
5396 {
5397     DASSERT(m_validationNestCount > 0 &&
5398            m_validationNestCount < 1000); // sanity check
5399     DASSERT(m_hdwp != NULL);
5400 
5401     m_validationNestCount--;
5402     if (m_validationNestCount == 0) {
5403     // if this call to EndValidate is not nested inside another
5404     // Begin/EndValidate pair, end deferred window positioning
5405         ::EndDeferWindowPos(m_hdwp);
5406         m_hdwp = NULL;
5407     }
5408 }
5409 
5410 /**
5411  * HWND, AwtComponent and Java Peer interaction
5412  */
5413 
5414 /*
5415  *Link the C++, Java peer, and HWNDs together.
5416  */
5417 void AwtComponent::LinkObjects(JNIEnv *env, jobject peer)
5418 {
5419     /*
5420      * Bind all three objects together thru this C++ object, two-way to each:
5421      *     JavaPeer <-> C++ <-> HWND
5422      *
5423      * C++ -> JavaPeer
5424      */
5425     if (m_peerObject == NULL) {
5426         // This may have already been set up by CreateHWnd
5427         // And we don't want to create two references so we
5428         // will leave the prior one alone
5429         m_peerObject = env->NewGlobalRef(peer);
5430     }
5431     /* JavaPeer -> HWND */
5432     env->SetLongField(peer, AwtComponent::hwndID, reinterpret_cast<jlong>(m_hwnd));
5433 
5434     /* JavaPeer -> C++ */
5435     JNI_SET_PDATA(peer, this);
5436 
5437     /* HWND -> C++ */
5438     SetComponentInHWND();
5439 }
5440 
5441 /* Cleanup above linking */
5442 void AwtComponent::UnlinkObjects()
5443 {
5444     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5445     if (m_peerObject) {
5446         env->SetLongField(m_peerObject, AwtComponent::hwndID, 0);
5447         JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL));
5448         JNI_SET_DESTROYED(m_peerObject);
5449         env->DeleteGlobalRef(m_peerObject);
5450         m_peerObject = NULL;
5451     }
5452 }
5453 
5454 void AwtComponent::Enable(BOOL bEnable)
5455 {
5456     if (bEnable && IsTopLevel()) {
5457         // we should not enable blocked toplevels
5458         bEnable = !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()));
5459     }
5460     // Shouldn't trigger native focus change
5461     // (only the proxy may be the native focus owner).
5462     ::EnableWindow(GetHWnd(), bEnable);
5463 
5464     CriticalSection::Lock l(GetLock());
5465     VerifyState();
5466 }
5467 
5468 /*
5469  * associate an AwtDropTarget with this AwtComponent
5470  */
5471 
5472 AwtDropTarget* AwtComponent::CreateDropTarget(JNIEnv* env) {
5473     m_dropTarget = new AwtDropTarget(env, this);
5474     m_dropTarget->RegisterTarget(TRUE);
5475     return m_dropTarget;
5476 }
5477 
5478 /*
5479  * disassociate an AwtDropTarget with this AwtComponent
5480  */
5481 
5482 void AwtComponent::DestroyDropTarget() {
5483     if (m_dropTarget != NULL) {
5484         m_dropTarget->RegisterTarget(FALSE);
5485         m_dropTarget->Release();
5486         m_dropTarget = NULL;
5487     }
5488 }
5489 
5490 BOOL AwtComponent::IsFocusingMouseMessage(MSG *pMsg) {
5491     return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
5492 }
5493 
5494 BOOL AwtComponent::IsFocusingKeyMessage(MSG *pMsg) {
5495     return pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_SPACE;
5496 }
5497 
5498 void AwtComponent::_Show(void *param)
5499 {
5500     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5501 
5502     jobject self = (jobject)param;
5503 
5504     AwtComponent *p;
5505 
5506     PDATA pData;
5507     JNI_CHECK_PEER_GOTO(self, ret);
5508     p = (AwtComponent *)pData;
5509     if (::IsWindow(p->GetHWnd()))
5510     {
5511         p->SendMessage(WM_AWT_COMPONENT_SHOW);
5512     }
5513 ret:
5514     env->DeleteGlobalRef(self);
5515 }
5516 
5517 void AwtComponent::_Hide(void *param)
5518 {
5519     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5520 
5521     jobject self = (jobject)param;
5522 
5523     AwtComponent *p;
5524 
5525     PDATA pData;
5526     JNI_CHECK_PEER_GOTO(self, ret);
5527     p = (AwtComponent *)pData;
5528     if (::IsWindow(p->GetHWnd()))
5529     {
5530         p->SendMessage(WM_AWT_COMPONENT_HIDE);
5531     }
5532 ret:
5533     env->DeleteGlobalRef(self);
5534 }
5535 
5536 void AwtComponent::_Enable(void *param)
5537 {
5538     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5539 
5540     jobject self = (jobject)param;
5541 
5542     AwtComponent *p;
5543 
5544     PDATA pData;
5545     JNI_CHECK_PEER_GOTO(self, ret);
5546     p = (AwtComponent *)pData;
5547     if (::IsWindow(p->GetHWnd()))
5548     {
5549         p->Enable(TRUE);
5550     }
5551 ret:
5552     env->DeleteGlobalRef(self);
5553 }
5554 
5555 void AwtComponent::_Disable(void *param)
5556 {
5557     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5558 
5559     jobject self = (jobject)param;
5560 
5561     AwtComponent *p;
5562 
5563     PDATA pData;
5564     JNI_CHECK_PEER_GOTO(self, ret);
5565     p = (AwtComponent *)pData;
5566     if (::IsWindow(p->GetHWnd()))
5567     {
5568         p->Enable(FALSE);
5569     }
5570 ret:
5571     env->DeleteGlobalRef(self);
5572 }
5573 
5574 jobject AwtComponent::_GetLocationOnScreen(void *param)
5575 {
5576     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5577 
5578     jobject self = (jobject)param;
5579 
5580     jobject result = NULL;
5581     AwtComponent *p;
5582 
5583     PDATA pData;
5584     JNI_CHECK_PEER_GOTO(self, ret);
5585     p = (AwtComponent *)pData;
5586     if (::IsWindow(p->GetHWnd()))
5587     {
5588         RECT rect;
5589         VERIFY(::GetWindowRect(p->GetHWnd(),&rect));
5590         result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
5591             rect.left, rect.top);
5592     }
5593 ret:
5594     env->DeleteGlobalRef(self);
5595 
5596     if (result != NULL)
5597     {
5598         jobject resultGlobalRef = env->NewGlobalRef(result);
5599         env->DeleteLocalRef(result);
5600         return resultGlobalRef;
5601     }
5602     else
5603     {
5604         return NULL;
5605     }
5606 }
5607 
5608 void AwtComponent::_Reshape(void *param)
5609 {
5610     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5611 
5612     ReshapeStruct *rs = (ReshapeStruct*)param;
5613     jobject self = rs->component;
5614     jint x = rs->x;
5615     jint y = rs->y;
5616     jint w = rs->w;
5617     jint h = rs->h;
5618 
5619     AwtComponent *p;
5620 
5621     PDATA pData;
5622     JNI_CHECK_PEER_GOTO(self, ret);
5623     p = (AwtComponent *)pData;
5624     if (::IsWindow(p->GetHWnd()))
5625     {
5626         RECT* r = new RECT;
5627         ::SetRect(r, x, y, x + w, y + h);
5628         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, CHECK_EMBEDDED, (LPARAM)r);
5629     }
5630 ret:
5631     env->DeleteGlobalRef(self);
5632 
5633     delete rs;
5634 }
5635 
5636 void AwtComponent::_ReshapeNoCheck(void *param)
5637 {
5638     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5639 
5640     ReshapeStruct *rs = (ReshapeStruct*)param;
5641     jobject self = rs->component;
5642     jint x = rs->x;
5643     jint y = rs->y;
5644     jint w = rs->w;
5645     jint h = rs->h;
5646 
5647     AwtComponent *p;
5648 
5649     PDATA pData;
5650     JNI_CHECK_PEER_GOTO(self, ret);
5651     p = (AwtComponent *)pData;
5652     if (::IsWindow(p->GetHWnd()))
5653     {
5654         RECT* r = new RECT;
5655         ::SetRect(r, x, y, x + w, y + h);
5656         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, DONT_CHECK_EMBEDDED, (LPARAM)r);
5657     }
5658 ret:
5659     env->DeleteGlobalRef(self);
5660 
5661     delete rs;
5662 }
5663 
5664 void AwtComponent::_NativeHandleEvent(void *param)
5665 {
5666     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5667 
5668     NativeHandleEventStruct *nhes = (NativeHandleEventStruct *)param;
5669     jobject self = nhes->component;
5670     jobject event = nhes->event;
5671 
5672     AwtComponent *p;
5673 
5674     PDATA pData;
5675     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5676     pData = JNI_GET_PDATA(self);
5677     if (pData == NULL) {
5678         env->DeleteGlobalRef(self);
5679         if (event != NULL) {
5680             env->DeleteGlobalRef(event);
5681         }
5682         delete nhes;
5683         return;
5684     }
5685     JNI_CHECK_NULL_GOTO(event, "null AWTEvent", ret);
5686 
5687     p = (AwtComponent *)pData;
5688     if (::IsWindow(p->GetHWnd()))
5689     {
5690         if (env->EnsureLocalCapacity(1) < 0) {
5691             env->DeleteGlobalRef(self);
5692             env->DeleteGlobalRef(event);
5693             delete nhes;
5694             return;
5695         }
5696         jbyteArray bdata = (jbyteArray)(env)->GetObjectField(event, AwtAWTEvent::bdataID);
5697         int id = (env)->GetIntField(event, AwtAWTEvent::idID);
5698         DASSERT(!safe_ExceptionOccurred(env));
5699         if (bdata != 0) {
5700             MSG msg;
5701             (env)->GetByteArrayRegion(bdata, 0, sizeof(MSG), (jbyte *)&msg);
5702             (env)->DeleteLocalRef(bdata);
5703             static BOOL keyDownConsumed = FALSE;
5704             static BOOL bCharChanged = FALSE;
5705             static WCHAR modifiedChar;
5706             WCHAR unicodeChar;
5707 
5708             /* Remember if a KEY_PRESSED event is consumed, as an old model
5709              * program won't consume a subsequent KEY_TYPED event.
5710              */
5711             jboolean consumed =
5712                 (env)->GetBooleanField(event, AwtAWTEvent::consumedID);
5713             DASSERT(!safe_ExceptionOccurred(env));
5714 
5715             if (consumed) {
5716                 keyDownConsumed = (id == java_awt_event_KeyEvent_KEY_PRESSED);
5717                 env->DeleteGlobalRef(self);
5718                 env->DeleteGlobalRef(event);
5719                 delete nhes;
5720                 return;
5721 
5722             } else if (id == java_awt_event_KeyEvent_KEY_PRESSED) {
5723                 // Fix for 6637607: reset consuming
5724                 keyDownConsumed = FALSE;
5725             }
5726 
5727             /* Consume a KEY_TYPED event if a KEY_PRESSED had been, to support
5728              * the old model.
5729              */
5730             if ((id == java_awt_event_KeyEvent_KEY_TYPED) && keyDownConsumed) {
5731                 keyDownConsumed = FALSE;
5732                 env->DeleteGlobalRef(self);
5733                 env->DeleteGlobalRef(event);
5734                 delete nhes;
5735                 return;
5736             }
5737 
5738             /* Modify any event parameters, if necessary. */
5739             if (self && pData &&
5740                 id >= java_awt_event_KeyEvent_KEY_FIRST &&
5741                 id <= java_awt_event_KeyEvent_KEY_LAST) {
5742 
5743                     AwtComponent* p = (AwtComponent*)pData;
5744 
5745                     jint keyCode =
5746                       (env)->GetIntField(event, AwtKeyEvent::keyCodeID);
5747                     jchar keyChar =
5748                       (env)->GetCharField(event, AwtKeyEvent::keyCharID);
5749                     jint modifiers =
5750                       (env)->GetIntField(event, AwtInputEvent::modifiersID);
5751 
5752                     DASSERT(!safe_ExceptionOccurred(env));
5753 
5754                 /* Check to see whether the keyCode or modifiers were changed
5755                    on the keyPressed event, and tweak the following keyTyped
5756                    event (if any) accodingly.  */
5757                 switch (id) {
5758                 case java_awt_event_KeyEvent_KEY_PRESSED:
5759                 {
5760                     UINT winKey = (UINT)msg.wParam;
5761                     bCharChanged = FALSE;
5762 
5763                     if (winKey == VK_PROCESSKEY) {
5764                         // Leave it up to IME
5765                         break;
5766                     }
5767 
5768                     if (keyCode != java_awt_event_KeyEvent_VK_UNDEFINED) {
5769                         UINT newWinKey, ignored;
5770                         p->JavaKeyToWindowsKey(keyCode, &newWinKey, &ignored, winKey);
5771                         if (newWinKey != 0) {
5772                             winKey = newWinKey;
5773                         }
5774                     }
5775 
5776                     BOOL isDeadKey = FALSE;
5777                     modifiedChar = p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE, isDeadKey);
5778                     bCharChanged = (keyChar != modifiedChar);
5779                 }
5780                 break;
5781 
5782                 case java_awt_event_KeyEvent_KEY_RELEASED:
5783                 {
5784                     keyDownConsumed = FALSE;
5785                     bCharChanged = FALSE;
5786                 }
5787                 break;
5788 
5789                 case java_awt_event_KeyEvent_KEY_TYPED:
5790                 {
5791                     if (bCharChanged)
5792                     {
5793                         unicodeChar = modifiedChar;
5794                     }
5795                     else
5796                     {
5797                         unicodeChar = keyChar;
5798                     }
5799                     bCharChanged = FALSE;
5800 
5801                     // Disable forwarding KEY_TYPED messages to peers of
5802                     // disabled components
5803                     if (p->isRecursivelyEnabled()) {
5804                         // send the character back to the native window for
5805                         // processing. The WM_AWT_FORWARD_CHAR handler will send
5806                         // this character to DefWindowProc
5807                         if (!::PostMessage(p->GetHWnd(), WM_AWT_FORWARD_CHAR,
5808                             MAKEWPARAM(unicodeChar, FALSE), msg.lParam)) {
5809                             JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5810                         }
5811                     }
5812                     env->DeleteGlobalRef(self);
5813                     env->DeleteGlobalRef(event);
5814                     delete nhes;
5815                     return;
5816                 }
5817                 break;
5818 
5819                 default:
5820                     break;
5821                 }
5822             }
5823 
5824             // ignore all InputMethodEvents
5825             if (self && (pData = JNI_GET_PDATA(self)) &&
5826                 id >= java_awt_event_InputMethodEvent_INPUT_METHOD_FIRST &&
5827                 id <= java_awt_event_InputMethodEvent_INPUT_METHOD_LAST) {
5828                 env->DeleteGlobalRef(self);
5829                 env->DeleteGlobalRef(event);
5830                 delete nhes;
5831                 return;
5832             }
5833 
5834             // Create copy for local msg
5835             MSG* pCopiedMsg = new MSG;
5836             memmove(pCopiedMsg, &msg, sizeof(MSG));
5837             // Event handler deletes msg
5838             p->PostHandleEventMessage(pCopiedMsg, FALSE);
5839 
5840             env->DeleteGlobalRef(self);
5841             env->DeleteGlobalRef(event);
5842             delete nhes;
5843             return;
5844         }
5845 
5846         /* Forward any valid synthesized events.  Currently only mouse and
5847          * key events are supported.
5848          */
5849         if (self == NULL || (pData = JNI_GET_PDATA(self)) == NULL) {
5850             env->DeleteGlobalRef(self);
5851             env->DeleteGlobalRef(event);
5852             delete nhes;
5853             return;
5854         }
5855 
5856         AwtComponent* p = (AwtComponent*)pData;
5857         if (id >= java_awt_event_KeyEvent_KEY_FIRST &&
5858             id <= java_awt_event_KeyEvent_KEY_LAST) {
5859             p->SynthesizeKeyMessage(env, event);
5860         } else if (id >= java_awt_event_MouseEvent_MOUSE_FIRST &&
5861                    id <= java_awt_event_MouseEvent_MOUSE_LAST) {
5862             p->SynthesizeMouseMessage(env, event);
5863         }
5864     }
5865 
5866 ret:
5867     if (self != NULL) {
5868         env->DeleteGlobalRef(self);
5869     }
5870     if (event != NULL) {
5871         env->DeleteGlobalRef(event);
5872     }
5873 
5874     delete nhes;
5875 }
5876 
5877 void AwtComponent::_SetForeground(void *param)
5878 {
5879     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5880 
5881     SetColorStruct *scs = (SetColorStruct *)param;
5882     jobject self = scs->component;
5883     jint rgb = scs->rgb;
5884 
5885     AwtComponent *c = NULL;
5886 
5887     PDATA pData;
5888     JNI_CHECK_PEER_GOTO(self, ret);
5889     c = (AwtComponent *)pData;
5890     if (::IsWindow(c->GetHWnd()))
5891     {
5892         c->SetColor(PALETTERGB((rgb>>16)&0xff,
5893                                (rgb>>8)&0xff,
5894                                (rgb)&0xff));
5895         c->VerifyState();
5896     }
5897 ret:
5898     env->DeleteGlobalRef(self);
5899 
5900     delete scs;
5901 }
5902 
5903 void AwtComponent::_SetBackground(void *param)
5904 {
5905     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5906 
5907     SetColorStruct *scs = (SetColorStruct *)param;
5908     jobject self = scs->component;
5909     jint rgb = scs->rgb;
5910 
5911     AwtComponent *c = NULL;
5912 
5913     PDATA pData;
5914     JNI_CHECK_PEER_GOTO(self, ret);
5915     c = (AwtComponent *)pData;
5916     if (::IsWindow(c->GetHWnd()))
5917     {
5918         c->SetBackgroundColor(PALETTERGB((rgb>>16)&0xff,
5919                                          (rgb>>8)&0xff,
5920                                          (rgb)&0xff));
5921         c->VerifyState();
5922     }
5923 ret:
5924     env->DeleteGlobalRef(self);
5925 
5926     delete scs;
5927 }
5928 
5929 void AwtComponent::_SetFont(void *param)
5930 {
5931     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5932 
5933     SetFontStruct *sfs = (SetFontStruct *)param;
5934     jobject self = sfs->component;
5935     jobject font = sfs->font;
5936 
5937     AwtComponent *c = NULL;
5938 
5939     PDATA pData;
5940     JNI_CHECK_PEER_GOTO(self, ret);
5941     JNI_CHECK_NULL_GOTO(font, "null font", ret);
5942     c = (AwtComponent *)pData;
5943     if (::IsWindow(c->GetHWnd()))
5944     {
5945         AwtFont *awtFont = (AwtFont *)env->GetLongField(font, AwtFont::pDataID);
5946         if (awtFont == NULL) {
5947             /*arguments of AwtFont::Create are changed for multifont component */
5948             awtFont = AwtFont::Create(env, font);
5949         }
5950         env->SetLongField(font, AwtFont::pDataID, (jlong)awtFont);
5951 
5952         c->SetFont(awtFont);
5953     }
5954 ret:
5955     env->DeleteGlobalRef(self);
5956     env->DeleteGlobalRef(font);
5957 
5958     delete sfs;
5959 }
5960 
5961 // Sets or kills focus for a component.
5962 void AwtComponent::_SetFocus(void *param)
5963 {
5964     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5965 
5966     SetFocusStruct *sfs = (SetFocusStruct *)param;
5967     jobject self = sfs->component;
5968     jboolean doSetFocus = sfs->doSetFocus;
5969 
5970     AwtComponent *c = NULL;
5971 
5972     PDATA pData;
5973     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5974     pData = JNI_GET_PDATA(self);
5975     if (pData == NULL) {
5976         // do nothing just return false
5977         goto ret;
5978     }
5979 
5980     c = (AwtComponent *)pData;
5981     if (::IsWindow(c->GetHWnd())) {
5982         c->SendMessage(WM_AWT_COMPONENT_SETFOCUS, (WPARAM)doSetFocus, 0);
5983     }
5984 ret:
5985     env->DeleteGlobalRef(self);
5986 
5987     delete sfs;
5988 }
5989 
5990 void AwtComponent::_Start(void *param)
5991 {
5992     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5993 
5994     jobject self = (jobject)param;
5995 
5996     AwtComponent *c = NULL;
5997 
5998     PDATA pData;
5999     JNI_CHECK_PEER_GOTO(self, ret);
6000     c = (AwtComponent *)pData;
6001     if (::IsWindow(c->GetHWnd()))
6002     {
6003         jobject target = c->GetTarget(env);
6004 
6005         /* Disable window if specified -- windows are enabled by default. */
6006         jboolean enabled = (jboolean)env->GetBooleanField(target,
6007                                                           AwtComponent::enabledID);
6008         if (!enabled) {
6009             ::EnableWindow(c->GetHWnd(), FALSE);
6010         }
6011 
6012         /* The peer is now ready for callbacks, since this is the last
6013          * initialization call
6014          */
6015         c->EnableCallbacks(TRUE);
6016 
6017         // Fix 4745222: we need to invalidate region since we validated it before initialization.
6018         ::InvalidateRgn(c->GetHWnd(), NULL, FALSE);
6019 
6020         // Fix 4530093: WM_PAINT after EnableCallbacks
6021         ::UpdateWindow(c->GetHWnd());
6022 
6023         env->DeleteLocalRef(target);
6024     }
6025 ret:
6026     env->DeleteGlobalRef(self);
6027 }
6028 
6029 void AwtComponent::_BeginValidate(void *param)
6030 {
6031     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6032     if (AwtToolkit::IsMainThread()) {
6033         jobject self = (jobject)param;
6034         if (self != NULL) {
6035             PDATA pData = JNI_GET_PDATA(self);
6036             if (pData) {
6037                 AwtComponent *c = (AwtComponent *)pData;
6038                 if (::IsWindow(c->GetHWnd())) {
6039                     c->SendMessage(WM_AWT_BEGIN_VALIDATE);
6040                 }
6041             }
6042             env->DeleteGlobalRef(self);
6043         }
6044     } else {
6045         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_BeginValidate, param);
6046     }
6047 }
6048 
6049 void AwtComponent::_EndValidate(void *param)
6050 {
6051     if (AwtToolkit::IsMainThread()) {
6052         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6053         jobject self = (jobject)param;
6054         if (self != NULL) {
6055             PDATA pData = JNI_GET_PDATA(self);
6056             if (pData) {
6057                 AwtComponent *c = (AwtComponent *)pData;
6058                 if (::IsWindow(c->GetHWnd())) {
6059                     c->SendMessage(WM_AWT_END_VALIDATE);
6060                 }
6061             }
6062             env->DeleteGlobalRef(self);
6063         }
6064     } else {
6065         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_EndValidate, param);
6066     }
6067 }
6068 
6069 void AwtComponent::_UpdateWindow(void *param)
6070 {
6071     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6072     if (AwtToolkit::IsMainThread()) {
6073         jobject self = (jobject)param;
6074         AwtComponent *c = NULL;
6075         PDATA pData;
6076         JNI_CHECK_PEER_GOTO(self, ret);
6077         c = (AwtComponent *)pData;
6078         if (::IsWindow(c->GetHWnd())) {
6079             ::UpdateWindow(c->GetHWnd());
6080         }
6081 ret:
6082         env->DeleteGlobalRef(self);
6083     } else {
6084         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_UpdateWindow, param);
6085     }
6086 }
6087 
6088 jlong AwtComponent::_AddNativeDropTarget(void *param)
6089 {
6090     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6091 
6092     jobject self = (jobject)param;
6093 
6094     jlong result = 0;
6095     AwtComponent *c = NULL;
6096 
6097     PDATA pData;
6098     JNI_CHECK_PEER_GOTO(self, ret);
6099     c = (AwtComponent *)pData;
6100     if (::IsWindow(c->GetHWnd()))
6101     {
6102         result = (jlong)(c->CreateDropTarget(env));
6103     }
6104 ret:
6105     env->DeleteGlobalRef(self);
6106 
6107     return result;
6108 }
6109 
6110 void AwtComponent::_RemoveNativeDropTarget(void *param)
6111 {
6112     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6113 
6114     jobject self = (jobject)param;
6115 
6116     AwtComponent *c = NULL;
6117 
6118     PDATA pData;
6119     JNI_CHECK_PEER_GOTO(self, ret);
6120     c = (AwtComponent *)pData;
6121     if (::IsWindow(c->GetHWnd()))
6122     {
6123         c->DestroyDropTarget();
6124     }
6125 ret:
6126     env->DeleteGlobalRef(self);
6127 }
6128 
6129 jintArray AwtComponent::_CreatePrintedPixels(void *param)
6130 {
6131     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6132 
6133     CreatePrintedPixelsStruct *cpps = (CreatePrintedPixelsStruct *)param;
6134     jobject self = cpps->component;
6135 
6136     jintArray result = NULL;
6137     AwtComponent *c = NULL;
6138 
6139     PDATA pData;
6140     JNI_CHECK_PEER_GOTO(self, ret);
6141     c = (AwtComponent *)pData;
6142     if (::IsWindow(c->GetHWnd()))
6143     {
6144         result = (jintArray)c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)cpps, 0);
6145     }
6146 ret:
6147     env->DeleteGlobalRef(self);
6148 
6149     delete cpps;
6150     return result; // this reference is global
6151 }
6152 
6153 jboolean AwtComponent::_IsObscured(void *param)
6154 {
6155     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6156 
6157     jobject self = (jobject)param;
6158 
6159     jboolean result = JNI_FALSE;
6160     AwtComponent *c = NULL;
6161 
6162     PDATA pData;
6163     JNI_CHECK_PEER_GOTO(self, ret);
6164 
6165     c = (AwtComponent *)pData;
6166 
6167     if (::IsWindow(c->GetHWnd()))
6168     {
6169         HWND hWnd = c->GetHWnd();
6170         HDC hDC = ::GetDC(hWnd);
6171         RECT clipbox;
6172         int callresult = ::GetClipBox(hDC, &clipbox);
6173         switch(callresult) {
6174             case NULLREGION :
6175                 result = JNI_FALSE;
6176                 break;
6177             case SIMPLEREGION : {
6178                 RECT windowRect;
6179                 if (!::GetClientRect(hWnd, &windowRect)) {
6180                     result = JNI_TRUE;
6181                 } else {
6182                     result  = (jboolean)((clipbox.bottom != windowRect.bottom)
6183                         || (clipbox.left != windowRect.left)
6184                         || (clipbox.right != windowRect.right)
6185                         || (clipbox.top != windowRect.top));
6186                 }
6187                 break;
6188             }
6189             case COMPLEXREGION :
6190             default :
6191                 result = JNI_TRUE;
6192                 break;
6193         }
6194         ::ReleaseDC(hWnd, hDC);
6195     }
6196 ret:
6197     env->DeleteGlobalRef(self);
6198 
6199     return result;
6200 }
6201 
6202 jboolean AwtComponent::_NativeHandlesWheelScrolling(void *param)
6203 {
6204     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6205 
6206     jobject self = (jobject)param;
6207 
6208     jboolean result = JNI_FALSE;
6209     AwtComponent *c = NULL;
6210 
6211     PDATA pData;
6212     JNI_CHECK_PEER_GOTO(self, ret);
6213     c = (AwtComponent *)pData;
6214     if (::IsWindow(c->GetHWnd()))
6215     {
6216         result = JNI_IS_TRUE(c->InheritsNativeMouseWheelBehavior());
6217     }
6218 ret:
6219     env->DeleteGlobalRef(self);
6220 
6221     return result;
6222 }
6223 
6224 void AwtComponent::_SetParent(void * param)
6225 {
6226     if (AwtToolkit::IsMainThread()) {
6227         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6228         SetParentStruct *data = (SetParentStruct*) param;
6229         jobject self = data->component;
6230         jobject parent = data->parentComp;
6231 
6232         AwtComponent *awtComponent = NULL;
6233         AwtComponent *awtParent = NULL;
6234 
6235         PDATA pData;
6236         JNI_CHECK_PEER_GOTO(self, ret);
6237         awtComponent = (AwtComponent *)pData;
6238         JNI_CHECK_PEER_GOTO(parent, ret);
6239         awtParent = (AwtComponent *)pData;
6240 
6241         HWND selfWnd = awtComponent->GetHWnd();
6242         HWND parentWnd = awtParent->GetHWnd();
6243         if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) {
6244             // Shouldn't trigger native focus change
6245             // (only the proxy may be the native focus owner).
6246             ::SetParent(selfWnd, parentWnd);
6247         }
6248 ret:
6249         env->DeleteGlobalRef(self);
6250         env->DeleteGlobalRef(parent);
6251         delete data;
6252     } else {
6253         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetParent, param);
6254     }
6255 }
6256 
6257 void AwtComponent::_SetRectangularShape(void *param)
6258 {
6259     if (!AwtToolkit::IsMainThread()) {
6260         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetRectangularShape, param);
6261     } else {
6262         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6263 
6264         SetRectangularShapeStruct *data = (SetRectangularShapeStruct *)param;
6265         jobject self = data->component;
6266         jint x1 = data->x1;
6267         jint x2 = data->x2;
6268         jint y1 = data->y1;
6269         jint y2 = data->y2;
6270         jobject region = data->region;
6271 
6272         AwtComponent *c = NULL;
6273 
6274         PDATA pData;
6275         JNI_CHECK_PEER_GOTO(self, ret);
6276 
6277         c = (AwtComponent *)pData;
6278         if (::IsWindow(c->GetHWnd())) {
6279             HRGN hRgn = NULL;
6280 
6281             // If all the params are zeros, the shape must be simply reset.
6282             // Otherwise, convert it into a region.
6283             if (region || x1 || x2 || y1 || y2) {
6284                 RECT_T rects[256];
6285                 RECT_T *pRect = rects;
6286 
6287                 const int numrects = RegionToYXBandedRectangles(env, x1, y1, x2, y2,
6288                         region, &pRect, sizeof(rects)/sizeof(rects[0]));
6289                 if (!pRect) {
6290                     // RegionToYXBandedRectangles doesn't use safe_Malloc(),
6291                     // so throw the exception explicitly
6292                     throw std::bad_alloc();
6293                 }
6294 
6295                 RGNDATA *pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc,
6296                         sizeof(RGNDATAHEADER), sizeof(RECT_T), numrects);
6297                 memcpy((BYTE*)pRgnData + sizeof(RGNDATAHEADER), pRect, sizeof(RECT_T) * numrects);
6298                 if (pRect != rects) {
6299                     free(pRect);
6300                 }
6301                 pRect = NULL;
6302 
6303                 RGNDATAHEADER *pRgnHdr = (RGNDATAHEADER *) pRgnData;
6304                 pRgnHdr->dwSize = sizeof(RGNDATAHEADER);
6305                 pRgnHdr->iType = RDH_RECTANGLES;
6306                 pRgnHdr->nRgnSize = 0;
6307                 pRgnHdr->rcBound.top = 0;
6308                 pRgnHdr->rcBound.left = 0;
6309                 pRgnHdr->rcBound.bottom = LONG(y2 - y1);
6310                 pRgnHdr->rcBound.right = LONG(x2 - x1);
6311                 pRgnHdr->nCount = numrects;
6312 
6313                 hRgn = ::ExtCreateRegion(NULL,
6314                         sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, pRgnData);
6315 
6316                 free(pRgnData);
6317             }
6318 
6319             ::SetWindowRgn(c->GetHWnd(), hRgn, TRUE);
6320         }
6321 
6322 ret:
6323         env->DeleteGlobalRef(self);
6324         if (region) {
6325             env->DeleteGlobalRef(region);
6326         }
6327 
6328         delete data;
6329     }
6330 }
6331 
6332 void AwtComponent::_SetZOrder(void *param) {
6333     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6334 
6335     SetZOrderStruct *data = (SetZOrderStruct *)param;
6336     jobject self = data->component;
6337     HWND above = HWND_TOP;
6338     if (data->above != 0) {
6339         above = reinterpret_cast<HWND>(data->above);
6340     }
6341 
6342     AwtComponent *c = NULL;
6343 
6344     PDATA pData;
6345     JNI_CHECK_PEER_GOTO(self, ret);
6346 
6347     c = (AwtComponent *)pData;
6348     if (::IsWindow(c->GetHWnd())) {
6349         ::SetWindowPos(c->GetHWnd(), above, 0, 0, 0, 0,
6350                        SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS);
6351     }
6352 
6353 ret:
6354     env->DeleteGlobalRef(self);
6355 
6356     delete data;
6357 }
6358 
6359 void AwtComponent::PostUngrabEvent() {
6360     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6361     jobject target = GetTarget(env);
6362     jobject event = JNU_NewObjectByName(env, "sun/awt/UngrabEvent", "(Ljava/awt/Component;)V",
6363                                         target);
6364     if (safe_ExceptionOccurred(env)) {
6365         env->ExceptionDescribe();
6366         env->ExceptionClear();
6367     }
6368     env->DeleteLocalRef(target);
6369     if (event != NULL) {
6370         SendEvent(event);
6371         env->DeleteLocalRef(event);
6372     }
6373 }
6374 
6375 void AwtComponent::SetFocusedWindow(HWND window)
6376 {
6377     HWND old = sm_focusedWindow;
6378     sm_focusedWindow = window;
6379 
6380     AwtWindow::FocusedWindowChanged(old, window);
6381 }
6382 
6383 /************************************************************************
6384  * Component native methods
6385  */
6386 
6387 extern "C" {
6388 
6389 /**
6390  * This method is called from the WGL pipeline when it needs to retrieve
6391  * the HWND associated with a ComponentPeer's C++ level object.
6392  */
6393 HWND
6394 AwtComponent_GetHWnd(JNIEnv *env, jlong pData)
6395 {
6396     AwtComponent *p = (AwtComponent *)jlong_to_ptr(pData);
6397     if (p == NULL) {
6398         return (HWND)0;
6399     }
6400     return p->GetHWnd();
6401 }
6402 
6403 static void _GetInsets(void* param)
6404 {
6405     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6406 
6407     GetInsetsStruct *gis = (GetInsetsStruct *)param;
6408     jobject self = gis->window;
6409 
6410     gis->insets->left = gis->insets->top =
6411         gis->insets->right = gis->insets->bottom = 0;
6412 
6413     PDATA pData;
6414     JNI_CHECK_PEER_GOTO(self, ret);
6415     AwtComponent *component = (AwtComponent *)pData;
6416 
6417     component->GetInsets(gis->insets);
6418 
6419   ret:
6420     env->DeleteGlobalRef(self);
6421     delete gis;
6422 }
6423 
6424 /**
6425  * This method is called from the WGL pipeline when it needs to retrieve
6426  * the insets associated with a ComponentPeer's C++ level object.
6427  */
6428 void AwtComponent_GetInsets(JNIEnv *env, jobject peer, RECT *insets)
6429 {
6430     TRY;
6431 
6432     GetInsetsStruct *gis = new GetInsetsStruct;
6433     gis->window = env->NewGlobalRef(peer);
6434     gis->insets = insets;
6435 
6436     AwtToolkit::GetInstance().InvokeFunction(_GetInsets, gis);
6437     // global refs and mds are deleted in _UpdateWindow
6438 
6439     CATCH_BAD_ALLOC;
6440 
6441 }
6442 
6443 JNIEXPORT void JNICALL
6444 Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls)
6445 {
6446     TRY;
6447     jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent");
6448     CHECK_NULL(inputEventClazz);
6449     jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I");
6450     CHECK_NULL(getButtonDownMasksID);
6451     jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID);
6452     jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE);
6453     CHECK_NULL(tmp);
6454     jsize len = env->GetArrayLength(obj);
6455     AwtComponent::masks = SAFE_SIZE_NEW_ARRAY(jint, len);
6456     for (int i = 0; i < len; i++) {
6457         AwtComponent::masks[i] = tmp[i];
6458     }
6459     env->ReleaseIntArrayElements(obj, tmp, 0);
6460     env->DeleteLocalRef(obj);
6461 
6462     /* class ids */
6463     jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer");
6464 
6465     DASSERT(peerCls);
6466     CHECK_NULL(peerCls);
6467 
6468     /* field ids */
6469     AwtComponent::peerID =
6470       env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;");
6471     DASSERT(AwtComponent::peerID);
6472     CHECK_NULL(AwtComponent::peerID);
6473 
6474     AwtComponent::xID = env->GetFieldID(cls, "x", "I");
6475     DASSERT(AwtComponent::xID);
6476     CHECK_NULL(AwtComponent::xID);
6477 
6478     AwtComponent::yID = env->GetFieldID(cls, "y", "I");
6479     DASSERT(AwtComponent::yID);
6480     CHECK_NULL(AwtComponent::yID);
6481 
6482     AwtComponent::heightID = env->GetFieldID(cls, "height", "I");
6483     DASSERT(AwtComponent::heightID);
6484     CHECK_NULL(AwtComponent::heightID);
6485 
6486     AwtComponent::widthID = env->GetFieldID(cls, "width", "I");
6487     DASSERT(AwtComponent::widthID);
6488     CHECK_NULL(AwtComponent::widthID);
6489 
6490     AwtComponent::visibleID = env->GetFieldID(cls, "visible", "Z");
6491     DASSERT(AwtComponent::visibleID);
6492     CHECK_NULL(AwtComponent::visibleID);
6493 
6494     AwtComponent::backgroundID =
6495         env->GetFieldID(cls, "background", "Ljava/awt/Color;");
6496     DASSERT(AwtComponent::backgroundID);
6497     CHECK_NULL(AwtComponent::backgroundID);
6498 
6499     AwtComponent::foregroundID =
6500         env->GetFieldID(cls, "foreground", "Ljava/awt/Color;");
6501     DASSERT(AwtComponent::foregroundID);
6502     CHECK_NULL(AwtComponent::foregroundID);
6503 
6504     AwtComponent::enabledID = env->GetFieldID(cls, "enabled", "Z");
6505     DASSERT(AwtComponent::enabledID);
6506     CHECK_NULL(AwtComponent::enabledID);
6507 
6508     AwtComponent::parentID = env->GetFieldID(cls, "parent", "Ljava/awt/Container;");
6509     DASSERT(AwtComponent::parentID);
6510     CHECK_NULL(AwtComponent::parentID);
6511 
6512     AwtComponent::graphicsConfigID =
6513      env->GetFieldID(cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;");
6514     DASSERT(AwtComponent::graphicsConfigID);
6515     CHECK_NULL(AwtComponent::graphicsConfigID);
6516 
6517     AwtComponent::focusableID = env->GetFieldID(cls, "focusable", "Z");
6518     DASSERT(AwtComponent::focusableID);
6519     CHECK_NULL(AwtComponent::focusableID);
6520 
6521     AwtComponent::appContextID = env->GetFieldID(cls, "appContext",
6522                                                  "Lsun/awt/AppContext;");
6523     DASSERT(AwtComponent::appContextID);
6524     CHECK_NULL(AwtComponent::appContextID);
6525 
6526     AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig",
6527                                         "Lsun/awt/Win32GraphicsConfig;");
6528     DASSERT(AwtComponent::peerGCID);
6529     CHECK_NULL(AwtComponent::peerGCID);
6530 
6531     AwtComponent::hwndID = env->GetFieldID(peerCls, "hwnd", "J");
6532     DASSERT(AwtComponent::hwndID);
6533     CHECK_NULL(AwtComponent::hwndID);
6534 
6535     AwtComponent::cursorID = env->GetFieldID(cls, "cursor", "Ljava/awt/Cursor;");
6536     DASSERT(AwtComponent::cursorID);
6537     CHECK_NULL(AwtComponent::cursorID);
6538 
6539     /* method ids */
6540     AwtComponent::getFontMID =
6541         env->GetMethodID(cls, "getFont_NoClientCode", "()Ljava/awt/Font;");
6542     DASSERT(AwtComponent::getFontMID);
6543     CHECK_NULL(AwtComponent::getFontMID);
6544 
6545     AwtComponent::getToolkitMID =
6546         env->GetMethodID(cls, "getToolkitImpl", "()Ljava/awt/Toolkit;");
6547     DASSERT(AwtComponent::getToolkitMID);
6548     CHECK_NULL(AwtComponent::getToolkitMID);
6549 
6550     AwtComponent::isEnabledMID = env->GetMethodID(cls, "isEnabledImpl", "()Z");
6551     DASSERT(AwtComponent::isEnabledMID);
6552     CHECK_NULL(AwtComponent::isEnabledMID);
6553 
6554     AwtComponent::getLocationOnScreenMID =
6555         env->GetMethodID(cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;");
6556     DASSERT(AwtComponent::getLocationOnScreenMID);
6557     CHECK_NULL(AwtComponent::getLocationOnScreenMID);
6558 
6559     AwtComponent::replaceSurfaceDataMID =
6560         env->GetMethodID(peerCls, "replaceSurfaceData", "()V");
6561     DASSERT(AwtComponent::replaceSurfaceDataMID);
6562     CHECK_NULL(AwtComponent::replaceSurfaceDataMID);
6563 
6564     AwtComponent::replaceSurfaceDataLaterMID =
6565         env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V");
6566     DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
6567     CHECK_NULL(AwtComponent::replaceSurfaceDataLaterMID);
6568 
6569     AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
6570     DASSERT(AwtComponent::disposeLaterMID);
6571     CHECK_NULL(AwtComponent::disposeLaterMID);
6572 
6573     CATCH_BAD_ALLOC;
6574 }
6575 
6576 } /* extern "C" */
6577 
6578 
6579 /************************************************************************
6580  * ComponentPeer native methods
6581  */
6582 
6583 extern "C" {
6584 
6585 /*
6586  * Class:     sun_awt_windows_WComponentPeer
6587  * Method:    pShow
6588  * Signature: ()V
6589  */
6590 JNIEXPORT void JNICALL
6591 Java_sun_awt_windows_WComponentPeer_pShow(JNIEnv *env, jobject self)
6592 {
6593     TRY;
6594 
6595     jobject selfGlobalRef = env->NewGlobalRef(self);
6596 
6597     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Show, (void *)selfGlobalRef);
6598     // selfGlobalRef is deleted in _Show
6599 
6600     CATCH_BAD_ALLOC;
6601 }
6602 
6603 /*
6604  * Class:     sun_awt_windows_WComponentPeer
6605  * Method:    hide
6606  * Signature: ()V
6607  */
6608 JNIEXPORT void JNICALL
6609 Java_sun_awt_windows_WComponentPeer_hide(JNIEnv *env, jobject self)
6610 {
6611     TRY;
6612 
6613     jobject selfGlobalRef = env->NewGlobalRef(self);
6614 
6615     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Hide, (void *)selfGlobalRef);
6616     // selfGlobalRef is deleted in _Hide
6617 
6618     CATCH_BAD_ALLOC;
6619 }
6620 
6621 /*
6622  * Class:     sun_awt_windows_WComponentPeer
6623  * Method:    enable
6624  * Signature: ()V
6625  */
6626 JNIEXPORT void JNICALL
6627 Java_sun_awt_windows_WComponentPeer_enable(JNIEnv *env, jobject self)
6628 {
6629     TRY;
6630 
6631     jobject selfGlobalRef = env->NewGlobalRef(self);
6632 
6633     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Enable, (void *)selfGlobalRef);
6634     // selfGlobalRef is deleted in _Enable
6635 
6636     CATCH_BAD_ALLOC;
6637 }
6638 
6639 /*
6640  * Class:     sun_awt_windows_WComponentPeer
6641  * Method:    disable
6642  * Signature: ()V
6643  */
6644 JNIEXPORT void JNICALL
6645 Java_sun_awt_windows_WComponentPeer_disable(JNIEnv *env, jobject self)
6646 {
6647     TRY;
6648 
6649     jobject selfGlobalRef = env->NewGlobalRef(self);
6650 
6651     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Disable, (void *)selfGlobalRef);
6652     // selfGlobalRef is deleted in _Disable
6653 
6654     CATCH_BAD_ALLOC;
6655 }
6656 
6657 /*
6658  * Class:     sun_awt_windows_WComponentPeer
6659  * Method:    getLocationOnScreen
6660  * Signature: ()Ljava/awt/Point;
6661  */
6662 JNIEXPORT jobject JNICALL
6663 Java_sun_awt_windows_WComponentPeer_getLocationOnScreen(JNIEnv *env, jobject self)
6664 {
6665     TRY;
6666 
6667     jobject selfGlobalRef = env->NewGlobalRef(self);
6668 
6669     jobject resultGlobalRef = (jobject)AwtToolkit::GetInstance().SyncCall(
6670         (void*(*)(void*))AwtComponent::_GetLocationOnScreen, (void *)selfGlobalRef);
6671     // selfGlobalRef is deleted in _GetLocationOnScreen
6672     if (resultGlobalRef != NULL)
6673     {
6674         jobject resultLocalRef = env->NewLocalRef(resultGlobalRef);
6675         env->DeleteGlobalRef(resultGlobalRef);
6676         return resultLocalRef;
6677     }
6678 
6679     return NULL;
6680 
6681     CATCH_BAD_ALLOC_RET(NULL);
6682 }
6683 
6684 /*
6685  * Class:     sun_awt_windows_WComponentPeer
6686  * Method:    reshape
6687  * Signature: (IIII)V
6688  */
6689 JNIEXPORT void JNICALL
6690 Java_sun_awt_windows_WComponentPeer_reshape(JNIEnv *env, jobject self,
6691                                             jint x, jint y, jint w, jint h)
6692 {
6693     TRY;
6694 
6695     ReshapeStruct *rs = new ReshapeStruct;
6696     rs->component = env->NewGlobalRef(self);
6697     rs->x = x;
6698     rs->y = y;
6699     rs->w = w;
6700     rs->h = h;
6701 
6702     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Reshape, rs);
6703     // global ref and rs are deleted in _Reshape
6704 
6705     CATCH_BAD_ALLOC;
6706 }
6707 
6708 /*
6709  * Class:     sun_awt_windows_WComponentPeer
6710  * Method:    reshape
6711  * Signature: (IIII)V
6712  */
6713 JNIEXPORT void JNICALL
6714 Java_sun_awt_windows_WComponentPeer_reshapeNoCheck(JNIEnv *env, jobject self,
6715                                             jint x, jint y, jint w, jint h)
6716 {
6717     TRY;
6718 
6719     ReshapeStruct *rs = new ReshapeStruct;
6720     rs->component = env->NewGlobalRef(self);
6721     rs->x = x;
6722     rs->y = y;
6723     rs->w = w;
6724     rs->h = h;
6725 
6726     AwtToolkit::GetInstance().SyncCall(AwtComponent::_ReshapeNoCheck, rs);
6727     // global ref and rs are deleted in _ReshapeNoCheck
6728 
6729     CATCH_BAD_ALLOC;
6730 }
6731 
6732 
6733 /*
6734  * Class:     sun_awt_windows_WComponentPeer
6735  * Method:    nativeHandleEvent
6736  * Signature: (Ljava/awt/AWTEvent;)V
6737  */
6738 JNIEXPORT void JNICALL
6739 Java_sun_awt_windows_WComponentPeer_nativeHandleEvent(JNIEnv *env,
6740                                                       jobject self,
6741                                                       jobject event)
6742 {
6743     TRY;
6744 
6745     jobject selfGlobalRef = env->NewGlobalRef(self);
6746     jobject eventGlobalRef = env->NewGlobalRef(event);
6747 
6748     NativeHandleEventStruct *nhes = new NativeHandleEventStruct;
6749     nhes->component = selfGlobalRef;
6750     nhes->event = eventGlobalRef;
6751 
6752     AwtToolkit::GetInstance().SyncCall(AwtComponent::_NativeHandleEvent, nhes);
6753     // global refs and nhes are deleted in _NativeHandleEvent
6754 
6755     CATCH_BAD_ALLOC;
6756 }
6757 
6758 /*
6759  * Class:     sun_awt_windows_WComponentPeer
6760  * Method:    _dispose
6761  * Signature: ()V
6762  */
6763 JNIEXPORT void JNICALL
6764 Java_sun_awt_windows_WComponentPeer__1dispose(JNIEnv *env, jobject self)
6765 {
6766     TRY_NO_HANG;
6767 
6768     AwtObject::_Dispose(self);
6769 
6770     CATCH_BAD_ALLOC;
6771 }
6772 
6773 /*
6774  * Class:     sun_awt_windows_WComponentPeer
6775  * Method:    _setForeground
6776  * Signature: (I)V
6777  */
6778 JNIEXPORT void JNICALL
6779 Java_sun_awt_windows_WComponentPeer__1setForeground(JNIEnv *env, jobject self,
6780                                                     jint rgb)
6781 {
6782     TRY;
6783 
6784     jobject selfGlobalRef = env->NewGlobalRef(self);
6785 
6786     SetColorStruct *scs = new SetColorStruct;
6787     scs->component = selfGlobalRef;
6788     scs->rgb = rgb;
6789 
6790     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetForeground, scs);
6791     // selfGlobalRef and scs are deleted in _SetForeground()
6792 
6793     CATCH_BAD_ALLOC;
6794 }
6795 
6796 /*
6797  * Class:     sun_awt_windows_WComponentPeer
6798  * Method:    _setBackground
6799  * Signature: (I)V
6800  */
6801 JNIEXPORT void JNICALL
6802 Java_sun_awt_windows_WComponentPeer__1setBackground(JNIEnv *env, jobject self,
6803                                                     jint rgb)
6804 {
6805     TRY;
6806 
6807     jobject selfGlobalRef = env->NewGlobalRef(self);
6808 
6809     SetColorStruct *scs = new SetColorStruct;
6810     scs->component = selfGlobalRef;
6811     scs->rgb = rgb;
6812 
6813     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetBackground, scs);
6814     // selfGlobalRef and scs are deleted in _SetBackground()
6815 
6816     CATCH_BAD_ALLOC;
6817 }
6818 
6819 /*
6820  * Class:     sun_awt_windows_WComponentPeer
6821  * Method:    _setFont
6822  * Signature: (Ljava/awt/Font;)V
6823  */
6824 JNIEXPORT void JNICALL
6825 Java_sun_awt_windows_WComponentPeer__1setFont(JNIEnv *env, jobject self,
6826                         jobject font)
6827 {
6828     TRY;
6829 
6830     jobject selfGlobalRef = env->NewGlobalRef(self);
6831     jobject fontGlobalRef = env->NewGlobalRef(font);
6832 
6833     SetFontStruct *sfs = new SetFontStruct;
6834     sfs->component = selfGlobalRef;
6835     sfs->font = fontGlobalRef;
6836 
6837     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetFont, sfs);
6838     // global refs and sfs are deleted in _SetFont()
6839 
6840     CATCH_BAD_ALLOC;
6841 }
6842 
6843 /*
6844  * Class:     sun_awt_windows_WComponentPeer
6845  * Method:    focusGained
6846  * Signature: (Z)
6847  */
6848 JNIEXPORT void JNICALL Java_sun_awt_windows_WComponentPeer_setFocus
6849     (JNIEnv *env, jobject self, jboolean doSetFocus)
6850 {
6851     TRY;
6852 
6853     jobject selfGlobalRef = env->NewGlobalRef(self);
6854 
6855     SetFocusStruct *sfs = new SetFocusStruct;
6856     sfs->component = selfGlobalRef;
6857     sfs->doSetFocus = doSetFocus;
6858 
6859     AwtToolkit::GetInstance().SyncCall(
6860         (void*(*)(void*))AwtComponent::_SetFocus, sfs);
6861     // global refs and self are deleted in _SetFocus
6862 
6863     CATCH_BAD_ALLOC;
6864 }
6865 
6866 /*
6867  * Class:     sun_awt_windows_WComponentPeer
6868  * Method:    start
6869  * Signature: ()V
6870  */
6871 JNIEXPORT void JNICALL
6872 Java_sun_awt_windows_WComponentPeer_start(JNIEnv *env, jobject self)
6873 {
6874     TRY;
6875 
6876     jobject selfGlobalRef = env->NewGlobalRef(self);
6877 
6878     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Start, (void *)selfGlobalRef);
6879     // selfGlobalRef is deleted in _Start
6880 
6881     CATCH_BAD_ALLOC;
6882 }
6883 
6884 /*
6885  * Class:     sun_awt_windows_WComponentPeer
6886  * Method:    beginValidate
6887  * Signature: ()V
6888  */
6889 JNIEXPORT void JNICALL
6890 Java_sun_awt_windows_WComponentPeer_beginValidate(JNIEnv *env, jobject self)
6891 {
6892     TRY;
6893 
6894     jobject selfGlobalRef = env->NewGlobalRef(self);
6895 
6896     AwtToolkit::GetInstance().SyncCall(AwtComponent::_BeginValidate, (void *)selfGlobalRef);
6897     // selfGlobalRef is deleted in _BeginValidate
6898 
6899     CATCH_BAD_ALLOC;
6900 }
6901 
6902 /*
6903  * Class:     sun_awt_windows_WComponentPeer
6904  * Method:    endValidate
6905  * Signature: ()V
6906  */
6907 JNIEXPORT void JNICALL
6908 Java_sun_awt_windows_WComponentPeer_endValidate(JNIEnv *env, jobject self)
6909 {
6910     TRY;
6911 
6912     jobject selfGlobalRef = env->NewGlobalRef(self);
6913 
6914     AwtToolkit::GetInstance().SyncCall(AwtComponent::_EndValidate, (void *)selfGlobalRef);
6915     // selfGlobalRef is deleted in _EndValidate
6916 
6917     CATCH_BAD_ALLOC;
6918 }
6919 
6920 JNIEXPORT void JNICALL
6921 Java_sun_awt_windows_WComponentPeer_updateWindow(JNIEnv *env, jobject self)
6922 {
6923     TRY;
6924 
6925     jobject selfGlobalRef = env->NewGlobalRef(self);
6926 
6927     AwtToolkit::GetInstance().SyncCall(AwtComponent::_UpdateWindow, (void *)selfGlobalRef);
6928     // selfGlobalRef is deleted in _UpdateWindow
6929 
6930     CATCH_BAD_ALLOC;
6931 }
6932 
6933 /*
6934  * Class:     sun_awt_windows_WComponentPeer
6935  * Method:    addNativeDropTarget
6936  * Signature: ()L
6937  */
6938 
6939 JNIEXPORT jlong JNICALL
6940 Java_sun_awt_windows_WComponentPeer_addNativeDropTarget(JNIEnv *env,
6941                                                         jobject self)
6942 {
6943     TRY;
6944 
6945     jobject selfGlobalRef = env->NewGlobalRef(self);
6946 
6947     return ptr_to_jlong(AwtToolkit::GetInstance().SyncCall(
6948         (void*(*)(void*))AwtComponent::_AddNativeDropTarget,
6949         (void *)selfGlobalRef));
6950     // selfGlobalRef is deleted in _AddNativeDropTarget
6951 
6952     CATCH_BAD_ALLOC_RET(0);
6953 }
6954 
6955 /*
6956  * Class:     sun_awt_windows_WComponentPeer
6957  * Method:    removeNativeDropTarget
6958  * Signature: ()V
6959  */
6960 
6961 JNIEXPORT void JNICALL
6962 Java_sun_awt_windows_WComponentPeer_removeNativeDropTarget(JNIEnv *env,
6963                                                            jobject self)
6964 {
6965     TRY;
6966 
6967     jobject selfGlobalRef = env->NewGlobalRef(self);
6968 
6969     AwtToolkit::GetInstance().SyncCall(
6970         AwtComponent::_RemoveNativeDropTarget, (void *)selfGlobalRef);
6971     // selfGlobalRef is deleted in _RemoveNativeDropTarget
6972 
6973     CATCH_BAD_ALLOC;
6974 }
6975 
6976 /*
6977  * Class:     sun_awt_windows_WComponentPeer
6978  * Method:    getTargetGC
6979  * Signature: ()Ljava/awt/GraphicsConfiguration;
6980  */
6981 JNIEXPORT jobject JNICALL
6982 Java_sun_awt_windows_WComponentPeer_getTargetGC(JNIEnv* env, jobject theThis)
6983 {
6984     TRY;
6985 
6986     jobject targetObj;
6987     jobject gc = 0;
6988 
6989     targetObj = env->GetObjectField(theThis, AwtObject::targetID);
6990     DASSERT(targetObj);
6991 
6992     gc = env->GetObjectField(targetObj, AwtComponent::graphicsConfigID);
6993     return gc;
6994 
6995     CATCH_BAD_ALLOC_RET(NULL);
6996 }
6997 
6998 /*
6999  * Class:     sun_awt_windows_WComponentPeer
7000  * Method:    createPrintedPixels
7001  * Signature: (IIIIII)I[
7002  */
7003 JNIEXPORT jintArray JNICALL
7004 Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env,
7005     jobject self, jint srcX, jint srcY, jint srcW, jint srcH, jint alpha)
7006 {
7007     TRY;
7008 
7009     jobject selfGlobalRef = env->NewGlobalRef(self);
7010 
7011     CreatePrintedPixelsStruct *cpps = new CreatePrintedPixelsStruct;
7012     cpps->component = selfGlobalRef;
7013     cpps->srcx = srcX;
7014     cpps->srcy = srcY;
7015     cpps->srcw = srcW;
7016     cpps->srch = srcH;
7017     cpps->alpha = alpha;
7018 
7019     jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall(
7020         (void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps);
7021     // selfGlobalRef and cpps are deleted in _CreatePrintedPixels
7022     if (globalRef != NULL)
7023     {
7024         jintArray localRef = (jintArray)env->NewLocalRef(globalRef);
7025         env->DeleteGlobalRef(globalRef);
7026         return localRef;
7027     }
7028     else
7029     {
7030         return NULL;
7031     }
7032 
7033     CATCH_BAD_ALLOC_RET(NULL);
7034 }
7035 
7036 /*
7037  * Class:     sun_awt_windows_WComponentPeer
7038  * Method:    nativeHandlesWheelScrolling
7039  * Signature: ()Z
7040  */
7041 JNIEXPORT jboolean JNICALL
7042 Java_sun_awt_windows_WComponentPeer_nativeHandlesWheelScrolling (JNIEnv* env,
7043     jobject self)
7044 {
7045     TRY;
7046 
7047     return (jboolean)AwtToolkit::GetInstance().SyncCall(
7048         (void *(*)(void *))AwtComponent::_NativeHandlesWheelScrolling,
7049         env->NewGlobalRef(self));
7050     // global ref is deleted in _NativeHandlesWheelScrolling
7051 
7052     CATCH_BAD_ALLOC_RET(NULL);
7053 }
7054 
7055 /*
7056  * Class:     sun_awt_windows_WComponentPeer
7057  * Method:    isObscured
7058  * Signature: ()Z
7059  */
7060 JNIEXPORT jboolean JNICALL
7061 Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv* env,
7062     jobject self)
7063 {
7064     TRY;
7065 
7066     jobject selfGlobalRef = env->NewGlobalRef(self);
7067 
7068     return (jboolean)AwtToolkit::GetInstance().SyncCall(
7069         (void*(*)(void*))AwtComponent::_IsObscured,
7070         (void *)selfGlobalRef);
7071     // selfGlobalRef is deleted in _IsObscured
7072 
7073     CATCH_BAD_ALLOC_RET(NULL);
7074 }
7075 
7076 JNIEXPORT void JNICALL
7077 Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv* env, jobject self, jobject parent) {
7078     TRY;
7079 
7080     SetParentStruct * data = new SetParentStruct;
7081     data->component = env->NewGlobalRef(self);
7082     data->parentComp = env->NewGlobalRef(parent);
7083 
7084     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetParent, data);
7085     // global refs and data are deleted in SetParent
7086 
7087     CATCH_BAD_ALLOC;
7088 }
7089 
7090 JNIEXPORT void JNICALL
7091 Java_sun_awt_windows_WComponentPeer_setRectangularShape(JNIEnv* env, jobject self,
7092         jint x1, jint y1, jint x2, jint y2, jobject region)
7093 {
7094     TRY;
7095 
7096     SetRectangularShapeStruct * data = new SetRectangularShapeStruct;
7097     data->component = env->NewGlobalRef(self);
7098     data->x1 = x1;
7099     data->x2 = x2;
7100     data->y1 = y1;
7101     data->y2 = y2;
7102     if (region) {
7103         data->region = env->NewGlobalRef(region);
7104     } else {
7105         data->region = NULL;
7106     }
7107 
7108     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetRectangularShape, data);
7109     // global refs and data are deleted in _SetRectangularShape
7110 
7111     CATCH_BAD_ALLOC;
7112 }
7113 
7114 JNIEXPORT void JNICALL
7115 Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv* env, jobject self, jlong above)
7116 {
7117     TRY;
7118 
7119     SetZOrderStruct * data = new SetZOrderStruct;
7120     data->component = env->NewGlobalRef(self);
7121     data->above = above;
7122 
7123     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetZOrder, data);
7124     // global refs and data are deleted in _SetLower
7125 
7126     CATCH_BAD_ALLOC;
7127 }
7128 
7129 } /* extern "C" */
7130 
7131 
7132 /************************************************************************
7133  * Diagnostic routines
7134  */
7135 
7136 #ifdef DEBUG
7137 
7138 void AwtComponent::VerifyState()
7139 {
7140     if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) {
7141         return;
7142     }
7143 
7144     if (m_callbacksEnabled == FALSE) {
7145         /* Component is not fully setup yet. */
7146         return;
7147     }
7148 
7149     /* Get target bounds. */
7150     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
7151     if (env->PushLocalFrame(10) < 0)
7152         return;
7153 
7154     jobject target = GetTarget(env);
7155 
7156     jint x = env->GetIntField(target, AwtComponent::xID);
7157     jint y = env->GetIntField(target, AwtComponent::yID);
7158     jint width = env->GetIntField(target, AwtComponent::widthID);
7159     jint height = env->GetIntField(target, AwtComponent::heightID);
7160 
7161     /* Convert target origin to absolute coordinates */
7162     while (TRUE) {
7163 
7164         jobject parent = env->GetObjectField(target, AwtComponent::parentID);
7165         if (parent == NULL) {
7166             break;
7167         }
7168         x += env->GetIntField(parent, AwtComponent::xID);
7169         y += env->GetIntField(parent, AwtComponent::yID);
7170 
7171         /* If this component has insets, factor them in, but ignore
7172          * top-level windows.
7173          */
7174         jobject parent2 = env->GetObjectField(parent, AwtComponent::parentID);
7175         if (parent2 != NULL) {
7176             jobject peer = GetPeerForTarget(env, parent);
7177             if (peer != NULL &&
7178                 JNU_IsInstanceOfByName(env, peer,
7179                                        "sun/awt/windows/WPanelPeer") > 0) {
7180                 jobject insets =
7181                     JNU_CallMethodByName(env, NULL, peer,"insets",
7182                                          "()Ljava/awt/Insets;").l;
7183                 x += (env)->GetIntField(insets, AwtInsets::leftID);
7184                 y += (env)->GetIntField(insets, AwtInsets::topID);
7185             }
7186         }
7187         env->DeleteLocalRef(target);
7188         target = parent;
7189     }
7190 
7191     // Test whether component's bounds match the native window's
7192     RECT rect;
7193     VERIFY(::GetWindowRect(GetHWnd(), &rect));
7194 #if 0
7195     DASSERT( (x == rect.left) &&
7196             (y == rect.top) &&
7197             (width == (rect.right-rect.left)) &&
7198             (height == (rect.bottom-rect.top)) );
7199 #else
7200     BOOL fSizeValid = ( (x == rect.left) &&
7201             (y == rect.top) &&
7202             (width == (rect.right-rect.left)) &&
7203             (height == (rect.bottom-rect.top)) );
7204 #endif
7205 
7206     // See if visible state matches
7207     BOOL wndVisible = ::IsWindowVisible(GetHWnd());
7208     jboolean targetVisible;
7209     // To avoid possibly running client code on the toolkit thread, don't
7210     // do the following check if we're running on the toolkit thread.
7211     if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7212         targetVisible = JNU_CallMethodByName(env, NULL, GetTarget(env),
7213                                                   "isShowing", "()Z").z;
7214         DASSERT(!safe_ExceptionOccurred(env));
7215     } else {
7216         targetVisible = wndVisible ? 1 : 0;
7217     }
7218 #if 0
7219     DASSERT( (targetVisible && wndVisible) ||
7220             (!targetVisible && !wndVisible) );
7221 #else
7222     BOOL fVisibleValid = ( (targetVisible && wndVisible) ||
7223             (!targetVisible && !wndVisible) );
7224 #endif
7225 
7226     // Check enabled state
7227     BOOL wndEnabled = ::IsWindowEnabled(GetHWnd());
7228     jboolean enabled = (jboolean)env->GetBooleanField(target,
7229                                                       AwtComponent::enabledID);
7230 #if 0
7231     DASSERT( (enabled && wndEnabled) ||
7232             (!enabled && !wndEnabled) );
7233 #else
7234     BOOL fEnabledValid = ((enabled && wndEnabled) ||
7235                           (!(enabled && !wndEnabled) ));
7236 
7237     if (!fSizeValid || !fVisibleValid || !fEnabledValid) {
7238         printf("AwtComponent::ValidateState() failed:\n");
7239         // To avoid possibly running client code on the toolkit thread, don't
7240         // do the following call if we're running on the toolkit thread.
7241         if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7242             jstring targetStr =
7243                 (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),
7244                                               "getName",
7245                                               "()Ljava/lang/String;").l;
7246             DASSERT(!safe_ExceptionOccurred(env));
7247             LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
7248             printf("\t%S\n", targetStrW);
7249             JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
7250         }
7251         printf("\twas:       [%d,%d,%dx%d]\n", x, y, width, height);
7252         if (!fSizeValid) {
7253             printf("\tshould be: [%d,%d,%dx%d]\n", rect.left, rect.top,
7254                    rect.right-rect.left, rect.bottom-rect.top);
7255         }
7256         if (!fVisibleValid) {
7257             printf("\tshould be: %s\n",
7258                    (targetVisible) ? "visible" : "hidden");
7259         }
7260         if (!fEnabledValid) {
7261             printf("\tshould be: %s\n",
7262                    enabled ? "enabled" : "disabled");
7263         }
7264     }
7265 #endif
7266     env->PopLocalFrame(0);
7267 }
7268 #endif //DEBUG
7269 
7270 // Methods for globally managed DC list
7271 
7272 /**
7273  * Add a new DC to the DC list for this component.
7274  */
7275 void DCList::AddDC(HDC hDC, HWND hWnd)
7276 {
7277     DCItem *newItem = new DCItem;
7278     newItem->hDC = hDC;
7279     newItem->hWnd = hWnd;
7280     AddDCItem(newItem);
7281 }
7282 
7283 void DCList::AddDCItem(DCItem *newItem)
7284 {
7285     listLock.Enter();
7286     newItem->next = head;
7287     head = newItem;
7288     listLock.Leave();
7289 }
7290 
7291 /**
7292  * Given a DC and window handle, remove the DC from the DC list
7293  * and return TRUE if it exists on the current list.  Otherwise
7294  * return FALSE.
7295  * A DC may not exist on the list because it has already
7296  * been released elsewhere (for example, the window
7297  * destruction process may release a DC while a rendering
7298  * thread may also want to release a DC when it notices that
7299  * its DC is obsolete for the current window).
7300  */
7301 DCItem *DCList::RemoveDC(HDC hDC, HWND hWnd)
7302 {
7303     listLock.Enter();
7304     DCItem **prevPtrPtr = &head;
7305     DCItem *listPtr = head;
7306     while (listPtr) {
7307         DCItem *nextPtr = listPtr->next;
7308         if (listPtr->hDC == hDC && listPtr->hWnd == hWnd) {
7309             *prevPtrPtr = nextPtr;
7310             break;
7311         }
7312         prevPtrPtr = &listPtr->next;
7313         listPtr = nextPtr;
7314     }
7315     listLock.Leave();
7316     return listPtr;
7317 }
7318 
7319 /**
7320  * Remove all DCs from the DC list which are associated with
7321  * the same window as hWnd.  Return the list of those
7322  * DC's to the caller (which will then probably want to
7323  * call ReleaseDC() for the returned DCs).
7324  */
7325 DCItem *DCList::RemoveAllDCs(HWND hWnd)
7326 {
7327     listLock.Enter();
7328     DCItem **prevPtrPtr = &head;
7329     DCItem *listPtr = head;
7330     DCItem *newListPtr = NULL;
7331     BOOL ret = FALSE;
7332     while (listPtr) {
7333         DCItem *nextPtr = listPtr->next;
7334         if (listPtr->hWnd == hWnd) {
7335             *prevPtrPtr = nextPtr;
7336             listPtr->next = newListPtr;
7337             newListPtr = listPtr;
7338         } else {
7339             prevPtrPtr = &listPtr->next;
7340         }
7341         listPtr = nextPtr;
7342     }
7343     listLock.Leave();
7344     return newListPtr;
7345 }
7346 
7347 
7348 /**
7349  * Realize palettes of all existing HDC objects
7350  */
7351 void DCList::RealizePalettes(int screen)
7352 {
7353     listLock.Enter();
7354     DCItem *listPtr = head;
7355     while (listPtr) {
7356         AwtWin32GraphicsDevice::RealizePalette(listPtr->hDC, screen);
7357         listPtr = listPtr->next;
7358     }
7359     listLock.Leave();
7360 }
7361 
7362 void MoveDCToPassiveList(HDC hDC, HWND hWnd) {
7363     DCItem *removedDC;
7364     if ((removedDC = activeDCList.RemoveDC(hDC, hWnd)) != NULL) {
7365         passiveDCList.AddDCItem(removedDC);
7366     }
7367 }
7368 
7369 void ReleaseDCList(HWND hwnd, DCList &list) {
7370     DCItem *removedDCs = list.RemoveAllDCs(hwnd);
7371     while (removedDCs) {
7372         DCItem *tmpDCList = removedDCs;
7373         DASSERT(::GetObjectType(tmpDCList->hDC) == OBJ_DC);
7374         int retValue = ::ReleaseDC(tmpDCList->hWnd, tmpDCList->hDC);
7375         VERIFY(retValue != 0);
7376         if (retValue != 0) {
7377             // Valid ReleaseDC call; need to decrement GDI object counter
7378             AwtGDIObject::Decrement();
7379         }
7380         removedDCs = removedDCs->next;
7381         delete tmpDCList;
7382     }
7383 }
7384