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