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