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