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