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