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