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