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