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