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