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