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 #define _JNI_IMPLEMENTATION_
  27 
  28 #include "awt.h"
  29 #include <signal.h>
  30 #include <windowsx.h>
  31 #include <process.h>
  32 #include <shellapi.h>
  33 #include <shlwapi.h>
  34 
  35 #include "awt_DrawingSurface.h"
  36 #include "awt_AWTEvent.h"
  37 #include "awt_Component.h"
  38 #include "awt_Canvas.h"
  39 #include "awt_Clipboard.h"
  40 #include "awt_Frame.h"
  41 #include "awt_Dialog.h"
  42 #include "awt_Font.h"
  43 #include "awt_Cursor.h"
  44 #include "awt_InputEvent.h"
  45 #include "awt_KeyEvent.h"
  46 #include "awt_List.h"
  47 #include "awt_Palette.h"
  48 #include "awt_PopupMenu.h"
  49 #include "awt_Toolkit.h"
  50 #include "awt_DesktopProperties.h"
  51 #include "awt_FileDialog.h"
  52 #include "CmdIDList.h"
  53 #include "awt_new.h"
  54 #include "debug_trace.h"
  55 #include "debug_mem.h"
  56 
  57 #include "ComCtl32Util.h"
  58 #include "DllUtil.h"
  59 
  60 #include "D3DPipelineManager.h"
  61 
  62 #include <awt_DnDDT.h>
  63 #include <awt_DnDDS.h>
  64 
  65 #include <java_awt_Toolkit.h>
  66 #include <java_awt_event_InputMethodEvent.h>
  67 
  68 extern void initScreens(JNIEnv *env);
  69 extern "C" void awt_dnd_initialize();
  70 extern "C" void awt_dnd_uninitialize();
  71 extern "C" void awt_clipboard_uninitialize(JNIEnv *env);
  72 extern "C" BOOL g_bUserHasChangedInputLang;
  73 
  74 extern CriticalSection windowMoveLock;
  75 extern BOOL windowMoveLockHeld;
  76 
  77 // Needed by JAWT: see awt_DrawingSurface.cpp.
  78 extern jclass jawtVImgClass;
  79 extern jclass jawtVSMgrClass;
  80 extern jclass jawtComponentClass;
  81 extern jfieldID jawtPDataID;
  82 extern jfieldID jawtSDataID;
  83 extern jfieldID jawtSMgrID;
  84 
  85 extern void DWMResetCompositionEnabled();
  86 
  87 /************************************************************************
  88  * Utilities
  89  */
  90 
  91 /* Initialize the Java VM instance variable when the library is
  92    first loaded */
  93 JavaVM *jvm = NULL;
  94 
  95 JNIEXPORT jint JNICALL
  96 JNI_OnLoad(JavaVM *vm, void *reserved)
  97 {
  98     TRY;
  99 
 100     jvm = vm;
 101     return JNI_VERSION_1_2;
 102 
 103     CATCH_BAD_ALLOC_RET(0);
 104 }
 105 
 106 extern "C" JNIEXPORT jboolean JNICALL AWTIsHeadless() {
 107     static JNIEnv *env = NULL;
 108     static jboolean isHeadless;
 109     jmethodID headlessFn;
 110     jclass graphicsEnvClass;
 111 
 112     if (env == NULL) {
 113         env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 114         graphicsEnvClass = env->FindClass(
 115             "java/awt/GraphicsEnvironment");
 116         if (graphicsEnvClass == NULL) {
 117             return JNI_TRUE;
 118         }
 119         headlessFn = env->GetStaticMethodID(
 120             graphicsEnvClass, "isHeadless", "()Z");
 121         if (headlessFn == NULL) {
 122             return JNI_TRUE;
 123         }
 124         isHeadless = env->CallStaticBooleanMethod(graphicsEnvClass,
 125             headlessFn);
 126     }
 127     return isHeadless;
 128 }
 129 
 130 #define IDT_AWT_MOUSECHECK 0x101
 131 
 132 static LPCTSTR szAwtToolkitClassName = TEXT("SunAwtToolkit");
 133 
 134 static const int MOUSE_BUTTONS_WINDOWS_SUPPORTED = 5; //three standard buttons + XBUTTON1 + XBUTTON2.
 135 
 136 UINT AwtToolkit::GetMouseKeyState()
 137 {
 138     static BOOL mbSwapped = ::GetSystemMetrics(SM_SWAPBUTTON);
 139     UINT mouseKeyState = 0;
 140 
 141     if (HIBYTE(::GetKeyState(VK_CONTROL)))
 142         mouseKeyState |= MK_CONTROL;
 143     if (HIBYTE(::GetKeyState(VK_SHIFT)))
 144         mouseKeyState |= MK_SHIFT;
 145     if (HIBYTE(::GetKeyState(VK_LBUTTON)))
 146         mouseKeyState |= (mbSwapped ? MK_RBUTTON : MK_LBUTTON);
 147     if (HIBYTE(::GetKeyState(VK_RBUTTON)))
 148         mouseKeyState |= (mbSwapped ? MK_LBUTTON : MK_RBUTTON);
 149     if (HIBYTE(::GetKeyState(VK_MBUTTON)))
 150         mouseKeyState |= MK_MBUTTON;
 151     return mouseKeyState;
 152 }
 153 
 154 //
 155 // Normal ::GetKeyboardState call only works if current thread has
 156 // a message pump, so provide a way for other threads to get
 157 // the keyboard state
 158 //
 159 void AwtToolkit::GetKeyboardState(PBYTE keyboardState)
 160 {
 161     CriticalSection::Lock       l(AwtToolkit::GetInstance().m_lockKB);
 162     DASSERT(!IsBadWritePtr(keyboardState, KB_STATE_SIZE));
 163     memcpy(keyboardState, AwtToolkit::GetInstance().m_lastKeyboardState,
 164            KB_STATE_SIZE);
 165 }
 166 
 167 void AwtToolkit::SetBusy(BOOL busy) {
 168 
 169     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 170 
 171     static jclass awtAutoShutdownClass = NULL;
 172     static jmethodID notifyBusyMethodID = NULL;
 173     static jmethodID notifyFreeMethodID = NULL;
 174 
 175     if (awtAutoShutdownClass == NULL) {
 176         jclass awtAutoShutdownClassLocal = env->FindClass("sun/awt/AWTAutoShutdown");
 177         DASSERT(awtAutoShutdownClassLocal != NULL);
 178         if (!awtAutoShutdownClassLocal) throw std::bad_alloc();
 179 
 180         awtAutoShutdownClass = (jclass)env->NewGlobalRef(awtAutoShutdownClassLocal);
 181         env->DeleteLocalRef(awtAutoShutdownClassLocal);
 182         if (!awtAutoShutdownClass) throw std::bad_alloc();
 183 
 184         notifyBusyMethodID = env->GetStaticMethodID(awtAutoShutdownClass,
 185                                                     "notifyToolkitThreadBusy", "()V");
 186         DASSERT(notifyBusyMethodID != NULL);
 187         if (!notifyBusyMethodID) throw std::bad_alloc();
 188 
 189         notifyFreeMethodID = env->GetStaticMethodID(awtAutoShutdownClass,
 190                                                     "notifyToolkitThreadFree", "()V");
 191         DASSERT(notifyFreeMethodID != NULL);
 192         if (!notifyFreeMethodID) throw std::bad_alloc();
 193     } /* awtAutoShutdownClass == NULL*/
 194 
 195     if (busy) {
 196         env->CallStaticVoidMethod(awtAutoShutdownClass,
 197                                   notifyBusyMethodID);
 198     } else {
 199         env->CallStaticVoidMethod(awtAutoShutdownClass,
 200                                   notifyFreeMethodID);
 201     }
 202 
 203     if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
 204         env->ExceptionDescribe();
 205         env->ExceptionClear();
 206     }
 207 }
 208 
 209 BOOL AwtToolkit::activateKeyboardLayout(HKL hkl) {
 210     // This call should succeed in case of one of the following:
 211     // 1. Win 9x
 212     // 2. NT with that HKL already loaded
 213     HKL prev = ::ActivateKeyboardLayout(hkl, 0);
 214 
 215     // If the above call fails, try loading the layout in case of NT
 216     if (!prev) {
 217         // create input locale string, e.g., "00000409", from hkl.
 218         TCHAR inputLocale[9];
 219         TCHAR buf[9];
 220         _tcscpy_s(inputLocale, 9, TEXT("00000000"));
 221 
 222     // 64-bit: ::LoadKeyboardLayout() is such a weird API - a string of
 223     // the hex value you want?!  Here we're converting our HKL value to
 224     // a string.  Hopefully there is no 64-bit trouble.
 225         _i64tot(reinterpret_cast<INT_PTR>(hkl), buf, 16);
 226         size_t len = _tcslen(buf);
 227         memcpy(&inputLocale[8-len], buf, len);
 228 
 229         // load and activate the keyboard layout
 230         hkl = ::LoadKeyboardLayout(inputLocale, 0);
 231         if (hkl != 0) {
 232             prev = ::ActivateKeyboardLayout(hkl, 0);
 233         }
 234     }
 235 
 236     return (prev != 0);
 237 }
 238 
 239 /************************************************************************
 240  * Exported functions
 241  */
 242 
 243 extern "C" BOOL APIENTRY DllMain(HANDLE hInstance, DWORD ul_reason_for_call,
 244                                  LPVOID)
 245 {
 246     // Don't use the TRY and CATCH_BAD_ALLOC_RET macros if we're detaching
 247     // the library. Doing so causes awt.dll to call back into the VM during
 248     // shutdown. This crashes the HotSpot VM.
 249     switch (ul_reason_for_call) {
 250     case DLL_PROCESS_ATTACH:
 251         TRY;
 252         AwtToolkit::GetInstance().SetModuleHandle((HMODULE)hInstance);
 253         CATCH_BAD_ALLOC_RET(FALSE);
 254         break;
 255     case DLL_PROCESS_DETACH:
 256 #ifdef DEBUG
 257         DTrace_DisableMutex();
 258         DMem_DisableMutex();
 259 #endif DEBUG
 260         break;
 261     }
 262     return TRUE;
 263 }
 264 
 265 /************************************************************************
 266  * AwtToolkit fields
 267  */
 268 
 269 AwtToolkit AwtToolkit::theInstance;
 270 
 271 /* ids for WToolkit fields accessed from native code */
 272 jmethodID AwtToolkit::windowsSettingChangeMID;
 273 jmethodID AwtToolkit::displayChangeMID;
 274 /* ids for Toolkit methods */
 275 jmethodID AwtToolkit::getDefaultToolkitMID;
 276 jmethodID AwtToolkit::getFontMetricsMID;
 277 jmethodID AwtToolkit::insetsMID;
 278 
 279 /************************************************************************
 280  * AwtToolkit methods
 281  */
 282 
 283 AwtToolkit::AwtToolkit() {
 284     m_localPump = FALSE;
 285     m_mainThreadId = 0;
 286     m_toolkitHWnd = NULL;
 287     m_inputMethodHWnd = NULL;
 288     m_verbose = FALSE;
 289     m_isActive = TRUE;
 290     m_isDisposed = FALSE;
 291 
 292     m_vmSignalled = FALSE;
 293 
 294     m_isDynamicLayoutSet = FALSE;
 295     m_areExtraMouseButtonsEnabled = TRUE;
 296 
 297     m_isWin8OrLater = FALSE;
 298     m_touchKbrdAutoShowIsEnabled = FALSE;
 299     m_touchKbrdExeFilePath = NULL;
 300     m_pRegisterTouchWindow = NULL;
 301     m_pGetTouchInputInfo = NULL;
 302     m_pCloseTouchInputHandle = NULL;
 303 
 304     m_verifyComponents = FALSE;
 305     m_breakOnError = FALSE;
 306 
 307     m_breakMessageLoop = FALSE;
 308     m_messageLoopResult = 0;
 309 
 310     m_lastMouseOver = NULL;
 311     m_mouseDown = FALSE;
 312 
 313     m_hGetMessageHook = 0;
 314     m_hMouseLLHook = 0;
 315     m_lastWindowUnderMouse = NULL;
 316     m_timer = 0;
 317 
 318     m_cmdIDs = new AwtCmdIDList();
 319     m_pModalDialog = NULL;
 320     m_peer = NULL;
 321     m_dllHandle = NULL;
 322 
 323     m_displayChanged = FALSE;
 324     m_embedderProcessID = 0;
 325 
 326     // XXX: keyboard mapping should really be moved out of AwtComponent
 327     AwtComponent::InitDynamicKeyMapTable();
 328 
 329     // initialize kb state array
 330     ::GetKeyboardState(m_lastKeyboardState);
 331 
 332     m_waitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
 333     eventNumber = 0;
 334 }
 335 
 336 AwtToolkit::~AwtToolkit() {
 337 /*
 338  *  The code has been moved to AwtToolkit::Dispose() method.
 339  */
 340 }
 341 
 342 HWND AwtToolkit::CreateToolkitWnd(LPCTSTR name)
 343 {
 344     HWND hwnd = CreateWindow(
 345         szAwtToolkitClassName,
 346         (LPCTSTR)name,                    /* window name */
 347         WS_DISABLED,                      /* window style */
 348         -1, -1,                           /* position of window */
 349         0, 0,                             /* width and height */
 350         NULL, NULL,                       /* hWndParent and hWndMenu */
 351         GetModuleHandle(),
 352         NULL);                            /* lpParam */
 353     DASSERT(hwnd != NULL);
 354     return hwnd;
 355 }
 356 
 357 void AwtToolkit::InitTouchKeyboardExeFilePath() {
 358     enum RegistryView { WOW64_32BIT, WOW64_64BIT };
 359     const TCHAR tabTipCoKeyName[] = _T("SOFTWARE\\Classes\\CLSID\\")
 360         _T("{054AAE20-4BEA-4347-8A35-64A533254A9D}\\LocalServer32");
 361     HKEY hTabTipCoKey = NULL;
 362     RegistryView regViewWithTabTipCoKey = WOW64_32BIT;
 363 
 364     if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, tabTipCoKeyName, 0,
 365             KEY_READ | KEY_WOW64_32KEY, &hTabTipCoKey) != ERROR_SUCCESS) {
 366         if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, tabTipCoKeyName, 0,
 367                 KEY_READ | KEY_WOW64_64KEY, &hTabTipCoKey) != ERROR_SUCCESS) {
 368             return;
 369         } else {
 370             regViewWithTabTipCoKey = WOW64_64BIT;
 371         }
 372     }
 373 
 374     DWORD keyValType = 0;
 375     DWORD bytesCopied = 0;
 376     if ((::RegQueryValueEx(hTabTipCoKey, NULL, NULL, &keyValType, NULL,
 377             &bytesCopied) != ERROR_SUCCESS) ||
 378         ((keyValType != REG_EXPAND_SZ) && (keyValType != REG_SZ))) {
 379         if (hTabTipCoKey != NULL) {
 380             ::RegCloseKey(hTabTipCoKey);
 381         }
 382         return;
 383     }
 384 
 385     // Increase the buffer size for 1 additional null-terminating character.
 386     bytesCopied += sizeof(TCHAR);
 387     TCHAR* tabTipFilePath = new TCHAR[bytesCopied / sizeof(TCHAR)];
 388     ::memset(tabTipFilePath, 0, bytesCopied);
 389 
 390     DWORD oldBytesCopied = bytesCopied;
 391     if (::RegQueryValueEx(hTabTipCoKey, NULL, NULL, NULL,
 392             (LPBYTE)tabTipFilePath, &bytesCopied) == ERROR_SUCCESS) {
 393         const TCHAR searchedStr[] = _T("%CommonProgramFiles%");
 394         const size_t searchedStrLen = ::_tcslen(searchedStr);
 395         int searchedStrStartIndex = -1;
 396 
 397         TCHAR* commonFilesDirPath = NULL;
 398         DWORD commonFilesDirPathLen = 0;
 399 
 400         // Check, if '%CommonProgramFiles%' string is present in the defined
 401         // path of the touch keyboard executable.
 402         TCHAR* const searchedStrStart = ::_tcsstr(tabTipFilePath, searchedStr);
 403         if (searchedStrStart != NULL) {
 404             searchedStrStartIndex = searchedStrStart - tabTipFilePath;
 405 
 406             // Get value of 'CommonProgramFiles' environment variable, if the
 407             // file path of the touch keyboard executable was found in 32-bit
 408             // registry view, otherwise get value of 'CommonProgramW6432'.
 409             const TCHAR envVar32BitName[] = _T("CommonProgramFiles");
 410             const TCHAR envVar64BitName[] = _T("CommonProgramW6432");
 411             const TCHAR* envVarName = (regViewWithTabTipCoKey == WOW64_32BIT ?
 412                 envVar32BitName : envVar64BitName);
 413 
 414             DWORD charsStored = ::GetEnvironmentVariable(envVarName, NULL, 0);
 415             if (charsStored > 0) {
 416                 commonFilesDirPath = new TCHAR[charsStored];
 417                 ::memset(commonFilesDirPath, 0, charsStored * sizeof(TCHAR));
 418 
 419                 DWORD oldCharsStored = charsStored;
 420                 if (((charsStored = ::GetEnvironmentVariable(envVarName,
 421                         commonFilesDirPath, charsStored)) > 0) &&
 422                     (charsStored <= oldCharsStored)) {
 423                     commonFilesDirPathLen = charsStored;
 424                 } else {
 425                     delete[] commonFilesDirPath;
 426                     commonFilesDirPath = NULL;
 427                 }
 428             }
 429         }
 430 
 431         // Calculate 'm_touchKbrdExeFilePath' length in characters including
 432         // the null-terminating character.
 433         DWORD exeFilePathLen = oldBytesCopied / sizeof(TCHAR);
 434         if (commonFilesDirPathLen > 0) {
 435             exeFilePathLen = exeFilePathLen - searchedStrLen +
 436                 commonFilesDirPathLen;
 437         }
 438 
 439         if (m_touchKbrdExeFilePath != NULL) {
 440             delete[] m_touchKbrdExeFilePath;
 441             m_touchKbrdExeFilePath = NULL;
 442         }
 443         m_touchKbrdExeFilePath = new TCHAR[exeFilePathLen];
 444         ::memset(m_touchKbrdExeFilePath, 0, exeFilePathLen * sizeof(TCHAR));
 445 
 446         if (commonFilesDirPathLen > 0) {
 447             ::_tcsncpy_s(m_touchKbrdExeFilePath, exeFilePathLen, tabTipFilePath,
 448                 searchedStrStartIndex);
 449             DWORD charsCopied = searchedStrStartIndex;
 450 
 451             ::_tcsncpy_s(m_touchKbrdExeFilePath + charsCopied,
 452                 exeFilePathLen - charsCopied, commonFilesDirPath,
 453                 commonFilesDirPathLen);
 454             charsCopied += commonFilesDirPathLen;
 455 
 456             ::_tcsncpy_s(m_touchKbrdExeFilePath + charsCopied,
 457                 exeFilePathLen - charsCopied, searchedStrStart + searchedStrLen,
 458                 bytesCopied / sizeof(TCHAR) -
 459                     (searchedStrStartIndex + searchedStrLen));
 460         } else {
 461             ::_tcsncpy_s(m_touchKbrdExeFilePath, exeFilePathLen, tabTipFilePath,
 462                 bytesCopied / sizeof(TCHAR));
 463         }
 464 
 465         // Remove leading and trailing quotation marks.
 466         ::StrTrim(m_touchKbrdExeFilePath, _T("\""));
 467 
 468         // Verify that a file with the path 'm_touchKbrdExeFilePath' exists.
 469         DWORD fileAttrs = ::GetFileAttributes(m_touchKbrdExeFilePath);
 470         DWORD err = ::GetLastError();
 471         if ((fileAttrs == INVALID_FILE_ATTRIBUTES) ||
 472             (fileAttrs & FILE_ATTRIBUTE_DIRECTORY)) {
 473             delete[] m_touchKbrdExeFilePath;
 474             m_touchKbrdExeFilePath = NULL;
 475         }
 476 
 477         if (commonFilesDirPath != NULL) {
 478             delete[] commonFilesDirPath;
 479         }
 480     }
 481 
 482     if (tabTipFilePath != NULL) {
 483         delete[] tabTipFilePath;
 484     }
 485     if (hTabTipCoKey != NULL) {
 486         ::RegCloseKey(hTabTipCoKey);
 487     }
 488 }
 489 
 490 HWND AwtToolkit::GetTouchKeyboardWindow() {
 491     const TCHAR wndClassName[] = _T("IPTip_Main_Window");
 492     HWND hwnd = ::FindWindow(wndClassName, NULL);
 493     if ((hwnd != NULL) && ::IsWindow(hwnd) && ::IsWindowEnabled(hwnd) &&
 494         ::IsWindowVisible(hwnd)) {
 495         return hwnd;
 496     }
 497     return NULL;
 498 }
 499 
 500 
 501 struct ToolkitThreadProc_Data {
 502     bool result;
 503     HANDLE hCompleted;
 504 
 505     jobject thread;
 506     jobject threadGroup;
 507 };
 508 
 509 void ToolkitThreadProc(void *param)
 510 {
 511     ToolkitThreadProc_Data *data = (ToolkitThreadProc_Data *)param;
 512 
 513     bool bNotified = false;
 514 
 515     JNIEnv *env;
 516     JavaVMAttachArgs attachArgs;
 517     attachArgs.version  = JNI_VERSION_1_2;
 518     attachArgs.name     = "AWT-Windows";
 519     attachArgs.group    = data->threadGroup;
 520 
 521     jint res = jvm->AttachCurrentThreadAsDaemon((void **)&env, &attachArgs);
 522     if (res < 0) {
 523         return;
 524     }
 525 
 526     jobject thread = env->NewGlobalRef(data->thread);
 527     if (thread != NULL) {
 528         jclass cls = env->GetObjectClass(thread);
 529         if (cls != NULL) {
 530             jmethodID runId = env->GetMethodID(cls, "run", "()V");
 531             if (runId != NULL) {
 532                 data->result = true;
 533                 ::SetEvent(data->hCompleted);
 534                 bNotified = true;
 535 
 536                 env->CallVoidMethod(thread, runId);
 537 
 538                 if (env->ExceptionCheck()) {
 539                     env->ExceptionDescribe();
 540                     env->ExceptionClear();
 541                     // TODO: handle
 542                 }
 543             }
 544             env->DeleteLocalRef(cls);
 545         }
 546         env->DeleteGlobalRef(thread);
 547     }
 548     if (!bNotified) {
 549         ::SetEvent(data->hCompleted);
 550     }
 551 
 552     jvm->DetachCurrentThread();
 553 }
 554 
 555 /*
 556  * Class:     sun_awt_windows_WToolkit
 557  * Method:    startToolkitThread
 558  * Signature: (Ljava/lang/Runnable;Ljava/lang/ThreadGroup)Z
 559  */
 560 JNIEXPORT jboolean JNICALL
 561 Java_sun_awt_windows_WToolkit_startToolkitThread(JNIEnv *env, jclass cls, jobject thread, jobject threadGroup)
 562 {
 563     AwtToolkit& tk = AwtToolkit::GetInstance();
 564 
 565     ToolkitThreadProc_Data data;
 566     data.result = false;
 567     data.thread = env->NewGlobalRef(thread);
 568     data.threadGroup = env->NewGlobalRef(threadGroup);
 569     if (data.thread == NULL || data.threadGroup == NULL) {
 570         return JNI_FALSE;
 571     }
 572     data.hCompleted = ::CreateEvent(NULL, FALSE, FALSE, NULL);
 573 
 574     bool result = tk.GetPreloadThread()
 575                     .InvokeAndTerminate(ToolkitThreadProc, &data);
 576 
 577     if (result) {
 578         ::WaitForSingleObject(data.hCompleted, INFINITE);
 579         result = data.result;
 580     } else {
 581         // no awt preloading
 582         // return back to the usual toolkit way
 583     }
 584     ::CloseHandle(data.hCompleted);
 585 
 586     env->DeleteGlobalRef(data.thread);
 587     env->DeleteGlobalRef(data.threadGroup);
 588 
 589     return result ? JNI_TRUE : JNI_FALSE;
 590 }
 591 
 592 BOOL AwtToolkit::Initialize(BOOL localPump) {
 593     AwtToolkit& tk = AwtToolkit::GetInstance();
 594 
 595     if (!tk.m_isActive || tk.m_mainThreadId != 0) {
 596         /* Already initialized. */
 597         return FALSE;
 598     }
 599 
 600     // This call is moved here from AwtToolkit constructor. Having it
 601     // there led to the bug 6480630: there could be a situation when
 602     // ComCtl32Util was constructed but not disposed
 603     ComCtl32Util::GetInstance().InitLibraries();
 604 
 605     if (!localPump) {
 606         // if preload thread was run, terminate it
 607         preloadThread.Terminate(true);
 608     }
 609 
 610     /* Register this toolkit's helper window */
 611     VERIFY(tk.RegisterClass() != NULL);
 612 
 613     // Set up operator new/malloc out of memory handler.
 614     NewHandler::init();
 615 
 616         //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
 617         // Bugs 4032109, 4047966, and 4071991 to fix AWT
 618         //      crash in 16 color display mode.  16 color mode is supported.  Less
 619         //      than 16 color is not.
 620         // creighto@eng.sun.com 1997-10-07
 621         //
 622         // Check for at least 16 colors
 623     HDC hDC = ::GetDC(NULL);
 624         if ((::GetDeviceCaps(hDC, BITSPIXEL) * ::GetDeviceCaps(hDC, PLANES)) < 4) {
 625                 ::MessageBox(NULL,
 626                              TEXT("Sorry, but this release of Java requires at least 16 colors"),
 627                              TEXT("AWT Initialization Error"),
 628                              MB_ICONHAND | MB_APPLMODAL);
 629                 ::DeleteDC(hDC);
 630                 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 631                 JNU_ThrowByName(env, "java/lang/InternalError",
 632                                 "unsupported screen depth");
 633                 return FALSE;
 634         }
 635     ::ReleaseDC(NULL, hDC);
 636         ///////////////////////////////////////////////////////////////////////////
 637 
 638     tk.m_localPump = localPump;
 639     tk.m_mainThreadId = ::GetCurrentThreadId();
 640 
 641     /*
 642      * Create the one-and-only toolkit window.  This window isn't
 643      * displayed, but is used to route messages to this thread.
 644      */
 645     tk.m_toolkitHWnd = tk.CreateToolkitWnd(TEXT("theAwtToolkitWindow"));
 646     DASSERT(tk.m_toolkitHWnd != NULL);
 647 
 648     /*
 649      * Setup a GetMessage filter to watch all messages coming out of our
 650      * queue from PreProcessMsg().
 651      */
 652     tk.m_hGetMessageHook = ::SetWindowsHookEx(WH_GETMESSAGE,
 653                                               (HOOKPROC)GetMessageFilter,
 654                                               0, tk.m_mainThreadId);
 655 
 656     awt_dnd_initialize();
 657 
 658     /*
 659      * Initialization of the touch keyboard related variables.
 660      */
 661     tk.m_isWin8OrLater = IS_WIN8;
 662 
 663     TRY;
 664 
 665     JNIEnv* env = AwtToolkit::GetEnv();
 666     jclass sunToolkitCls = env->FindClass("sun/awt/SunToolkit");
 667     DASSERT(sunToolkitCls != 0);
 668     CHECK_NULL_RETURN(sunToolkitCls, FALSE);
 669 
 670     jmethodID isTouchKeyboardAutoShowEnabledMID = env->GetStaticMethodID(
 671         sunToolkitCls, "isTouchKeyboardAutoShowEnabled", "()Z");
 672     DASSERT(isTouchKeyboardAutoShowEnabledMID != 0);
 673     CHECK_NULL_RETURN(isTouchKeyboardAutoShowEnabledMID, FALSE);
 674 
 675     tk.m_touchKbrdAutoShowIsEnabled = env->CallStaticBooleanMethod(
 676         sunToolkitCls, isTouchKeyboardAutoShowEnabledMID);
 677 
 678     CATCH_BAD_ALLOC_RET(FALSE);
 679 
 680     if (tk.m_isWin8OrLater && tk.m_touchKbrdAutoShowIsEnabled) {
 681         tk.InitTouchKeyboardExeFilePath();
 682         HMODULE hUser32Dll = ::LoadLibrary(_T("user32.dll"));
 683         if (hUser32Dll != NULL) {
 684             tk.m_pRegisterTouchWindow = (RegisterTouchWindowFunc)
 685                 ::GetProcAddress(hUser32Dll, "RegisterTouchWindow");
 686             tk.m_pGetTouchInputInfo = (GetTouchInputInfoFunc)
 687                 ::GetProcAddress(hUser32Dll, "GetTouchInputInfo");
 688             tk.m_pCloseTouchInputHandle = (CloseTouchInputHandleFunc)
 689                 ::GetProcAddress(hUser32Dll, "CloseTouchInputHandle");
 690         }
 691 
 692         if ((tk.m_pRegisterTouchWindow == NULL) ||
 693             (tk.m_pGetTouchInputInfo == NULL) ||
 694             (tk.m_pCloseTouchInputHandle == NULL)) {
 695             tk.m_pRegisterTouchWindow = NULL;
 696             tk.m_pGetTouchInputInfo = NULL;
 697             tk.m_pCloseTouchInputHandle = NULL;
 698         }
 699     }
 700     /*
 701      * End of the touch keyboard related initialization code.
 702      */
 703 
 704     return TRUE;
 705 }
 706 
 707 BOOL AwtToolkit::Dispose() {
 708     DTRACE_PRINTLN("In AwtToolkit::Dispose()");
 709 
 710     AwtToolkit& tk = AwtToolkit::GetInstance();
 711 
 712     if (!tk.m_isActive || tk.m_mainThreadId != ::GetCurrentThreadId()) {
 713         return FALSE;
 714     }
 715 
 716     tk.m_isActive = FALSE;
 717 
 718     // dispose Direct3D-related resources. This should be done
 719     // before AwtObjectList::Cleanup() as the d3d will attempt to
 720     // shutdown when the last of its windows is disposed of
 721     D3DInitializer::GetInstance().Clean();
 722 
 723     AwtObjectList::Cleanup();
 724 
 725     awt_dnd_uninitialize();
 726     awt_clipboard_uninitialize((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2));
 727 
 728     if (tk.m_touchKbrdExeFilePath != NULL) {
 729         delete[] tk.m_touchKbrdExeFilePath;
 730         tk.m_touchKbrdExeFilePath = NULL;
 731     }
 732     tk.m_pRegisterTouchWindow = NULL;
 733     tk.m_pGetTouchInputInfo = NULL;
 734     tk.m_pCloseTouchInputHandle = NULL;
 735 
 736     if (tk.m_inputMethodHWnd != NULL) {
 737         ::SendMessage(tk.m_inputMethodHWnd, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0);
 738     }
 739     tk.m_inputMethodHWnd = NULL;
 740 
 741     // wait for any messages to be processed, in particular,
 742     // all WM_AWT_DELETEOBJECT messages that delete components; no
 743     // new messages will appear as all the windows except toolkit
 744     // window are unsubclassed and destroyed
 745     MSG msg;
 746     while (::GetMessage(&msg, NULL, 0, 0)) {
 747         ::TranslateMessage(&msg);
 748         ::DispatchMessage(&msg);
 749     }
 750 
 751     AwtFont::Cleanup();
 752 
 753     HWND toolkitHWndToDestroy = tk.m_toolkitHWnd;
 754     tk.m_toolkitHWnd = 0;
 755     VERIFY(::DestroyWindow(toolkitHWndToDestroy) != NULL);
 756 
 757     tk.UnregisterClass();
 758 
 759     ::UnhookWindowsHookEx(tk.m_hGetMessageHook);
 760     UninstallMouseLowLevelHook();
 761 
 762     tk.m_mainThreadId = 0;
 763 
 764     delete tk.m_cmdIDs;
 765 
 766     ::CloseHandle(m_waitEvent);
 767 
 768     tk.m_isDisposed = TRUE;
 769 
 770     return TRUE;
 771 }
 772 
 773 void AwtToolkit::SetDynamicLayout(BOOL dynamic) {
 774     m_isDynamicLayoutSet = dynamic;
 775 }
 776 
 777 BOOL AwtToolkit::IsDynamicLayoutSet() {
 778     return m_isDynamicLayoutSet;
 779 }
 780 
 781 BOOL AwtToolkit::IsDynamicLayoutSupported() {
 782     // SPI_GETDRAGFULLWINDOWS is only supported on Win95 if
 783     // Windows Plus! is installed.  Otherwise, box frame resize.
 784     BOOL fullWindowDragEnabled = FALSE;
 785     int result = 0;
 786     result = ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
 787                                   &fullWindowDragEnabled, 0);
 788 
 789     return (fullWindowDragEnabled && (result != 0));
 790 }
 791 
 792 BOOL AwtToolkit::IsDynamicLayoutActive() {
 793     return (IsDynamicLayoutSet() && IsDynamicLayoutSupported());
 794 }
 795 
 796 ATOM AwtToolkit::RegisterClass() {
 797     WNDCLASS  wc;
 798 
 799     wc.style         = 0;
 800     wc.lpfnWndProc   = (WNDPROC)WndProc;
 801     wc.cbClsExtra    = 0;
 802     wc.cbWndExtra    = 0;
 803     wc.hInstance     = AwtToolkit::GetInstance().GetModuleHandle(),
 804     wc.hIcon         = AwtToolkit::GetInstance().GetAwtIcon();
 805     wc.hCursor       = NULL;
 806     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
 807     wc.lpszMenuName  = NULL;
 808     wc.lpszClassName = szAwtToolkitClassName;
 809 
 810     ATOM ret = ::RegisterClass(&wc);
 811     DASSERT(ret != NULL);
 812     return ret;
 813 }
 814 
 815 void AwtToolkit::UnregisterClass() {
 816     VERIFY(::UnregisterClass(szAwtToolkitClassName, AwtToolkit::GetInstance().GetModuleHandle()));
 817 }
 818 
 819 /*
 820  * Structure holding the information to create a component. This packet is
 821  * sent to the toolkit window.
 822  */
 823 struct ComponentCreatePacket {
 824     void* hComponent;
 825     void* hParent;
 826     void (*factory)(void*, void*);
 827 };
 828 
 829 /*
 830  * Create an AwtXxxx component using a given factory function
 831  * Implemented by sending a message to the toolkit window to invoke the
 832  * factory function from that thread
 833  */
 834 void AwtToolkit::CreateComponent(void* component, void* parent,
 835                                  ComponentFactory compFactory, BOOL isParentALocalReference)
 836 {
 837     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 838 
 839     /* Since Local references are not valid in another Thread, we need to
 840        create a global reference before we send this to the Toolkit thread.
 841        In some cases this method is called with parent being a native
 842        malloced struct so we cannot and do not need to create a Global
 843        Reference from it. This is indicated by isParentALocalReference */
 844 
 845     jobject gcomponent = env->NewGlobalRef((jobject)component);
 846     jobject gparent;
 847     if (isParentALocalReference) gparent = env->NewGlobalRef((jobject)parent);
 848     ComponentCreatePacket ccp = { gcomponent,
 849                                   isParentALocalReference == TRUE ?  gparent : parent,
 850                                    compFactory };
 851     AwtToolkit::GetInstance().SendMessage(WM_AWT_COMPONENT_CREATE, 0,
 852                                           (LPARAM)&ccp);
 853     env->DeleteGlobalRef(gcomponent);
 854     if (isParentALocalReference) env->DeleteGlobalRef(gparent);
 855 }
 856 
 857 /*
 858  * Destroy an HWND that was created in the toolkit thread. Can be used on
 859  * Components and the toolkit window itself.
 860  */
 861 void AwtToolkit::DestroyComponentHWND(HWND hwnd)
 862 {
 863     if (!::IsWindow(hwnd)) {
 864         return;
 865     }
 866 
 867     AwtToolkit& tk = AwtToolkit::GetInstance();
 868     if ((tk.m_lastMouseOver != NULL) &&
 869         (tk.m_lastMouseOver->GetHWnd() == hwnd))
 870     {
 871         tk.m_lastMouseOver = NULL;
 872     }
 873 
 874     ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)NULL);
 875     tk.SendMessage(WM_AWT_DESTROY_WINDOW, (WPARAM)hwnd, 0);
 876 }
 877 
 878 #ifndef SPY_MESSAGES
 879 #define SpyWinMessage(hwin,msg,str)
 880 #else
 881 void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment);
 882 #endif
 883 
 884 /*
 885  * An AwtToolkit window is just a means of routing toolkit messages to here.
 886  */
 887 LRESULT CALLBACK AwtToolkit::WndProc(HWND hWnd, UINT message,
 888                                      WPARAM wParam, LPARAM lParam)
 889 {
 890     TRY;
 891 
 892     JNIEnv *env = GetEnv();
 893     JNILocalFrame lframe(env, 10);
 894 
 895     SpyWinMessage(hWnd, message, TEXT("AwtToolkit"));
 896 
 897     AwtToolkit::GetInstance().eventNumber++;
 898     /*
 899      * Awt widget creation messages are routed here so that all
 900      * widgets are created on the main thread.  Java allows widgets
 901      * to live beyond their creating thread -- by creating them on
 902      * the main thread, a widget can always be properly disposed.
 903      */
 904     switch (message) {
 905       case WM_AWT_EXECUTE_SYNC: {
 906           jobject peerObject = (jobject)wParam;
 907           AwtObject* object = (AwtObject *)JNI_GET_PDATA(peerObject);
 908           DASSERT( !IsBadReadPtr(object, sizeof(AwtObject)));
 909           AwtObject::ExecuteArgs *args = (AwtObject::ExecuteArgs *)lParam;
 910           DASSERT(!IsBadReadPtr(args, sizeof(AwtObject::ExecuteArgs)));
 911           LRESULT result = 0;
 912           if (object != NULL)
 913           {
 914               result = object->WinThreadExecProc(args);
 915           }
 916           env->DeleteGlobalRef(peerObject);
 917           return result;
 918       }
 919       case WM_AWT_COMPONENT_CREATE: {
 920           ComponentCreatePacket* ccp = (ComponentCreatePacket*)lParam;
 921           DASSERT(ccp->factory != NULL);
 922           DASSERT(ccp->hComponent != NULL);
 923           (*ccp->factory)(ccp->hComponent, ccp->hParent);
 924           return 0;
 925       }
 926       case WM_AWT_DESTROY_WINDOW: {
 927           /* Destroy widgets from this same thread that created them */
 928           VERIFY(::DestroyWindow((HWND)wParam) != NULL);
 929           return 0;
 930       }
 931       case WM_AWT_DISPOSE: {
 932           if(wParam != NULL) {
 933               jobject self = (jobject)wParam;
 934               AwtObject *o = (AwtObject *) JNI_GET_PDATA(self);
 935               env->DeleteGlobalRef(self);
 936               if(o != NULL && theAwtObjectList.Remove(o)) {
 937                   o->Dispose();
 938               }
 939           }
 940           return 0;
 941       }
 942       case WM_AWT_DISPOSEPDATA: {
 943           /*
 944            * NOTE: synchronization routine (like in WM_AWT_DISPOSE) was omitted because
 945            * this handler is called ONLY while disposing Cursor and Font objects where
 946            * synchronization takes place.
 947            */
 948           AwtObject *o = (AwtObject *) wParam;
 949           if(o != NULL && theAwtObjectList.Remove(o)) {
 950               o->Dispose();
 951           }
 952           return 0;
 953       }
 954       case WM_AWT_DELETEOBJECT: {
 955           AwtObject *p = (AwtObject *) wParam;
 956           if (p->CanBeDeleted()) {
 957               // all the messages for this component are processed, so
 958               // it can be deleted
 959               delete p;
 960           } else {
 961               // postpone deletion, waiting for all the messages for this
 962               // component to be processed
 963               AwtToolkit::GetInstance().PostMessage(WM_AWT_DELETEOBJECT, wParam, (LPARAM)0);
 964           }
 965           return 0;
 966       }
 967       case WM_AWT_OBJECTLISTCLEANUP: {
 968           AwtObjectList::Cleanup();
 969           return 0;
 970       }
 971       case WM_SYSCOLORCHANGE: {
 972 
 973           jclass systemColorClass = env->FindClass("java/awt/SystemColor");
 974           DASSERT(systemColorClass);
 975           if (!systemColorClass) throw std::bad_alloc();
 976 
 977           jmethodID mid = env->GetStaticMethodID(systemColorClass, "updateSystemColors", "()V");
 978           DASSERT(mid);
 979           if (!mid) throw std::bad_alloc();
 980 
 981           env->CallStaticVoidMethod(systemColorClass, mid);
 982 
 983           /* FALL THROUGH - NO BREAK */
 984       }
 985 
 986       case WM_SETTINGCHANGE: {
 987           AwtWin32GraphicsDevice::ResetAllMonitorInfo();
 988           /* FALL THROUGH - NO BREAK */
 989       }
 990 // Remove this define when we move to newer (XP) version of SDK.
 991 #define WM_THEMECHANGED                 0x031A
 992       case WM_THEMECHANGED: {
 993           /* Upcall to WToolkit when user changes configuration.
 994            *
 995            * NOTE: there is a bug in Windows 98 and some older versions of
 996            * Windows NT (it seems to be fixed in NT4 SP5) where no
 997            * WM_SETTINGCHANGE is sent when any of the properties under
 998            * Control Panel -> Display are changed.  You must _always_ query
 999            * the system for these - you can't rely on cached values.
1000            */
1001           jobject peer = AwtToolkit::GetInstance().m_peer;
1002           if (peer != NULL) {
1003               env->CallVoidMethod(peer, AwtToolkit::windowsSettingChangeMID);
1004           }
1005           return 0;
1006       }
1007 #ifndef WM_DWMCOMPOSITIONCHANGED
1008 #define WM_DWMCOMPOSITIONCHANGED        0x031E
1009 #define WM_DWMNCRENDERINGCHANGED        0x031F
1010 #define WM_DWMCOLORIZATIONCOLORCHANGED  0x0320
1011 #define WM_DWMWINDOWMAXIMIZEDCHANGED    0x0321
1012 #endif // WM_DWMCOMPOSITIONCHANGED
1013       case WM_DWMCOMPOSITIONCHANGED: {
1014           DWMResetCompositionEnabled();
1015           return 0;
1016       }
1017 
1018       case WM_TIMER: {
1019           // 6479820. Should check if a window is in manual resizing process: skip
1020           // sending any MouseExit/Enter events while inside resize-loop.
1021           // Note that window being in manual moving process could still
1022           // produce redundant enter/exit mouse events. In future, they can be
1023           // made skipped in a similar way.
1024            if (AwtWindow::IsResizing()) {
1025                return 0;
1026            }
1027           // Create an artifical MouseExit message if the mouse left to
1028           // a non-java window (bad mouse!)
1029           POINT pt;
1030           AwtToolkit& tk = AwtToolkit::GetInstance();
1031           if (::GetCursorPos(&pt)) {
1032               HWND hWndOver = ::WindowFromPoint(pt);
1033               AwtComponent * last_M;
1034               if ( AwtComponent::GetComponent(hWndOver) == NULL && tk.m_lastMouseOver != NULL ) {
1035                   last_M = tk.m_lastMouseOver;
1036                   // translate point from screen to target window
1037                   MapWindowPoints(HWND_DESKTOP, last_M->GetHWnd(), &pt, 1);
1038                   last_M->SendMessage(WM_AWT_MOUSEEXIT,
1039                                       GetMouseKeyState(),
1040                                       POINTTOPOINTS(pt));
1041                   tk.m_lastMouseOver = 0;
1042               }
1043           }
1044           if (tk.m_lastMouseOver == NULL && tk.m_timer != 0) {
1045               VERIFY(::KillTimer(tk.m_toolkitHWnd, tk.m_timer));
1046               tk.m_timer = 0;
1047           }
1048           return 0;
1049       }
1050       case WM_DESTROYCLIPBOARD: {
1051           if (!AwtClipboard::IsGettingOwnership())
1052               AwtClipboard::LostOwnership((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2));
1053           return 0;
1054       }
1055       case WM_CHANGECBCHAIN: {
1056           AwtClipboard::WmChangeCbChain(wParam, lParam);
1057           return 0;
1058       }
1059       case WM_DRAWCLIPBOARD: {
1060           AwtClipboard::WmDrawClipboard((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), wParam, lParam);
1061           return 0;
1062       }
1063       case WM_AWT_LIST_SETMULTISELECT: {
1064           jobject peerObject = (jobject)wParam;
1065           AwtList* list = (AwtList *)JNI_GET_PDATA(peerObject);
1066           DASSERT( !IsBadReadPtr(list, sizeof(AwtObject)));
1067           list->SetMultiSelect(static_cast<BOOL>(lParam));
1068           return 0;
1069       }
1070 
1071       // Special awt message to call Imm APIs.
1072       // ImmXXXX() API must be used in the main thread.
1073       // In other thread these APIs does not work correctly even if
1074       // it returs with no error. (This restriction is not documented)
1075       // So we must use thse messages to call these APIs in main thread.
1076       case WM_AWT_CREATECONTEXT: {
1077         return reinterpret_cast<LRESULT>(
1078             reinterpret_cast<void*>(ImmCreateContext()));
1079       }
1080       case WM_AWT_DESTROYCONTEXT: {
1081           ImmDestroyContext((HIMC)wParam);
1082           return 0;
1083       }
1084       case WM_AWT_ASSOCIATECONTEXT: {
1085           EnableNativeIMEStruct *data = (EnableNativeIMEStruct*)wParam;
1086 
1087           jobject peer = data->peer;
1088           jobject self = data->self;
1089           jint context = data->context;
1090           jboolean useNativeCompWindow = data->useNativeCompWindow;
1091 
1092           AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
1093           if (comp != NULL)
1094           {
1095               comp->SetInputMethod(self, useNativeCompWindow);
1096               comp->ImmAssociateContext((HIMC)context);
1097           }
1098 
1099           if (peer != NULL) {
1100               env->DeleteGlobalRef(peer);
1101           }
1102           if (self != NULL) {
1103               env->DeleteGlobalRef(self);
1104           }
1105 
1106           delete data;
1107           return 0;
1108       }
1109       case WM_AWT_GET_DEFAULT_IME_HANDLER: {
1110           LRESULT ret = (LRESULT)FALSE;
1111           jobject peer = (jobject)wParam;
1112 
1113           AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
1114           if (comp != NULL) {
1115               HWND defaultIMEHandler = ImmGetDefaultIMEWnd(comp->GetHWnd());
1116               if (defaultIMEHandler != NULL) {
1117                   AwtToolkit::GetInstance().SetInputMethodWindow(defaultIMEHandler);
1118                   ret = (LRESULT)TRUE;
1119               }
1120           }
1121 
1122           if (peer != NULL) {
1123               env->DeleteGlobalRef(peer);
1124           }
1125           return ret;
1126       }
1127       case WM_AWT_HANDLE_NATIVE_IME_EVENT: {
1128           jobject peer = (jobject)wParam;
1129           AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
1130           MSG* msg = (MSG*)lParam;
1131 
1132           long modifiers = comp->GetJavaModifiers();
1133           if ((comp != NULL) && (msg->message==WM_CHAR || msg->message==WM_SYSCHAR)) {
1134               WCHAR unicodeChar = (WCHAR)msg->wParam;
1135               comp->SendKeyEvent(java_awt_event_KeyEvent_KEY_TYPED,
1136                                  0, //to be fixed nowMillis(),
1137                                  java_awt_event_KeyEvent_CHAR_UNDEFINED,
1138                                  unicodeChar,
1139                                  modifiers,
1140                                  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
1141                                  msg);
1142           } else if (comp != NULL) {
1143               MSG* pCopiedMsg = new MSG;
1144               *pCopiedMsg = *msg;
1145               comp->SendMessage(WM_AWT_HANDLE_EVENT, (WPARAM) FALSE,
1146                                 (LPARAM) pCopiedMsg);
1147           }
1148 
1149           if (peer != NULL) {
1150               env->DeleteGlobalRef(peer);
1151           }
1152           return 0;
1153       }
1154       case WM_AWT_ENDCOMPOSITION: {
1155           /*right now we just cancel the composition string
1156           may need to commit it in the furture
1157           Changed to commit it according to the flag 10/29/98*/
1158           ImmNotifyIME((HIMC)wParam, NI_COMPOSITIONSTR,
1159                        (lParam ? CPS_COMPLETE : CPS_CANCEL), 0);
1160           return 0;
1161       }
1162       case WM_AWT_SETCONVERSIONSTATUS: {
1163           DWORD cmode;
1164           DWORD smode;
1165           ImmGetConversionStatus((HIMC)wParam, (LPDWORD)&cmode, (LPDWORD)&smode);
1166           ImmSetConversionStatus((HIMC)wParam, (DWORD)LOWORD(lParam), smode);
1167           return 0;
1168       }
1169       case WM_AWT_GETCONVERSIONSTATUS: {
1170           DWORD cmode;
1171           DWORD smode;
1172           ImmGetConversionStatus((HIMC)wParam, (LPDWORD)&cmode, (LPDWORD)&smode);
1173           return cmode;
1174       }
1175       case WM_AWT_ACTIVATEKEYBOARDLAYOUT: {
1176           if (wParam && g_bUserHasChangedInputLang) {
1177               // Input language has been changed since the last WInputMethod.getNativeLocale()
1178               // call.  So let's honor the user's selection.
1179               // Note: we need to check this flag inside the toolkit thread to synchronize access
1180               // to the flag.
1181               return FALSE;
1182           }
1183 
1184           if (lParam == (LPARAM)::GetKeyboardLayout(0)) {
1185               // already active
1186               return FALSE;
1187           }
1188 
1189           // Since ActivateKeyboardLayout does not post WM_INPUTLANGCHANGEREQUEST,
1190           // we explicitly need to do the same thing here.
1191           static BYTE keyboardState[AwtToolkit::KB_STATE_SIZE];
1192           AwtToolkit::GetKeyboardState(keyboardState);
1193           WORD ignored;
1194           ::ToAscii(VK_SPACE, ::MapVirtualKey(VK_SPACE, 0),
1195                     keyboardState, &ignored, 0);
1196 
1197           return (LRESULT)activateKeyboardLayout((HKL)lParam);
1198       }
1199       case WM_AWT_OPENCANDIDATEWINDOW: {
1200           jobject peerObject = (jobject)wParam;
1201           AwtComponent* p = (AwtComponent*)JNI_GET_PDATA(peerObject);
1202           DASSERT( !IsBadReadPtr(p, sizeof(AwtObject)));
1203           // fix for 4805862: use GET_X_LPARAM and GET_Y_LPARAM macros
1204           // instead of LOWORD and HIWORD
1205           p->OpenCandidateWindow(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1206           env->DeleteGlobalRef(peerObject);
1207           return 0;
1208       }
1209 
1210       /*
1211        * send this message via ::SendMessage() and the MPT will acquire the
1212        * HANDLE synchronized with the sender's thread. The HANDLE must be
1213        * signalled or deadlock may occur between the MPT and the caller.
1214        */
1215 
1216       case WM_AWT_WAIT_FOR_SINGLE_OBJECT: {
1217         return ::WaitForSingleObject((HANDLE)lParam, INFINITE);
1218       }
1219       case WM_AWT_INVOKE_METHOD: {
1220         return (LRESULT)(*(void*(*)(void*))wParam)((void *)lParam);
1221       }
1222       case WM_AWT_INVOKE_VOID_METHOD: {
1223         return (LRESULT)(*(void*(*)(void))wParam)();
1224       }
1225 
1226       case WM_AWT_SETOPENSTATUS: {
1227           ImmSetOpenStatus((HIMC)wParam, (BOOL)lParam);
1228           return 0;
1229       }
1230       case WM_AWT_GETOPENSTATUS: {
1231           return (DWORD)ImmGetOpenStatus((HIMC)wParam);
1232       }
1233       case WM_DISPLAYCHANGE: {
1234           // Reinitialize screens
1235           initScreens(env);
1236 
1237           // Notify Java side - call WToolkit.displayChanged()
1238           jclass clazz = env->FindClass("sun/awt/windows/WToolkit");
1239           DASSERT(clazz != NULL);
1240           if (!clazz) throw std::bad_alloc();
1241           env->CallStaticVoidMethod(clazz, AwtToolkit::displayChangeMID);
1242 
1243           GetInstance().m_displayChanged = TRUE;
1244 
1245           ::PostMessage(HWND_BROADCAST, WM_PALETTEISCHANGING, NULL, NULL);
1246           break;
1247       }
1248       case WM_AWT_SETCURSOR: {
1249           ::SetCursor((HCURSOR)wParam);
1250           return TRUE;
1251       }
1252       /* Session management */
1253       case WM_QUERYENDSESSION: {
1254           /* Shut down cleanly */
1255           if (JVM_RaiseSignal(SIGTERM)) {
1256               AwtToolkit::GetInstance().m_vmSignalled = TRUE;
1257           }
1258           return TRUE;
1259       }
1260       case WM_ENDSESSION: {
1261           // Keep pumping messages until the shutdown sequence halts the VM,
1262           // or we exit the MessageLoop because of a WM_QUIT message
1263           AwtToolkit& tk = AwtToolkit::GetInstance();
1264 
1265           // if WM_QUERYENDSESSION hasn't successfully raised SIGTERM
1266           // we ignore the ENDSESSION message
1267           if (!tk.m_vmSignalled) {
1268               return 0;
1269           }
1270           tk.MessageLoop(AwtToolkit::PrimaryIdleFunc,
1271                          AwtToolkit::CommonPeekMessageFunc);
1272 
1273           // Dispose here instead of in eventLoop so that we don't have
1274           // to return from the WM_ENDSESSION handler.
1275           tk.Dispose();
1276 
1277           // Never return. The VM will halt the process.
1278           hang_if_shutdown();
1279 
1280           // Should never get here.
1281           DASSERT(FALSE);
1282           break;
1283       }
1284       case WM_SYNC_WAIT:
1285           SetEvent(AwtToolkit::GetInstance().m_waitEvent);
1286           break;
1287     }
1288 
1289     return DefWindowProc(hWnd, message, wParam, lParam);
1290 
1291     CATCH_BAD_ALLOC_RET(0);
1292 }
1293 
1294 LRESULT CALLBACK AwtToolkit::GetMessageFilter(int code,
1295                                               WPARAM wParam, LPARAM lParam)
1296 {
1297     TRY;
1298 
1299     if (code >= 0 && wParam == PM_REMOVE && lParam != 0) {
1300        if (AwtToolkit::GetInstance().PreProcessMsg(*(MSG*)lParam) !=
1301                mrPassAlong) {
1302            /* PreProcessMsg() wants us to eat it */
1303            ((MSG*)lParam)->message = WM_NULL;
1304        }
1305     }
1306     return ::CallNextHookEx(AwtToolkit::GetInstance().m_hGetMessageHook, code,
1307                             wParam, lParam);
1308 
1309     CATCH_BAD_ALLOC_RET(0);
1310 }
1311 
1312 void AwtToolkit::InstallMouseLowLevelHook()
1313 {
1314     // We need the low-level hook since we need to process mouse move
1315     // messages outside of our windows.
1316     m_hMouseLLHook = ::SetWindowsHookEx(WH_MOUSE_LL,
1317             (HOOKPROC)MouseLowLevelHook,
1318             GetModuleHandle(), NULL);
1319 
1320     // Reset the old value
1321     m_lastWindowUnderMouse = NULL;
1322 }
1323 
1324 void AwtToolkit::UninstallMouseLowLevelHook()
1325 {
1326     if (m_hMouseLLHook != 0) {
1327         ::UnhookWindowsHookEx(m_hMouseLLHook);
1328         m_hMouseLLHook = 0;
1329     }
1330 }
1331 
1332 LRESULT CALLBACK AwtToolkit::MouseLowLevelHook(int code,
1333         WPARAM wParam, LPARAM lParam)
1334 {
1335     TRY;
1336 
1337     if (code >= 0 && wParam == WM_MOUSEMOVE) {
1338         POINT pt = ((MSLLHOOKSTRUCT*)lParam)->pt;
1339 
1340         // We can't use GA_ROOTOWNER since in this case we'll go up to
1341         // the root Java toplevel, not the actual owned toplevel.
1342         HWND hwnd = ::GetAncestor(::WindowFromPoint(pt), GA_ROOT);
1343 
1344         AwtToolkit& tk = AwtToolkit::GetInstance();
1345 
1346         if (tk.m_lastWindowUnderMouse != hwnd) {
1347             AwtWindow *fw = NULL, *tw = NULL;
1348 
1349             if (tk.m_lastWindowUnderMouse) {
1350                 fw = (AwtWindow*)
1351                     AwtComponent::GetComponent(tk.m_lastWindowUnderMouse);
1352             }
1353             if (hwnd) {
1354                 tw = (AwtWindow*)AwtComponent::GetComponent(hwnd);
1355             }
1356 
1357             tk.m_lastWindowUnderMouse = hwnd;
1358 
1359             if (fw) {
1360                 fw->UpdateSecurityWarningVisibility();
1361             }
1362             // ... however, because we use GA_ROOT, we may find the warningIcon
1363             // which is not a Java windows.
1364             if (AwtWindow::IsWarningWindow(hwnd)) {
1365                 hwnd = ::GetParent(hwnd);
1366                 if (hwnd) {
1367                     tw = (AwtWindow*)AwtComponent::GetComponent(hwnd);
1368                 }
1369                 tk.m_lastWindowUnderMouse = hwnd;
1370             }
1371             if (tw) {
1372                 tw->UpdateSecurityWarningVisibility();
1373             }
1374 
1375 
1376         }
1377     }
1378 
1379     return ::CallNextHookEx(AwtToolkit::GetInstance().m_hMouseLLHook, code,
1380             wParam, lParam);
1381 
1382     CATCH_BAD_ALLOC_RET(0);
1383 }
1384 
1385 /*
1386  * The main message loop
1387  */
1388 
1389 const int AwtToolkit::EXIT_ENCLOSING_LOOP      = 0;
1390 const int AwtToolkit::EXIT_ALL_ENCLOSING_LOOPS = -1;
1391 
1392 
1393 /**
1394  * Called upon event idle to ensure that we have released any
1395  * CriticalSections that we took during window event processing.
1396  *
1397  * Note that this gets used more often than you would think; some
1398  * window moves actually happen over more than one event burst.  So,
1399  * for example, we might get a WINDOWPOSCHANGING event, then we
1400  * idle and release the lock here, then eventually we get the
1401  * WINDOWPOSCHANGED event.
1402  *
1403  * This method may be called from WToolkit.embeddedEventLoopIdleProcessing
1404  * if there is a separate event loop that must do the same CriticalSection
1405  * check.
1406  *
1407  * See bug #4526587 for more information.
1408  */
1409 void VerifyWindowMoveLockReleased()
1410 {
1411     if (windowMoveLockHeld) {
1412         windowMoveLockHeld = FALSE;
1413         windowMoveLock.Leave();
1414     }
1415 }
1416 
1417 UINT
1418 AwtToolkit::MessageLoop(IDLEPROC lpIdleFunc,
1419                         PEEKMESSAGEPROC lpPeekMessageFunc)
1420 {
1421     DTRACE_PRINTLN("AWT event loop started");
1422 
1423     DASSERT(lpIdleFunc != NULL);
1424     DASSERT(lpPeekMessageFunc != NULL);
1425 
1426     m_messageLoopResult = 0;
1427     while (!m_breakMessageLoop) {
1428 
1429         (*lpIdleFunc)();
1430 
1431         PumpWaitingMessages(lpPeekMessageFunc); /* pumps waiting messages */
1432 
1433         // Catch problems with windowMoveLock critical section.  In case we
1434         // misunderstood the way windows processes window move/resize
1435         // events, we don't want to hold onto the windowMoveLock CS forever.
1436         // If we've finished processing events for now, release the lock
1437         // if held.
1438         VerifyWindowMoveLockReleased();
1439     }
1440     if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
1441         ::PostQuitMessage(EXIT_ALL_ENCLOSING_LOOPS);
1442     m_breakMessageLoop = FALSE;
1443 
1444     DTRACE_PRINTLN("AWT event loop ended");
1445 
1446     return m_messageLoopResult;
1447 }
1448 
1449 /*
1450  * Exit the enclosing message loop(s).
1451  *
1452  * The message will be ignored if Windows is currently is in an internal
1453  * message loop (such as a scroll bar drag). So we first send IDCANCEL and
1454  * WM_CANCELMODE messages to every Window on the thread.
1455  */
1456 static BOOL CALLBACK CancelAllThreadWindows(HWND hWnd, LPARAM)
1457 {
1458     TRY;
1459 
1460     ::SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), (LPARAM)hWnd);
1461     ::SendMessage(hWnd, WM_CANCELMODE, 0, 0);
1462 
1463     return TRUE;
1464 
1465     CATCH_BAD_ALLOC_RET(FALSE);
1466 }
1467 
1468 static void DoQuitMessageLoop(void* param) {
1469     int status = *static_cast<int*>(param);
1470 
1471     AwtToolkit::GetInstance().QuitMessageLoop(status);
1472 }
1473 
1474 void AwtToolkit::QuitMessageLoop(int status) {
1475     /*
1476      * Fix for 4623377.
1477      * Reinvoke QuitMessageLoop on the toolkit thread, so that
1478      * m_breakMessageLoop is accessed on a single thread.
1479      */
1480     if (!AwtToolkit::IsMainThread()) {
1481         InvokeFunction(DoQuitMessageLoop, &status);
1482         return;
1483     }
1484 
1485     /*
1486      * Fix for BugTraq ID 4445747.
1487      * EnumThreadWindows() is very slow during dnd on Win9X/ME.
1488      * This call is unnecessary during dnd, since we postpone processing of all
1489      * messages that can enter internal message loop until dnd is over.
1490      */
1491       if (status == EXIT_ALL_ENCLOSING_LOOPS) {
1492           ::EnumThreadWindows(MainThread(), (WNDENUMPROC)CancelAllThreadWindows,
1493                               0);
1494       }
1495 
1496     /*
1497      * Fix for 4623377.
1498      * Modal loop may not exit immediatelly after WM_CANCELMODE, so it still can
1499      * eat WM_QUIT message and the nested message loop will never exit.
1500      * The fix is to use AwtToolkit instance variables instead of WM_QUIT to
1501      * guarantee that we exit from the nested message loop when any possible
1502      * modal loop quits. In this case CancelAllThreadWindows is needed only to
1503      * ensure that the nested message loop exits quickly and doesn't wait until
1504      * a possible modal loop completes.
1505      */
1506     m_breakMessageLoop = TRUE;
1507     m_messageLoopResult = status;
1508 
1509     /*
1510      * Fix for 4683602.
1511      * Post an empty message, to wake up the toolkit thread
1512      * if it is currently in WaitMessage(),
1513      */
1514     PostMessage(WM_NULL);
1515 }
1516 
1517 /*
1518  * Called by the message loop to pump the message queue when there are
1519  * messages waiting. Can also be called anywhere to pump messages.
1520  */
1521 BOOL AwtToolkit::PumpWaitingMessages(PEEKMESSAGEPROC lpPeekMessageFunc)
1522 {
1523     MSG  msg;
1524     BOOL foundOne = FALSE;
1525 
1526     DASSERT(lpPeekMessageFunc != NULL);
1527 
1528     while (!m_breakMessageLoop && (*lpPeekMessageFunc)(msg)) {
1529         foundOne = TRUE;
1530         ProcessMsg(msg);
1531     }
1532     return foundOne;
1533 }
1534 
1535 void AwtToolkit::PumpToDestroy(class AwtComponent* p)
1536 {
1537     MSG  msg;
1538 
1539     DASSERT(AwtToolkit::PrimaryIdleFunc != NULL);
1540     DASSERT(AwtToolkit::CommonPeekMessageFunc != NULL);
1541 
1542     while (p->IsDestroyPaused() && !m_breakMessageLoop) {
1543 
1544         PrimaryIdleFunc();
1545 
1546         while (p->IsDestroyPaused() && !m_breakMessageLoop && CommonPeekMessageFunc(msg)) {
1547             ProcessMsg(msg);
1548         }
1549     }
1550 }
1551 
1552 void AwtToolkit::ProcessMsg(MSG& msg)
1553 {
1554     if (msg.message == WM_QUIT) {
1555         m_breakMessageLoop = TRUE;
1556         m_messageLoopResult = static_cast<UINT>(msg.wParam);
1557         if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
1558             ::PostQuitMessage(static_cast<int>(msg.wParam));  // make sure all loops exit
1559     }
1560     else if (msg.message != WM_NULL) {
1561         /*
1562         * The AWT in standalone mode (that is, dynamically loaded from the
1563         * Java VM) doesn't have any translation tables to worry about, so
1564         * TranslateAccelerator isn't called.
1565         */
1566 
1567         ::TranslateMessage(&msg);
1568         ::DispatchMessage(&msg);
1569     }
1570 }
1571 
1572 VOID CALLBACK
1573 AwtToolkit::PrimaryIdleFunc() {
1574     AwtToolkit::SetBusy(FALSE);
1575     ::WaitMessage();               /* allow system to go idle */
1576     AwtToolkit::SetBusy(TRUE);
1577 }
1578 
1579 VOID CALLBACK
1580 AwtToolkit::SecondaryIdleFunc() {
1581     ::WaitMessage();               /* allow system to go idle */
1582 }
1583 
1584 BOOL
1585 AwtToolkit::CommonPeekMessageFunc(MSG& msg) {
1586     return ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
1587 }
1588 
1589 /*
1590  * Perform pre-processing on a message before it is translated &
1591  * dispatched.  Returns true to eat the message
1592  */
1593 BOOL AwtToolkit::PreProcessMsg(MSG& msg)
1594 {
1595     /*
1596      * Offer preprocessing first to the target component, then call out to
1597      * specific mouse and key preprocessor methods
1598      */
1599     AwtComponent* p = AwtComponent::GetComponent(msg.hwnd);
1600     if (p && p->PreProcessMsg(msg) == mrConsume)
1601         return TRUE;
1602 
1603     if ((msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) ||
1604         (msg.message >= WM_NCMOUSEMOVE && msg.message <= WM_NCMBUTTONDBLCLK)) {
1605         if (PreProcessMouseMsg(p, msg)) {
1606             return TRUE;
1607         }
1608     }
1609     else if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) {
1610         if (PreProcessKeyMsg(p, msg))
1611             return TRUE;
1612     }
1613     return FALSE;
1614 }
1615 
1616 BOOL AwtToolkit::PreProcessMouseMsg(AwtComponent* p, MSG& msg)
1617 {
1618     WPARAM mouseWParam;
1619     LPARAM mouseLParam;
1620 
1621     /*
1622      * Fix for BugTraq ID 4395290.
1623      * Do not synthesize mouse enter/exit events during drag-and-drop,
1624      * since it messes up LightweightDispatcher.
1625      */
1626     if (AwtDropTarget::IsLocalDnD()) {
1627         return FALSE;
1628     }
1629 
1630     if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) {
1631         mouseWParam = msg.wParam;
1632         mouseLParam = msg.lParam;
1633     } else {
1634         mouseWParam = GetMouseKeyState();
1635     }
1636 
1637     /*
1638      * Get the window under the mouse, as it will be different if its
1639      * captured.
1640      */
1641     DWORD dwCurPos = ::GetMessagePos();
1642     DWORD dwScreenPos = dwCurPos;
1643     POINT curPos;
1644     // fix for 4805862
1645     // According to MSDN: do not use LOWORD and HIWORD macros to extract x and
1646     // y coordinates because these macros return incorrect results on systems
1647     // with multiple monitors (signed values are treated as unsigned)
1648     curPos.x = GET_X_LPARAM(dwCurPos);
1649     curPos.y = GET_Y_LPARAM(dwCurPos);
1650     HWND hWndFromPoint = ::WindowFromPoint(curPos);
1651     // hWndFromPoint == 0 if mouse is over a scrollbar
1652     AwtComponent* mouseComp =
1653         AwtComponent::GetComponent(hWndFromPoint);
1654     // Need extra copies for non-client area issues
1655     HWND hWndForWheel = hWndFromPoint;
1656 
1657     // If the point under the mouse isn't in the client area,
1658     // ignore it to maintain compatibility with Solaris (#4095172)
1659     RECT windowRect;
1660     ::GetClientRect(hWndFromPoint, &windowRect);
1661     POINT topLeft;
1662     topLeft.x = 0;
1663     topLeft.y = 0;
1664     ::ClientToScreen(hWndFromPoint, &topLeft);
1665     windowRect.top += topLeft.y;
1666     windowRect.bottom += topLeft.y;
1667     windowRect.left += topLeft.x;
1668     windowRect.right += topLeft.x;
1669     if ((curPos.y < windowRect.top) ||
1670         (curPos.y >= windowRect.bottom) ||
1671         (curPos.x < windowRect.left) ||
1672         (curPos.x >= windowRect.right)) {
1673         mouseComp = NULL;
1674         hWndFromPoint = NULL;
1675     }
1676 
1677     /*
1678      * Look for mouse transitions between windows & create
1679      * MouseExit & MouseEnter messages
1680      */
1681     // 6479820. Should check if a window is in manual resizing process: skip
1682     // sending any MouseExit/Enter events while inside resize-loop.
1683     // Note that window being in manual moving process could still
1684     // produce redundant enter/exit mouse events. In future, they can be
1685     // made skipped in a similar way.
1686     if (mouseComp != m_lastMouseOver && !AwtWindow::IsResizing()) {
1687         /*
1688          * Send the messages right to the windows so that they are in
1689          * the right sequence.
1690          */
1691         if (m_lastMouseOver) {
1692             dwCurPos = dwScreenPos;
1693             curPos.x = LOWORD(dwCurPos);
1694             curPos.y = HIWORD(dwCurPos);
1695             ::MapWindowPoints(HWND_DESKTOP, m_lastMouseOver->GetHWnd(),
1696                               &curPos, 1);
1697             mouseLParam = MAKELPARAM((WORD)curPos.x, (WORD)curPos.y);
1698             m_lastMouseOver->SendMessage(WM_AWT_MOUSEEXIT, mouseWParam,
1699                                          mouseLParam);
1700         }
1701         if (mouseComp) {
1702                 dwCurPos = dwScreenPos;
1703                 curPos.x = LOWORD(dwCurPos);
1704                 curPos.y = HIWORD(dwCurPos);
1705                 ::MapWindowPoints(HWND_DESKTOP, mouseComp->GetHWnd(),
1706                                   &curPos, 1);
1707                 mouseLParam = MAKELPARAM((WORD)curPos.x, (WORD)curPos.y);
1708             mouseComp->SendMessage(WM_AWT_MOUSEENTER, mouseWParam,
1709                                    mouseLParam);
1710         }
1711         m_lastMouseOver = mouseComp;
1712     }
1713 
1714     /*
1715      * For MouseWheelEvents, hwnd must be changed to be the Component under
1716      * the mouse, not the Component with the input focus.
1717      */
1718 
1719     if (msg.message == WM_MOUSEWHEEL) {
1720             //i.e. mouse is over client area for this window
1721             DWORD hWndForWheelProcess;
1722             DWORD hWndForWheelThread = ::GetWindowThreadProcessId(hWndForWheel, &hWndForWheelProcess);
1723             if (::GetCurrentProcessId() == hWndForWheelProcess) {
1724                 if (AwtToolkit::MainThread() == hWndForWheelThread) {
1725                     msg.hwnd = hWndForWheel;
1726                 } else {
1727                     // Interop mode, redispatch the event to another toolkit.
1728                     ::SendMessage(hWndForWheel, msg.message, mouseWParam, mouseLParam);
1729                     return TRUE;
1730                 }
1731             }
1732     }
1733 
1734     /*
1735      * Make sure we get at least one last chance to check for transitions
1736      * before we sleep
1737      */
1738     if (m_lastMouseOver && !m_timer) {
1739         m_timer = ::SetTimer(m_toolkitHWnd, IDT_AWT_MOUSECHECK, 200, 0);
1740     }
1741     return FALSE;  /* Now go ahead and process current message as usual */
1742 }
1743 
1744 BOOL AwtToolkit::PreProcessKeyMsg(AwtComponent* p, MSG& msg)
1745 {
1746     // get keyboard state for use in AwtToolkit::GetKeyboardState
1747     CriticalSection::Lock       l(m_lockKB);
1748     ::GetKeyboardState(m_lastKeyboardState);
1749     return FALSE;
1750 }
1751 
1752 void *AwtToolkit::SyncCall(void *(*ftn)(void *), void *param) {
1753     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1754     if (!IsMainThread()) {
1755         CriticalSection::Lock l(GetSyncCS());
1756         return (*ftn)(param);
1757     } else {
1758         return (*ftn)(param);
1759     }
1760 }
1761 
1762 void AwtToolkit::SyncCall(void (*ftn)(void *), void *param) {
1763     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1764     if (!IsMainThread()) {
1765         CriticalSection::Lock l(GetSyncCS());
1766         (*ftn)(param);
1767     } else {
1768         (*ftn)(param);
1769     }
1770 }
1771 
1772 void *AwtToolkit::SyncCall(void *(*ftn)(void)) {
1773     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1774     if (!IsMainThread()) {
1775         CriticalSection::Lock l(GetSyncCS());
1776         return (*ftn)();
1777     } else {
1778         return (*ftn)();
1779     }
1780 }
1781 
1782 void AwtToolkit::SyncCall(void (*ftn)(void)) {
1783     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1784     if (!IsMainThread()) {
1785         CriticalSection::Lock l(GetSyncCS());
1786         (*ftn)();
1787     } else {
1788         (*ftn)();
1789     }
1790 }
1791 
1792 UINT AwtToolkit::CreateCmdID(AwtObject* object)
1793 {
1794     return m_cmdIDs->Add(object);
1795 }
1796 
1797 void AwtToolkit::RemoveCmdID(UINT id)
1798 {
1799     m_cmdIDs->Remove(id);
1800 }
1801 
1802 AwtObject* AwtToolkit::LookupCmdID(UINT id)
1803 {
1804     return m_cmdIDs->Lookup(id);
1805 }
1806 
1807 HICON AwtToolkit::GetAwtIcon()
1808 {
1809     return ::LoadIcon(GetModuleHandle(), TEXT("AWT_ICON"));
1810 }
1811 
1812 HICON AwtToolkit::GetAwtIconSm()
1813 {
1814     static HICON defaultIconSm = NULL;
1815     static int prevSmx = 0;
1816     static int prevSmy = 0;
1817 
1818     int smx = GetSystemMetrics(SM_CXSMICON);
1819     int smy = GetSystemMetrics(SM_CYSMICON);
1820 
1821     // Fixed 6364216: LoadImage() may leak memory
1822     if (defaultIconSm == NULL || smx != prevSmx || smy != prevSmy) {
1823         defaultIconSm = (HICON)LoadImage(GetModuleHandle(), TEXT("AWT_ICON"), IMAGE_ICON, smx, smy, 0);
1824         prevSmx = smx;
1825         prevSmy = smy;
1826     }
1827     return defaultIconSm;
1828 }
1829 
1830 // The icon at index 0 must be gray. See AwtWindow::GetSecurityWarningIcon()
1831 HICON AwtToolkit::GetSecurityWarningIcon(UINT index, UINT w, UINT h)
1832 {
1833     //Note: should not exceed 10 because of the current implementation.
1834     static const int securityWarningIconCounter = 3;
1835 
1836     static HICON securityWarningIcon[securityWarningIconCounter]      = {NULL, NULL, NULL};;
1837     static UINT securityWarningIconWidth[securityWarningIconCounter]  = {0, 0, 0};
1838     static UINT securityWarningIconHeight[securityWarningIconCounter] = {0, 0, 0};
1839 
1840     index = AwtToolkit::CalculateWave(index, securityWarningIconCounter);
1841 
1842     if (securityWarningIcon[index] == NULL ||
1843             w != securityWarningIconWidth[index] ||
1844             h != securityWarningIconHeight[index])
1845     {
1846         if (securityWarningIcon[index] != NULL)
1847         {
1848             ::DestroyIcon(securityWarningIcon[index]);
1849         }
1850 
1851         static const wchar_t securityWarningIconName[] = L"SECURITY_WARNING_";
1852         wchar_t iconResourceName[sizeof(securityWarningIconName) + 2];
1853         ::ZeroMemory(iconResourceName, sizeof(iconResourceName));
1854         wcscpy(iconResourceName, securityWarningIconName);
1855 
1856         wchar_t strIndex[2];
1857         ::ZeroMemory(strIndex, sizeof(strIndex));
1858         strIndex[0] = L'0' + index;
1859 
1860         wcscat(iconResourceName, strIndex);
1861 
1862         securityWarningIcon[index] = (HICON)::LoadImage(GetModuleHandle(),
1863                 iconResourceName,
1864                 IMAGE_ICON, w, h, LR_DEFAULTCOLOR);
1865         securityWarningIconWidth[index] = w;
1866         securityWarningIconHeight[index] = h;
1867     }
1868 
1869     return securityWarningIcon[index];
1870 }
1871 
1872 void AwtToolkit::SetHeapCheck(long flag) {
1873     if (flag) {
1874         printf("heap checking not supported with this build\n");
1875     }
1876 }
1877 
1878 void throw_if_shutdown(void) throw (awt_toolkit_shutdown)
1879 {
1880     AwtToolkit::GetInstance().VerifyActive();
1881 }
1882 void hang_if_shutdown(void)
1883 {
1884     try {
1885         AwtToolkit::GetInstance().VerifyActive();
1886     } catch (awt_toolkit_shutdown&) {
1887         // Never return. The VM will halt the process.
1888         ::WaitForSingleObject(::CreateEvent(NULL, TRUE, FALSE, NULL),
1889                               INFINITE);
1890         // Should never get here.
1891         DASSERT(FALSE);
1892     }
1893 }
1894 
1895 // for now we support only one embedder, but should be ready for future
1896 void AwtToolkit::RegisterEmbedderProcessId(HWND embedder)
1897 {
1898     if (m_embedderProcessID) {
1899         // we already set embedder process and do not expect
1900         // two different processes to embed the same AwtToolkit
1901         return;
1902     }
1903 
1904     embedder = ::GetAncestor(embedder, GA_ROOT);
1905     ::GetWindowThreadProcessId(embedder, &m_embedderProcessID);
1906 }
1907 
1908 JNIEnv* AwtToolkit::m_env;
1909 DWORD AwtToolkit::m_threadId;
1910 
1911 void AwtToolkit::SetEnv(JNIEnv *env) {
1912     if (m_env != NULL) { // If already cashed (by means of embeddedInit() call).
1913         return;
1914     }
1915     m_threadId = GetCurrentThreadId();
1916     m_env = env;
1917 }
1918 
1919 JNIEnv* AwtToolkit::GetEnv() {
1920     return (m_env == NULL || m_threadId != GetCurrentThreadId()) ?
1921         (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2) : m_env;
1922 }
1923 
1924 BOOL AwtToolkit::GetScreenInsets(int screenNum, RECT * rect)
1925 {
1926     /* if primary display */
1927     if (screenNum == 0) {
1928         RECT rRW;
1929         if (::SystemParametersInfo(SPI_GETWORKAREA,0,(void *) &rRW,0) == TRUE) {
1930             rect->top = rRW.top;
1931             rect->left = rRW.left;
1932             rect->bottom = ::GetSystemMetrics(SM_CYSCREEN) - rRW.bottom;
1933             rect->right = ::GetSystemMetrics(SM_CXSCREEN) - rRW.right;
1934             return TRUE;
1935         }
1936     }
1937     /* if additional display */
1938     else {
1939         MONITORINFO *miInfo;
1940         miInfo = AwtWin32GraphicsDevice::GetMonitorInfo(screenNum);
1941         if (miInfo) {
1942             rect->top = miInfo->rcWork.top    - miInfo->rcMonitor.top;
1943             rect->left = miInfo->rcWork.left   - miInfo->rcMonitor.left;
1944             rect->bottom = miInfo->rcMonitor.bottom - miInfo->rcWork.bottom;
1945             rect->right = miInfo->rcMonitor.right - miInfo->rcWork.right;
1946             return TRUE;
1947         }
1948     }
1949     return FALSE;
1950 }
1951 
1952 
1953 void AwtToolkit::GetWindowRect(HWND hWnd, LPRECT lpRect)
1954 {
1955     try {
1956         if (S_OK == DwmAPI::DwmGetWindowAttribute(hWnd,
1957                 DwmAPI::DWMWA_EXTENDED_FRAME_BOUNDS,
1958                 lpRect, sizeof(*lpRect)))
1959         {
1960             return;
1961         }
1962     } catch (const DllUtil::Exception &) {}
1963 
1964     ::GetWindowRect(hWnd, lpRect);
1965 }
1966 
1967 
1968 /************************************************************************
1969  * AWT preloading support
1970  */
1971 bool AwtToolkit::PreloadAction::EnsureInited()
1972 {
1973     DWORD _initThreadId = GetInitThreadID();
1974     if (_initThreadId != 0) {
1975         // already inited
1976         // ensure the action is inited on correct thread
1977         PreloadThread &preloadThread
1978             = AwtToolkit::GetInstance().GetPreloadThread();
1979         if (_initThreadId == preloadThread.GetThreadId()) {
1980             if (!preloadThread.IsWrongThread()) {
1981                 return true;
1982             }
1983             // inited on preloadThread (wrongThread), not cleaned yet
1984             // have to wait cleanup completion
1985             preloadThread.Wait4Finish();
1986         } else {
1987             // inited on other thread (Toolkit thread?)
1988             // consider as correctly inited
1989             return true;
1990         }
1991     }
1992 
1993     // init on Toolkit thread
1994     AwtToolkit::GetInstance().InvokeFunction(InitWrapper, this);
1995 
1996     return true;
1997 }
1998 
1999 DWORD AwtToolkit::PreloadAction::GetInitThreadID()
2000 {
2001     CriticalSection::Lock lock(initLock);
2002     return initThreadId;
2003 }
2004 
2005 bool AwtToolkit::PreloadAction::Clean()
2006 {
2007     DWORD _initThreadId = GetInitThreadID();
2008     if (_initThreadId == ::GetCurrentThreadId()) {
2009         // inited on this thread
2010         Clean(false);
2011         return true;
2012     }
2013     return false;
2014 }
2015 
2016 /*static*/
2017 void AwtToolkit::PreloadAction::InitWrapper(void *param)
2018 {
2019     PreloadAction *pThis = (PreloadAction *)param;
2020     pThis->Init();
2021 }
2022 
2023 void AwtToolkit::PreloadAction::Init()
2024 {
2025     CriticalSection::Lock lock(initLock);
2026     if (initThreadId == 0) {
2027         initThreadId = ::GetCurrentThreadId();
2028         InitImpl();
2029     }
2030 }
2031 
2032 void AwtToolkit::PreloadAction::Clean(bool reInit) {
2033     CriticalSection::Lock lock(initLock);
2034     if (initThreadId != 0) {
2035         //ASSERT(initThreadId == ::GetCurrentThreadId());
2036         CleanImpl(reInit);
2037         initThreadId = 0;
2038     }
2039 }
2040 
2041 // PreloadThread implementation
2042 AwtToolkit::PreloadThread::PreloadThread()
2043     : status(None), wrongThread(false), threadId(0),
2044     pActionChain(NULL), pLastProcessedAction(NULL),
2045     execFunc(NULL), execParam(NULL)
2046 {
2047     hFinished = ::CreateEvent(NULL, TRUE, FALSE, NULL);
2048     hAwake = ::CreateEvent(NULL, FALSE, FALSE, NULL);
2049 }
2050 
2051 AwtToolkit::PreloadThread::~PreloadThread()
2052 {
2053     //Terminate(false);
2054     ::CloseHandle(hFinished);
2055     ::CloseHandle(hAwake);
2056 }
2057 
2058 bool AwtToolkit::PreloadThread::AddAction(AwtToolkit::PreloadAction *pAction)
2059 {
2060     CriticalSection::Lock lock(threadLock);
2061 
2062     if (status > Preloading) {
2063         // too late - the thread already terminated or run as toolkit thread
2064         return false;
2065     }
2066 
2067     if (pActionChain == NULL) {
2068         // 1st action
2069         pActionChain = pAction;
2070     } else {
2071         // add the action to the chain
2072         PreloadAction *pChain = pActionChain;
2073         while (true) {
2074             PreloadAction *pNext = pChain->GetNext();
2075             if (pNext == NULL) {
2076                 break;
2077             }
2078             pChain = pNext;
2079         }
2080         pChain->SetNext(pAction);
2081     }
2082 
2083     if (status > None) {
2084         // the thread is already running (status == Preloading)
2085         AwakeThread();
2086         return true;
2087     }
2088 
2089     // need to start thread
2090     ::ResetEvent(hAwake);
2091     ::ResetEvent(hFinished);
2092 
2093     HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0x100000, StaticThreadProc,
2094                                             this, 0, &threadId);
2095 
2096     if (hThread == 0) {
2097         threadId = 0;
2098         return false;
2099     }
2100 
2101     status = Preloading;
2102 
2103     ::CloseHandle(hThread);
2104 
2105     return true;
2106 }
2107 
2108 bool AwtToolkit::PreloadThread::Terminate(bool wrongThread)
2109 {
2110     CriticalSection::Lock lock(threadLock);
2111 
2112     if (status != Preloading) {
2113         return false;
2114     }
2115 
2116     execFunc = NULL;
2117     execParam = NULL;
2118     this->wrongThread = wrongThread;
2119     status = Cleaning;
2120     AwakeThread();
2121 
2122     return true;
2123 }
2124 
2125 bool AwtToolkit::PreloadThread::InvokeAndTerminate(void(_cdecl *fn)(void *), void *param)
2126 {
2127     CriticalSection::Lock lock(threadLock);
2128 
2129     if (status != Preloading) {
2130         return false;
2131     }
2132 
2133     execFunc = fn;
2134     execParam = param;
2135     status = fn == NULL ? Cleaning : RunningToolkit;
2136     AwakeThread();
2137 
2138     return true;
2139 }
2140 
2141 bool AwtToolkit::PreloadThread::OnPreloadThread()
2142 {
2143     return GetThreadId() == ::GetCurrentThreadId();
2144 }
2145 
2146 /*static*/
2147 unsigned WINAPI AwtToolkit::PreloadThread::StaticThreadProc(void *param)
2148 {
2149     AwtToolkit::PreloadThread *pThis = (AwtToolkit::PreloadThread *)param;
2150     return pThis->ThreadProc();
2151 }
2152 
2153 unsigned AwtToolkit::PreloadThread::ThreadProc()
2154 {
2155     void(_cdecl *_execFunc)(void *) = NULL;
2156     void *_execParam = NULL;
2157     bool _wrongThread = false;
2158 
2159     // initialization
2160     while (true) {
2161         PreloadAction *pAction;
2162         {
2163             CriticalSection::Lock lock(threadLock);
2164             if (status != Preloading) {
2165                 // get invoke parameters
2166                 _execFunc = execFunc;
2167                 _execParam = execParam;
2168                 _wrongThread = wrongThread;
2169                 break;
2170             }
2171             pAction = GetNextAction();
2172         }
2173         if (pAction != NULL) {
2174             pAction->Init();
2175         } else {
2176             ::WaitForSingleObject(hAwake, INFINITE);
2177         }
2178     }
2179 
2180     // call a function from InvokeAndTerminate
2181     if (_execFunc != NULL) {
2182         _execFunc(_execParam);
2183     } else {
2184         // time to terminate..
2185     }
2186 
2187     // cleanup
2188     {
2189         CriticalSection::Lock lock(threadLock);
2190         pLastProcessedAction = NULL; // goto 1st action in the chain
2191         status = Cleaning;
2192     }
2193     for (PreloadAction *pAction = GetNextAction(); pAction != NULL;
2194             pAction = GetNextAction()) {
2195         pAction->Clean(_wrongThread);
2196     }
2197 
2198     // don't clear threadId! it is used by PreloadAction::EnsureInited
2199 
2200     {
2201         CriticalSection::Lock lock(threadLock);
2202         status = Finished;
2203     }
2204     ::SetEvent(hFinished);
2205     return 0;
2206 }
2207 
2208 AwtToolkit::PreloadAction* AwtToolkit::PreloadThread::GetNextAction()
2209 {
2210     CriticalSection::Lock lock(threadLock);
2211     PreloadAction *pAction = (pLastProcessedAction == NULL)
2212                                     ? pActionChain
2213                                     : pLastProcessedAction->GetNext();
2214     if (pAction != NULL) {
2215         pLastProcessedAction = pAction;
2216     }
2217 
2218     return pAction;
2219 }
2220 
2221 
2222 extern "C" {
2223 
2224 /* Terminates preload thread (if it's still alive
2225  * - it may occur if the application doesn't use AWT).
2226  * The function is called from launcher after completion main java thread.
2227  */
2228 __declspec(dllexport) void preloadStop()
2229 {
2230     AwtToolkit::GetInstance().GetPreloadThread().Terminate(false);
2231 }
2232 
2233 }
2234 
2235 
2236 /************************************************************************
2237  * Toolkit native methods
2238  */
2239 
2240 extern "C" {
2241 
2242 /*
2243  * Class:     java_awt_Toolkit
2244  * Method:    initIDs
2245  * Signature: ()V
2246  */
2247 JNIEXPORT void JNICALL
2248 Java_java_awt_Toolkit_initIDs(JNIEnv *env, jclass cls) {
2249     TRY;
2250 
2251     AwtToolkit::getDefaultToolkitMID =
2252         env->GetStaticMethodID(cls,"getDefaultToolkit","()Ljava/awt/Toolkit;");
2253     DASSERT(AwtToolkit::getDefaultToolkitMID != NULL);
2254     CHECK_NULL(AwtToolkit::getDefaultToolkitMID);
2255 
2256     AwtToolkit::getFontMetricsMID =
2257         env->GetMethodID(cls, "getFontMetrics", "(Ljava/awt/Font;)Ljava/awt/FontMetrics;");
2258     DASSERT(AwtToolkit::getFontMetricsMID != NULL);
2259     CHECK_NULL(AwtToolkit::getFontMetricsMID);
2260 
2261     jclass insetsClass = env->FindClass("java/awt/Insets");
2262     DASSERT(insetsClass != NULL);
2263     CHECK_NULL(insetsClass);
2264     AwtToolkit::insetsMID = env->GetMethodID(insetsClass, "<init>", "(IIII)V");
2265     DASSERT(AwtToolkit::insetsMID != NULL);
2266     CHECK_NULL(AwtToolkit::insetsMID);
2267 
2268     CATCH_BAD_ALLOC;
2269 }
2270 
2271 
2272 } /* extern "C" */
2273 
2274 /************************************************************************
2275  * WToolkit native methods
2276  */
2277 
2278 extern "C" {
2279 
2280 /*
2281  * Class:     sun_awt_windows_WToolkit
2282  * Method:    initIDs
2283  * Signature: ()V
2284  */
2285 JNIEXPORT void JNICALL
2286 Java_sun_awt_windows_WToolkit_initIDs(JNIEnv *env, jclass cls)
2287 {
2288     TRY;
2289 
2290     AwtToolkit::windowsSettingChangeMID =
2291         env->GetMethodID(cls, "windowsSettingChange", "()V");
2292     DASSERT(AwtToolkit::windowsSettingChangeMID != 0);
2293     CHECK_NULL(AwtToolkit::windowsSettingChangeMID);
2294 
2295     AwtToolkit::displayChangeMID =
2296     env->GetStaticMethodID(cls, "displayChanged", "()V");
2297     DASSERT(AwtToolkit::displayChangeMID != 0);
2298     CHECK_NULL(AwtToolkit::displayChangeMID);
2299 
2300     // Set various global IDs needed by JAWT code.  Note: these
2301     // variables cannot be set by JAWT code directly due to
2302     // different permissions that that code may be run under
2303     // (bug 4796548).  It would be nice to initialize these
2304     // variables lazily, but given the minimal number of calls
2305     // for this, it seems simpler to just do it at startup with
2306     // negligible penalty.
2307     jclass sDataClassLocal = env->FindClass("sun/java2d/SurfaceData");
2308     DASSERT(sDataClassLocal != 0);
2309     CHECK_NULL(sDataClassLocal);
2310 
2311     jclass vImgClassLocal = env->FindClass("sun/awt/image/SunVolatileImage");
2312     DASSERT(vImgClassLocal != 0);
2313     CHECK_NULL(vImgClassLocal);
2314 
2315     jclass vSMgrClassLocal =
2316         env->FindClass("sun/awt/image/VolatileSurfaceManager");
2317     DASSERT(vSMgrClassLocal != 0);
2318     CHECK_NULL(vSMgrClassLocal);
2319 
2320     jclass componentClassLocal = env->FindClass("java/awt/Component");
2321     DASSERT(componentClassLocal != 0);
2322     CHECK_NULL(componentClassLocal);
2323 
2324     jawtSMgrID = env->GetFieldID(vImgClassLocal, "volSurfaceManager",
2325                                  "Lsun/awt/image/VolatileSurfaceManager;");
2326     DASSERT(jawtSMgrID != 0);
2327     CHECK_NULL(jawtSMgrID);
2328 
2329     jawtSDataID = env->GetFieldID(vSMgrClassLocal, "sdCurrent",
2330                                   "Lsun/java2d/SurfaceData;");
2331     DASSERT(jawtSDataID != 0);
2332     CHECK_NULL(jawtSDataID);
2333 
2334     jawtPDataID = env->GetFieldID(sDataClassLocal, "pData", "J");
2335     DASSERT(jawtPDataID != 0);
2336     CHECK_NULL(jawtPDataID);
2337     // Save these classes in global references for later use
2338     jawtVImgClass = (jclass)env->NewGlobalRef(vImgClassLocal);
2339     CHECK_NULL(jawtVImgClass);
2340     jawtComponentClass = (jclass)env->NewGlobalRef(componentClassLocal);
2341 
2342     CATCH_BAD_ALLOC;
2343 }
2344 
2345 
2346 /*
2347  * Class:     sun_awt_windows_Toolkit
2348  * Method:    disableCustomPalette
2349  * Signature: ()V
2350  */
2351 JNIEXPORT void JNICALL
2352 Java_sun_awt_windows_WToolkit_disableCustomPalette(JNIEnv *env, jclass cls) {
2353     AwtPalette::DisableCustomPalette();
2354 }
2355 
2356 /*
2357  * Class:     sun_awt_windows_WToolkit
2358  * Method:    embeddedInit
2359  * Signature: ()Z
2360  */
2361 JNIEXPORT jboolean JNICALL
2362 Java_sun_awt_windows_WToolkit_embeddedInit(JNIEnv *env, jclass cls)
2363 {
2364     TRY;
2365 
2366     AwtToolkit::SetEnv(env);
2367 
2368     return AwtToolkit::GetInstance().Initialize(FALSE);
2369 
2370     CATCH_BAD_ALLOC_RET(JNI_FALSE);
2371 }
2372 
2373 /*
2374  * Class:     sun_awt_windows_WToolkit
2375  * Method:    embeddedDispose
2376  * Signature: ()Z
2377  */
2378 JNIEXPORT jboolean JNICALL
2379 Java_sun_awt_windows_WToolkit_embeddedDispose(JNIEnv *env, jclass cls)
2380 {
2381     TRY;
2382 
2383     BOOL retval = AwtToolkit::GetInstance().Dispose();
2384     AwtToolkit::GetInstance().SetPeer(env, NULL);
2385     return retval;
2386 
2387     CATCH_BAD_ALLOC_RET(JNI_FALSE);
2388 }
2389 
2390 /*
2391  * Class:     sun_awt_windows_WToolkit
2392  * Method:    embeddedEventLoopIdleProcessing
2393  * Signature: ()V
2394  */
2395 JNIEXPORT void JNICALL
2396 Java_sun_awt_windows_WToolkit_embeddedEventLoopIdleProcessing(JNIEnv *env,
2397     jobject self)
2398 {
2399     VerifyWindowMoveLockReleased();
2400 }
2401 
2402 
2403 /*
2404  * Class:     sun_awt_windows_WToolkit
2405  * Method:    init
2406  * Signature: ()Z
2407  */
2408 JNIEXPORT jboolean JNICALL
2409 Java_sun_awt_windows_WToolkit_init(JNIEnv *env, jobject self)
2410 {
2411     TRY;
2412 
2413     AwtToolkit::SetEnv(env);
2414 
2415     AwtToolkit::GetInstance().SetPeer(env, self);
2416 
2417     // This call will fail if the Toolkit was already initialized.
2418     // In that case, we don't want to start another message pump.
2419     return AwtToolkit::GetInstance().Initialize(TRUE);
2420 
2421     CATCH_BAD_ALLOC_RET(FALSE);
2422 }
2423 
2424 /*
2425  * Class:     sun_awt_windows_WToolkit
2426  * Method:    eventLoop
2427  * Signature: ()V
2428  */
2429 JNIEXPORT void JNICALL
2430 Java_sun_awt_windows_WToolkit_eventLoop(JNIEnv *env, jobject self)
2431 {
2432     TRY;
2433 
2434     DASSERT(AwtToolkit::GetInstance().localPump());
2435 
2436     AwtToolkit::SetBusy(TRUE);
2437 
2438     AwtToolkit::GetInstance().MessageLoop(AwtToolkit::PrimaryIdleFunc,
2439                                           AwtToolkit::CommonPeekMessageFunc);
2440 
2441     AwtToolkit::GetInstance().Dispose();
2442 
2443     AwtToolkit::SetBusy(FALSE);
2444 
2445     /*
2446      * IMPORTANT NOTES:
2447      *   The AwtToolkit has been destructed by now.
2448      * DO NOT CALL any method of AwtToolkit!!!
2449      */
2450 
2451     CATCH_BAD_ALLOC;
2452 }
2453 
2454 /*
2455  * Class:     sun_awt_windows_WToolkit
2456  * Method:    shutdown
2457  * Signature: ()V
2458  */
2459 JNIEXPORT void JNICALL
2460 Java_sun_awt_windows_WToolkit_shutdown(JNIEnv *env, jobject self)
2461 {
2462     TRY;
2463 
2464     AwtToolkit& tk = AwtToolkit::GetInstance();
2465 
2466     tk.QuitMessageLoop(AwtToolkit::EXIT_ALL_ENCLOSING_LOOPS);
2467 
2468     while (!tk.IsDisposed()) {
2469         Sleep(100);
2470     }
2471 
2472     CATCH_BAD_ALLOC;
2473 }
2474 
2475 /*
2476  * Class:     sun_awt_windows_WToolkit
2477  * Method:    startSecondaryEventLoop
2478  * Signature: ()V;
2479  */
2480 JNIEXPORT void JNICALL
2481 Java_sun_awt_windows_WToolkit_startSecondaryEventLoop(
2482     JNIEnv *env,
2483     jclass)
2484 {
2485     TRY;
2486 
2487     DASSERT(AwtToolkit::MainThread() == ::GetCurrentThreadId());
2488 
2489     AwtToolkit::GetInstance().MessageLoop(AwtToolkit::SecondaryIdleFunc,
2490                                           AwtToolkit::CommonPeekMessageFunc);
2491 
2492     CATCH_BAD_ALLOC;
2493 }
2494 
2495 /*
2496  * Class:     sun_awt_windows_WToolkit
2497  * Method:    quitSecondaryEventLoop
2498  * Signature: ()V;
2499  */
2500 JNIEXPORT void JNICALL
2501 Java_sun_awt_windows_WToolkit_quitSecondaryEventLoop(
2502     JNIEnv *env,
2503     jclass)
2504 {
2505     TRY;
2506 
2507     AwtToolkit::GetInstance().QuitMessageLoop(AwtToolkit::EXIT_ENCLOSING_LOOP);
2508 
2509     CATCH_BAD_ALLOC;
2510 }
2511 
2512 /*
2513  * Class:     sun_awt_windows_WToolkit
2514  * Method:    makeColorModel
2515  * Signature: ()Ljava/awt/image/ColorModel;
2516  */
2517 JNIEXPORT jobject JNICALL
2518 Java_sun_awt_windows_WToolkit_makeColorModel(JNIEnv *env, jclass cls)
2519 {
2520     TRY;
2521 
2522     return AwtWin32GraphicsDevice::GetColorModel(env, JNI_FALSE,
2523         AwtWin32GraphicsDevice::GetDefaultDeviceIndex());
2524 
2525     CATCH_BAD_ALLOC_RET(NULL);
2526 }
2527 
2528 /*
2529  * Class:     sun_awt_windows_WToolkit
2530  * Method:    getMaximumCursorColors
2531  * Signature: ()I
2532  */
2533 JNIEXPORT jint JNICALL
2534 Java_sun_awt_windows_WToolkit_getMaximumCursorColors(JNIEnv *env, jobject self)
2535 {
2536     TRY;
2537 
2538     HDC hIC = ::CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
2539 
2540     int nColor = 256;
2541     switch (::GetDeviceCaps(hIC, BITSPIXEL) * ::GetDeviceCaps(hIC, PLANES)) {
2542         case 1:         nColor = 2;             break;
2543         case 4:         nColor = 16;            break;
2544         case 8:         nColor = 256;           break;
2545         case 16:        nColor = 65536;         break;
2546         case 24:        nColor = 16777216;      break;
2547     }
2548     ::DeleteDC(hIC);
2549     return nColor;
2550 
2551     CATCH_BAD_ALLOC_RET(0);
2552 }
2553 
2554 /*
2555  * Class:     sun_awt_windows_WToolkit
2556  * Method:    getScreenWidth
2557  * Signature: ()I
2558  */
2559 JNIEXPORT jint JNICALL
2560 Java_sun_awt_windows_WToolkit_getScreenWidth(JNIEnv *env, jobject self)
2561 {
2562     TRY;
2563 
2564     return ::GetSystemMetrics(SM_CXSCREEN);
2565 
2566     CATCH_BAD_ALLOC_RET(0);
2567 }
2568 
2569 /*
2570  * Class:     sun_awt_windows_WToolkit
2571  * Method:    getScreenHeight
2572  * Signature: ()I
2573  */
2574 JNIEXPORT jint JNICALL
2575 Java_sun_awt_windows_WToolkit_getScreenHeight(JNIEnv *env, jobject self)
2576 {
2577     TRY;
2578 
2579     return ::GetSystemMetrics(SM_CYSCREEN);
2580 
2581     CATCH_BAD_ALLOC_RET(0);
2582 }
2583 
2584 /*
2585  * Class:     sun_awt_windows_WToolkit
2586  * Method:    getSreenInsets
2587  * Signature: (I)Ljava/awt/Insets;
2588  */
2589 JNIEXPORT jobject JNICALL
2590 Java_sun_awt_windows_WToolkit_getScreenInsets(JNIEnv *env,
2591                                               jobject self,
2592                                               jint screen)
2593 {
2594     jobject insets = NULL;
2595     RECT rect;
2596 
2597     TRY;
2598 
2599     if (AwtToolkit::GetScreenInsets(screen, &rect)) {
2600         jclass insetsClass = env->FindClass("java/awt/Insets");
2601         DASSERT(insetsClass != NULL);
2602         CHECK_NULL_RETURN(insetsClass, NULL);
2603 
2604         insets = env->NewObject(insetsClass,
2605                 AwtToolkit::insetsMID,
2606                 rect.top,
2607                 rect.left,
2608                 rect.bottom,
2609                 rect.right);
2610     }
2611 
2612     if (safe_ExceptionOccurred(env)) {
2613         return 0;
2614     }
2615     return insets;
2616 
2617     CATCH_BAD_ALLOC_RET(NULL);
2618 }
2619 
2620 
2621 /*
2622  * Class:     sun_awt_windows_WToolkit
2623  * Method:    nativeSync
2624  * Signature: ()V
2625  */
2626 JNIEXPORT void JNICALL
2627 Java_sun_awt_windows_WToolkit_nativeSync(JNIEnv *env, jobject self)
2628 {
2629     TRY;
2630 
2631     // Synchronize both GDI and DDraw
2632     VERIFY(::GdiFlush());
2633 
2634     CATCH_BAD_ALLOC;
2635 }
2636 
2637 /*
2638  * Class:     sun_awt_windows_WToolkit
2639  * Method:    beep
2640  * Signature: ()V
2641  */
2642 JNIEXPORT void JNICALL
2643 Java_sun_awt_windows_WToolkit_beep(JNIEnv *env, jobject self)
2644 {
2645     TRY;
2646 
2647     VERIFY(::MessageBeep(MB_OK));
2648 
2649     CATCH_BAD_ALLOC;
2650 }
2651 
2652 /*
2653  * Class:     sun_awt_windows_WToolkit
2654  * Method:    getLockingKeyStateNative
2655  * Signature: (I)Z
2656  */
2657 JNIEXPORT jboolean JNICALL
2658 Java_sun_awt_windows_WToolkit_getLockingKeyStateNative(JNIEnv *env, jobject self, jint javaKey)
2659 {
2660     TRY;
2661 
2662     UINT windowsKey, modifiers;
2663     AwtComponent::JavaKeyToWindowsKey(javaKey, &windowsKey, &modifiers);
2664 
2665     if (windowsKey == 0) {
2666         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "Keyboard doesn't have requested key");
2667         return JNI_FALSE;
2668     }
2669 
2670     // low order bit in keyboardState indicates whether the key is toggled
2671     BYTE keyboardState[AwtToolkit::KB_STATE_SIZE];
2672     AwtToolkit::GetKeyboardState(keyboardState);
2673     return keyboardState[windowsKey] & 0x01;
2674 
2675     CATCH_BAD_ALLOC_RET(JNI_FALSE);
2676 }
2677 
2678 /*
2679  * Class:     sun_awt_windows_WToolkit
2680  * Method:    setLockingKeyStateNative
2681  * Signature: (IZ)V
2682  */
2683 JNIEXPORT void JNICALL
2684 Java_sun_awt_windows_WToolkit_setLockingKeyStateNative(JNIEnv *env, jobject self, jint javaKey, jboolean state)
2685 {
2686     TRY;
2687 
2688     UINT windowsKey, modifiers;
2689     AwtComponent::JavaKeyToWindowsKey(javaKey, &windowsKey, &modifiers);
2690 
2691     if (windowsKey == 0) {
2692         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "Keyboard doesn't have requested key");
2693         return;
2694     }
2695 
2696     // if the key isn't in the desired state yet, simulate key events to get there
2697     // low order bit in keyboardState indicates whether the key is toggled
2698     BYTE keyboardState[AwtToolkit::KB_STATE_SIZE];
2699     AwtToolkit::GetKeyboardState(keyboardState);
2700     if ((keyboardState[windowsKey] & 0x01) != state) {
2701         ::keybd_event(windowsKey, 0, 0, 0);
2702         ::keybd_event(windowsKey, 0, KEYEVENTF_KEYUP, 0);
2703     }
2704 
2705     CATCH_BAD_ALLOC;
2706 }
2707 
2708 /*
2709  * Class:     sun_awt_windows_WToolkit
2710  * Method:    loadSystemColors
2711  * Signature: ([I)V
2712  */
2713 JNIEXPORT void JNICALL
2714 Java_sun_awt_windows_WToolkit_loadSystemColors(JNIEnv *env, jobject self,
2715                                                jintArray colors)
2716 {
2717     TRY;
2718 
2719     static int indexMap[] = {
2720         COLOR_DESKTOP, /* DESKTOP */
2721         COLOR_ACTIVECAPTION, /* ACTIVE_CAPTION */
2722         COLOR_CAPTIONTEXT, /* ACTIVE_CAPTION_TEXT */
2723         COLOR_ACTIVEBORDER, /* ACTIVE_CAPTION_BORDER */
2724         COLOR_INACTIVECAPTION, /* INACTIVE_CAPTION */
2725         COLOR_INACTIVECAPTIONTEXT, /* INACTIVE_CAPTION_TEXT */
2726         COLOR_INACTIVEBORDER, /* INACTIVE_CAPTION_BORDER */
2727         COLOR_WINDOW, /* WINDOW */
2728         COLOR_WINDOWFRAME, /* WINDOW_BORDER */
2729         COLOR_WINDOWTEXT, /* WINDOW_TEXT */
2730         COLOR_MENU, /* MENU */
2731         COLOR_MENUTEXT, /* MENU_TEXT */
2732         COLOR_WINDOW, /* TEXT */
2733         COLOR_WINDOWTEXT, /* TEXT_TEXT */
2734         COLOR_HIGHLIGHT, /* TEXT_HIGHLIGHT */
2735         COLOR_HIGHLIGHTTEXT, /* TEXT_HIGHLIGHT_TEXT */
2736         COLOR_GRAYTEXT, /* TEXT_INACTIVE_TEXT */
2737         COLOR_3DFACE, /* CONTROL */
2738         COLOR_BTNTEXT, /* CONTROL_TEXT */
2739         COLOR_3DLIGHT, /* CONTROL_HIGHLIGHT */
2740         COLOR_3DHILIGHT, /* CONTROL_LT_HIGHLIGHT */
2741         COLOR_3DSHADOW, /* CONTROL_SHADOW */
2742         COLOR_3DDKSHADOW, /* CONTROL_DK_SHADOW */
2743         COLOR_SCROLLBAR, /* SCROLLBAR */
2744         COLOR_INFOBK, /* INFO */
2745         COLOR_INFOTEXT, /* INFO_TEXT */
2746     };
2747 
2748     jint colorLen = env->GetArrayLength(colors);
2749     jint* colorsPtr = NULL;
2750     try {
2751         colorsPtr = (jint *)env->GetPrimitiveArrayCritical(colors, 0);
2752         for (int i = 0; i < (sizeof indexMap)/(sizeof *indexMap) && i < colorLen; i++) {
2753             colorsPtr[i] = DesktopColor2RGB(indexMap[i]);
2754         }
2755     } catch (...) {
2756         if (colorsPtr != NULL) {
2757             env->ReleasePrimitiveArrayCritical(colors, colorsPtr, 0);
2758         }
2759         throw;
2760     }
2761 
2762     env->ReleasePrimitiveArrayCritical(colors, colorsPtr, 0);
2763 
2764     CATCH_BAD_ALLOC;
2765 }
2766 
2767 extern "C" JNIEXPORT jobject JNICALL DSGetComponent
2768     (JNIEnv* env, void* platformInfo)
2769 {
2770     TRY;
2771 
2772     HWND hWnd = (HWND)platformInfo;
2773     if (!::IsWindow(hWnd))
2774         return NULL;
2775 
2776     AwtComponent* comp = AwtComponent::GetComponent(hWnd);
2777     if (comp == NULL)
2778         return NULL;
2779 
2780     return comp->GetTarget(env);
2781 
2782     CATCH_BAD_ALLOC_RET(NULL);
2783 }
2784 
2785 JNIEXPORT void JNICALL
2786 Java_sun_awt_windows_WToolkit_postDispose(JNIEnv *env, jclass clazz)
2787 {
2788 #ifdef DEBUG
2789     TRY_NO_VERIFY;
2790 
2791     // If this method was called, that means runFinalizersOnExit is turned
2792     // on and the VM is exiting cleanly. We should signal the debug memory
2793     // manager to generate a leaks report.
2794     AwtDebugSupport::GenerateLeaksReport();
2795 
2796     CATCH_BAD_ALLOC;
2797 #endif
2798 }
2799 
2800 /*
2801  * Class:     sun_awt_windows_WToolkit
2802  * Method:    setDynamicLayoutNative
2803  * Signature: (Z)V
2804  */
2805 JNIEXPORT void JNICALL
2806 Java_sun_awt_windows_WToolkit_setDynamicLayoutNative(JNIEnv *env,
2807   jobject self, jboolean dynamic)
2808 {
2809     TRY;
2810 
2811     AwtToolkit::GetInstance().SetDynamicLayout(dynamic);
2812 
2813     CATCH_BAD_ALLOC;
2814 }
2815 
2816 /*
2817  * Class:     sun_awt_windows_WToolkit
2818  * Method:    isDynamicLayoutSupportedNative
2819  * Signature: ()Z
2820  */
2821 JNIEXPORT jboolean JNICALL
2822 Java_sun_awt_windows_WToolkit_isDynamicLayoutSupportedNative(JNIEnv *env,
2823   jobject self)
2824 {
2825     TRY;
2826 
2827     return (jboolean) AwtToolkit::GetInstance().IsDynamicLayoutSupported();
2828 
2829     CATCH_BAD_ALLOC_RET(FALSE);
2830 }
2831 
2832 /*
2833  * Class:     sun_awt_windows_WToolkit
2834  * Method:    printWindowsVersion
2835  * Signature: ()Ljava/lang/String;
2836  */
2837 JNIEXPORT jstring JNICALL
2838 Java_sun_awt_windows_WToolkit_getWindowsVersion(JNIEnv *env, jclass cls)
2839 {
2840     TRY;
2841 
2842     WCHAR szVer[128];
2843 
2844     DWORD version = ::GetVersion();
2845     swprintf(szVer, 128, L"0x%x = %ld", version, version);
2846     int l = lstrlen(szVer);
2847 
2848     if (IS_WIN2000) {
2849         if (IS_WINXP) {
2850             if (IS_WINVISTA) {
2851                 swprintf(szVer + l, 128, L" (Windows Vista)");
2852             } else {
2853                 swprintf(szVer + l, 128, L" (Windows XP)");
2854             }
2855         } else {
2856             swprintf(szVer + l, 128, L" (Windows 2000)");
2857         }
2858     } else {
2859         swprintf(szVer + l, 128, L" (Unknown)");
2860     }
2861 
2862     return JNU_NewStringPlatform(env, szVer);
2863 
2864     CATCH_BAD_ALLOC_RET(NULL);
2865 }
2866 
2867 JNIEXPORT void JNICALL
2868 Java_sun_awt_windows_WToolkit_showTouchKeyboard(JNIEnv *env, jobject self,
2869     jboolean causedByTouchEvent)
2870 {
2871     AwtToolkit& tk = AwtToolkit::GetInstance();
2872     if (!tk.IsWin8OrLater() || !tk.IsTouchKeyboardAutoShowEnabled()) {
2873         return;
2874     }
2875 
2876     if (causedByTouchEvent ||
2877         (tk.IsTouchKeyboardAutoShowSystemEnabled() &&
2878             !tk.IsAnyKeyboardAttached())) {
2879         tk.ShowTouchKeyboard();
2880     }
2881 }
2882 
2883 JNIEXPORT void JNICALL
2884 Java_sun_awt_windows_WToolkit_hideTouchKeyboard(JNIEnv *env, jobject self)
2885 {
2886     AwtToolkit& tk = AwtToolkit::GetInstance();
2887     if (!tk.IsWin8OrLater() || !tk.IsTouchKeyboardAutoShowEnabled()) {
2888         return;
2889     }
2890     tk.HideTouchKeyboard();
2891 }
2892 
2893 JNIEXPORT jboolean JNICALL
2894 Java_sun_awt_windows_WToolkit_syncNativeQueue(JNIEnv *env, jobject self, jlong timeout)
2895 {
2896     AwtToolkit & tk = AwtToolkit::GetInstance();
2897     DWORD eventNumber = tk.eventNumber;
2898     tk.PostMessage(WM_SYNC_WAIT, 0, 0);
2899     ::WaitForSingleObject(tk.m_waitEvent, INFINITE);
2900     DWORD newEventNumber = tk.eventNumber;
2901     return (newEventNumber - eventNumber) > 2;
2902 }
2903 
2904 } /* extern "C" */
2905 
2906 /* Convert a Windows desktop color index into an RGB value. */
2907 COLORREF DesktopColor2RGB(int colorIndex) {
2908     DWORD sysColor = ::GetSysColor(colorIndex);
2909     return ((GetRValue(sysColor)<<16) | (GetGValue(sysColor)<<8) |
2910             (GetBValue(sysColor)) | 0xff000000);
2911 }
2912 
2913 
2914 /*
2915  * Class:     sun_awt_SunToolkit
2916  * Method:    closeSplashScreen
2917  * Signature: ()V
2918  */
2919 extern "C" JNIEXPORT void JNICALL
2920 Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv *env, jclass cls)
2921 {
2922     typedef void (*SplashClose_t)();
2923     HMODULE hSplashDll = GetModuleHandle(_T("splashscreen.dll"));
2924     if (!hSplashDll) {
2925         return; // dll not loaded
2926     }
2927     SplashClose_t splashClose = (SplashClose_t)GetProcAddress(hSplashDll,
2928         "SplashClose");
2929     if (splashClose) {
2930         splashClose();
2931     }
2932 }
2933 
2934 /*
2935  * accessible from awt_Component
2936  */
2937 BOOL AwtToolkit::areExtraMouseButtonsEnabled() {
2938     return m_areExtraMouseButtonsEnabled;
2939 }
2940 
2941 /*
2942  * Class:     sun_awt_windows_WToolkit
2943  * Method:    setExtraMouseButtonsEnabledNative
2944  * Signature: (Z)V
2945  */
2946 extern "C" JNIEXPORT void JNICALL Java_sun_awt_windows_WToolkit_setExtraMouseButtonsEnabledNative
2947 (JNIEnv *env, jclass self, jboolean enable){
2948     TRY;
2949     AwtToolkit::GetInstance().setExtraMouseButtonsEnabled(enable);
2950     CATCH_BAD_ALLOC;
2951 }
2952 
2953 void AwtToolkit::setExtraMouseButtonsEnabled(BOOL enable) {
2954     m_areExtraMouseButtonsEnabled = enable;
2955 }
2956 
2957 JNIEXPORT jint JNICALL Java_sun_awt_windows_WToolkit_getNumberOfButtonsImpl
2958 (JNIEnv *, jobject self) {
2959     return AwtToolkit::GetNumberOfButtons();
2960 }
2961 
2962 UINT AwtToolkit::GetNumberOfButtons() {
2963     return MOUSE_BUTTONS_WINDOWS_SUPPORTED;
2964 }
2965 
2966 bool AwtToolkit::IsWin8OrLater() {
2967     return m_isWin8OrLater;
2968 }
2969 
2970 bool AwtToolkit::IsTouchKeyboardAutoShowEnabled() {
2971     return m_touchKbrdAutoShowIsEnabled;
2972 }
2973 
2974 bool AwtToolkit::IsAnyKeyboardAttached() {
2975     UINT numDevs = 0;
2976     UINT numDevsRet = 0;
2977     const UINT devListTypeSize = sizeof(RAWINPUTDEVICELIST);
2978     if ((::GetRawInputDeviceList(NULL, &numDevs, devListTypeSize) != 0) ||
2979         (numDevs == 0)) {
2980         return false;
2981     }
2982 
2983     RAWINPUTDEVICELIST* pDevList = new RAWINPUTDEVICELIST[numDevs];
2984     while (((numDevsRet = ::GetRawInputDeviceList(pDevList, &numDevs,
2985             devListTypeSize)) == (UINT)-1) &&
2986         (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
2987         if (pDevList != NULL) {
2988             delete[] pDevList;
2989         }
2990         pDevList = new RAWINPUTDEVICELIST[numDevs];
2991     }
2992 
2993     bool keyboardIsAttached = false;
2994     if (numDevsRet != (UINT)-1) {
2995         for (UINT i = 0; i < numDevsRet; i++) {
2996             if (pDevList[i].dwType == RIM_TYPEKEYBOARD) {
2997                 keyboardIsAttached = true;
2998                 break;
2999             }
3000         }
3001     }
3002 
3003     if (pDevList != NULL) {
3004         delete[] pDevList;
3005     }
3006     return keyboardIsAttached;
3007 }
3008 
3009 bool AwtToolkit::IsTouchKeyboardAutoShowSystemEnabled() {
3010     const TCHAR tabTipKeyName[] = _T("SOFTWARE\\Microsoft\\TabletTip\\1.7");
3011     HKEY hTabTipKey = NULL;
3012     if (::RegOpenKeyEx(HKEY_CURRENT_USER, tabTipKeyName, 0, KEY_READ,
3013             &hTabTipKey) != ERROR_SUCCESS) {
3014         return false;
3015     }
3016 
3017     const TCHAR enableAutoInvokeValName[] = _T("EnableDesktopModeAutoInvoke");
3018     DWORD keyValType = 0;
3019     bool autoShowIsEnabled = false;
3020     if (::RegQueryValueEx(hTabTipKey, enableAutoInvokeValName, NULL,
3021             &keyValType, NULL, NULL) == ERROR_SUCCESS) {
3022         if (keyValType == REG_DWORD) {
3023             DWORD enableAutoInvokeVal = 0;
3024             DWORD bytesCopied = sizeof(DWORD);
3025             if (::RegQueryValueEx(hTabTipKey, enableAutoInvokeValName, NULL,
3026                     NULL, (LPBYTE)(DWORD*)&enableAutoInvokeVal,
3027                     &bytesCopied) == ERROR_SUCCESS) {
3028                 autoShowIsEnabled = (enableAutoInvokeVal == 0 ? false : true);
3029             }
3030         }
3031     }
3032 
3033     if (hTabTipKey != NULL) {
3034         ::RegCloseKey(hTabTipKey);
3035     }
3036     return autoShowIsEnabled;
3037 }
3038 
3039 void AwtToolkit::ShowTouchKeyboard() {
3040     if (m_isWin8OrLater && m_touchKbrdAutoShowIsEnabled &&
3041         (m_touchKbrdExeFilePath != NULL)) {
3042         HINSTANCE retVal = ::ShellExecute(NULL, _T("open"),
3043             m_touchKbrdExeFilePath, NULL, NULL, SW_SHOW);
3044         if ((int)retVal <= 32) {
3045             DTRACE_PRINTLN1("AwtToolkit::ShowTouchKeyboard: Failed"
3046                 ", retVal='%d'", (int)retVal);
3047         }
3048     }
3049 }
3050 
3051 void AwtToolkit::HideTouchKeyboard() {
3052     if (m_isWin8OrLater && m_touchKbrdAutoShowIsEnabled) {
3053         HWND hwnd = GetTouchKeyboardWindow();
3054         if (hwnd != NULL) {
3055             ::PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
3056         }
3057     }
3058 }
3059 
3060 BOOL AwtToolkit::TIRegisterTouchWindow(HWND hWnd, ULONG ulFlags) {
3061     if (m_pRegisterTouchWindow == NULL) {
3062         return FALSE;
3063     }
3064     return m_pRegisterTouchWindow(hWnd, ulFlags);
3065 }
3066 
3067 BOOL AwtToolkit::TIGetTouchInputInfo(HTOUCHINPUT hTouchInput,
3068     UINT cInputs, PTOUCHINPUT pInputs, int cbSize) {
3069     if (m_pGetTouchInputInfo == NULL) {
3070         return FALSE;
3071     }
3072     return m_pGetTouchInputInfo(hTouchInput, cInputs, pInputs, cbSize);
3073 }
3074 
3075 BOOL AwtToolkit::TICloseTouchInputHandle(HTOUCHINPUT hTouchInput) {
3076     if (m_pCloseTouchInputHandle == NULL) {
3077         return FALSE;
3078     }
3079     return m_pCloseTouchInputHandle(hTouchInput);
3080 }