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