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