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