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