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