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