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