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