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