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