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