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