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