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