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