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