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