1 /*
2 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #define _JNI_IMPLEMENTATION_
27
28 #include "awt.h"
29 #include <signal.h>
30 #include <windowsx.h>
31 #include <process.h>
32 #include <shellapi.h>
33 #include <shlwapi.h>
34
35 #include "awt_DrawingSurface.h"
36 #include "awt_AWTEvent.h"
37 #include "awt_Component.h"
38 #include "awt_Canvas.h"
39 #include "awt_Clipboard.h"
40 #include "awt_Frame.h"
41 #include "awt_Dialog.h"
42 #include "awt_Font.h"
43 #include "awt_Cursor.h"
44 #include "awt_InputEvent.h"
45 #include "awt_KeyEvent.h"
46 #include "awt_List.h"
47 #include "awt_Palette.h"
48 #include "awt_PopupMenu.h"
49 #include "awt_Toolkit.h"
50 #include "awt_DesktopProperties.h"
51 #include "awt_FileDialog.h"
52 #include "CmdIDList.h"
53 #include "awt_new.h"
54 #include "debug_trace.h"
55 #include "debug_mem.h"
56
57 #include "ComCtl32Util.h"
58 #include "DllUtil.h"
59
60 #include "D3DPipelineManager.h"
61
62 #include <awt_DnDDT.h>
63 #include <awt_DnDDS.h>
64
65 #include <java_awt_Toolkit.h>
66 #include <java_awt_event_InputMethodEvent.h>
67
68 extern void initScreens(JNIEnv *env);
69 extern "C" void awt_dnd_initialize();
70 extern "C" void awt_dnd_uninitialize();
71 extern "C" void awt_clipboard_uninitialize(JNIEnv *env);
72 extern "C" BOOL g_bUserHasChangedInputLang;
73
74 extern CriticalSection windowMoveLock;
75 extern BOOL windowMoveLockHeld;
76
77 // Needed by JAWT: see awt_DrawingSurface.cpp.
78 extern jclass jawtVImgClass;
79 extern jclass jawtVSMgrClass;
80 extern jclass jawtComponentClass;
81 extern jfieldID jawtPDataID;
82 extern jfieldID jawtSDataID;
83 extern jfieldID jawtSMgrID;
84
85 jobject reasonUnspecified;
86 jobject reasonConsole;
87 jobject reasonRemote;
88 jobject reasonLock;
89
90 extern jobject GetStaticObject(JNIEnv *env, jclass wfClass, const char *fieldName,
91 const char *signature);
92
93 extern BOOL isSuddenTerminationEnabled;
94
95 extern void DWMResetCompositionEnabled();
96
97 /************************************************************************
98 * Utilities
99 */
100
101 /* Initialize the Java VM instance variable when the library is
102 first loaded */
103 JavaVM *jvm = NULL;
104
105 JNIEXPORT jint JNICALL
DEF_JNI_OnLoad(JavaVM * vm,void * reserved)106 DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
107 {
108 TRY;
109
110 jvm = vm;
111 return JNI_VERSION_1_2;
112
113 CATCH_BAD_ALLOC_RET(0);
114 }
115
AWTIsHeadless()116 extern "C" JNIEXPORT jboolean JNICALL AWTIsHeadless() {
117 static JNIEnv *env = NULL;
118 static jboolean isHeadless;
119 jmethodID headlessFn;
120 jclass graphicsEnvClass;
121
122 if (env == NULL) {
123 env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
124 graphicsEnvClass = env->FindClass(
125 "java/awt/GraphicsEnvironment");
126 if (graphicsEnvClass == NULL) {
127 return JNI_TRUE;
128 }
129 headlessFn = env->GetStaticMethodID(
130 graphicsEnvClass, "isHeadless", "()Z");
131 if (headlessFn == NULL) {
132 return JNI_TRUE;
133 }
134 isHeadless = env->CallStaticBooleanMethod(graphicsEnvClass,
135 headlessFn);
136 }
137 return isHeadless;
138 }
139
140 #define IDT_AWT_MOUSECHECK 0x101
141
142 static LPCTSTR szAwtToolkitClassName = TEXT("SunAwtToolkit");
143
144 static const int MOUSE_BUTTONS_WINDOWS_SUPPORTED = 5; //three standard buttons + XBUTTON1 + XBUTTON2.
145
GetMouseKeyState()146 UINT AwtToolkit::GetMouseKeyState()
147 {
148 static BOOL mbSwapped = ::GetSystemMetrics(SM_SWAPBUTTON);
149 UINT mouseKeyState = 0;
150
151 if (HIBYTE(::GetKeyState(VK_CONTROL)))
152 mouseKeyState |= MK_CONTROL;
153 if (HIBYTE(::GetKeyState(VK_SHIFT)))
154 mouseKeyState |= MK_SHIFT;
155 if (HIBYTE(::GetKeyState(VK_LBUTTON)))
156 mouseKeyState |= (mbSwapped ? MK_RBUTTON : MK_LBUTTON);
157 if (HIBYTE(::GetKeyState(VK_RBUTTON)))
158 mouseKeyState |= (mbSwapped ? MK_LBUTTON : MK_RBUTTON);
159 if (HIBYTE(::GetKeyState(VK_MBUTTON)))
160 mouseKeyState |= MK_MBUTTON;
161 return mouseKeyState;
162 }
163
164 //
165 // Normal ::GetKeyboardState call only works if current thread has
166 // a message pump, so provide a way for other threads to get
167 // the keyboard state
168 //
GetKeyboardState(PBYTE keyboardState)169 void AwtToolkit::GetKeyboardState(PBYTE keyboardState)
170 {
171 CriticalSection::Lock l(AwtToolkit::GetInstance().m_lockKB);
172 DASSERT(!IsBadWritePtr(keyboardState, KB_STATE_SIZE));
173 memcpy(keyboardState, AwtToolkit::GetInstance().m_lastKeyboardState,
174 KB_STATE_SIZE);
175 }
176
SetBusy(BOOL busy)177 void AwtToolkit::SetBusy(BOOL busy) {
178
179 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
180
181 static jclass awtAutoShutdownClass = NULL;
182 static jmethodID notifyBusyMethodID = NULL;
183 static jmethodID notifyFreeMethodID = NULL;
184
185 if (awtAutoShutdownClass == NULL) {
186 jclass awtAutoShutdownClassLocal = env->FindClass("sun/awt/AWTAutoShutdown");
187 DASSERT(awtAutoShutdownClassLocal != NULL);
188 if (!awtAutoShutdownClassLocal) throw std::bad_alloc();
189
190 awtAutoShutdownClass = (jclass)env->NewGlobalRef(awtAutoShutdownClassLocal);
191 env->DeleteLocalRef(awtAutoShutdownClassLocal);
192 if (!awtAutoShutdownClass) throw std::bad_alloc();
193
194 notifyBusyMethodID = env->GetStaticMethodID(awtAutoShutdownClass,
195 "notifyToolkitThreadBusy", "()V");
196 DASSERT(notifyBusyMethodID != NULL);
197 if (!notifyBusyMethodID) throw std::bad_alloc();
198
199 notifyFreeMethodID = env->GetStaticMethodID(awtAutoShutdownClass,
200 "notifyToolkitThreadFree", "()V");
201 DASSERT(notifyFreeMethodID != NULL);
202 if (!notifyFreeMethodID) throw std::bad_alloc();
203 } /* awtAutoShutdownClass == NULL*/
204
205 if (busy) {
206 env->CallStaticVoidMethod(awtAutoShutdownClass,
207 notifyBusyMethodID);
208 } else {
209 env->CallStaticVoidMethod(awtAutoShutdownClass,
210 notifyFreeMethodID);
211 }
212
213 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
214 env->ExceptionDescribe();
215 env->ExceptionClear();
216 }
217 }
218
activateKeyboardLayout(HKL hkl)219 BOOL AwtToolkit::activateKeyboardLayout(HKL hkl) {
220 // This call should succeed in case of one of the following:
221 // 1. Win 9x
222 // 2. NT with that HKL already loaded
223 HKL prev = ::ActivateKeyboardLayout(hkl, 0);
224
225 // If the above call fails, try loading the layout in case of NT
226 if (!prev) {
227 // create input locale string, e.g., "00000409", from hkl.
228 TCHAR inputLocale[9];
229 TCHAR buf[9];
230 _tcscpy_s(inputLocale, 9, TEXT("00000000"));
231
232 // 64-bit: ::LoadKeyboardLayout() is such a weird API - a string of
233 // the hex value you want?! Here we're converting our HKL value to
234 // a string. Hopefully there is no 64-bit trouble.
235 _i64tot(reinterpret_cast<INT_PTR>(hkl), buf, 16);
236 size_t len = _tcslen(buf);
237 memcpy(&inputLocale[8-len], buf, len);
238
239 // load and activate the keyboard layout
240 hkl = ::LoadKeyboardLayout(inputLocale, 0);
241 if (hkl != 0) {
242 prev = ::ActivateKeyboardLayout(hkl, 0);
243 }
244 }
245
246 return (prev != 0);
247 }
248
249 /************************************************************************
250 * Exported functions
251 */
252
DllMain(HANDLE hInstance,DWORD ul_reason_for_call,LPVOID)253 extern "C" BOOL APIENTRY DllMain(HANDLE hInstance, DWORD ul_reason_for_call,
254 LPVOID)
255 {
256 // Don't use the TRY and CATCH_BAD_ALLOC_RET macros if we're detaching
257 // the library. Doing so causes awt.dll to call back into the VM during
258 // shutdown. This crashes the HotSpot VM.
259 switch (ul_reason_for_call) {
260 case DLL_PROCESS_ATTACH:
261 TRY;
262 AwtToolkit::GetInstance().SetModuleHandle((HMODULE)hInstance);
263 CATCH_BAD_ALLOC_RET(FALSE);
264 break;
265 case DLL_PROCESS_DETACH:
266 #ifdef DEBUG
267 DTrace_DisableMutex();
268 DMem_DisableMutex();
269 #endif DEBUG
270 break;
271 }
272 return TRUE;
273 }
274
275 /************************************************************************
276 * AwtToolkit fields
277 */
278
279 AwtToolkit AwtToolkit::theInstance;
280
281 /* ids for WToolkit fields accessed from native code */
282 jmethodID AwtToolkit::windowsSettingChangeMID;
283 jmethodID AwtToolkit::displayChangeMID;
284
285 jmethodID AwtToolkit::userSessionMID;
286 jmethodID AwtToolkit::systemSleepMID;
287 /* ids for Toolkit methods */
288 jmethodID AwtToolkit::getDefaultToolkitMID;
289 jmethodID AwtToolkit::getFontMetricsMID;
290 jmethodID AwtToolkit::insetsMID;
291
292 /************************************************************************
293 * AwtToolkit methods
294 */
295
AwtToolkit()296 AwtToolkit::AwtToolkit() {
297 m_localPump = FALSE;
298 m_mainThreadId = 0;
299 m_toolkitHWnd = NULL;
300 m_inputMethodHWnd = NULL;
301 m_verbose = FALSE;
302 m_isActive = TRUE;
303 m_isDisposed = FALSE;
304
305 m_vmSignalled = FALSE;
306
307 m_isDynamicLayoutSet = FALSE;
308 m_areExtraMouseButtonsEnabled = TRUE;
309
310 m_isWin8OrLater = FALSE;
311 m_touchKbrdAutoShowIsEnabled = FALSE;
312 m_touchKbrdExeFilePath = NULL;
313 m_pRegisterTouchWindow = NULL;
314 m_pGetTouchInputInfo = NULL;
315 m_pCloseTouchInputHandle = NULL;
316
317 m_verifyComponents = FALSE;
318 m_breakOnError = FALSE;
319
320 m_breakMessageLoop = FALSE;
321 m_messageLoopResult = 0;
322
323 m_lastMouseOver = NULL;
324 m_mouseDown = FALSE;
325
326 m_hGetMessageHook = 0;
327 m_hMouseLLHook = 0;
328 m_lastWindowUnderMouse = NULL;
329 m_timer = 0;
330
331 m_cmdIDs = new AwtCmdIDList();
332 m_pModalDialog = NULL;
333 m_peer = NULL;
334 m_dllHandle = NULL;
335
336 m_displayChanged = FALSE;
337 m_embedderProcessID = 0;
338
339 // XXX: keyboard mapping should really be moved out of AwtComponent
340 AwtComponent::InitDynamicKeyMapTable();
341
342 // initialize kb state array
343 ::GetKeyboardState(m_lastKeyboardState);
344
345 m_waitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
346 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_CHANGECBCHAIN: {
1071 AwtClipboard::WmChangeCbChain(wParam, lParam);
1072 return 0;
1073 }
1074 case WM_DRAWCLIPBOARD: {
1075 AwtClipboard::WmDrawClipboard((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), wParam, lParam);
1076 return 0;
1077 }
1078 case WM_AWT_LIST_SETMULTISELECT: {
1079 jobject peerObject = (jobject)wParam;
1080 AwtList* list = (AwtList *)JNI_GET_PDATA(peerObject);
1081 DASSERT( !IsBadReadPtr(list, sizeof(AwtObject)));
1082 list->SetMultiSelect(static_cast<BOOL>(lParam));
1083 return 0;
1084 }
1085
1086 // Special awt message to call Imm APIs.
1087 // ImmXXXX() API must be used in the main thread.
1088 // In other thread these APIs does not work correctly even if
1089 // it returs with no error. (This restriction is not documented)
1090 // So we must use thse messages to call these APIs in main thread.
1091 case WM_AWT_CREATECONTEXT: {
1092 AwtToolkit& tk = AwtToolkit::GetInstance();
1093 tk.m_inputMethodData = reinterpret_cast<LRESULT>(
1094 reinterpret_cast<void*>(ImmCreateContext()));
1095 ::SetEvent(tk.m_inputMethodWaitEvent);
1096 return tk.m_inputMethodData;
1097 }
1098 case WM_AWT_DESTROYCONTEXT: {
1099 ImmDestroyContext((HIMC)wParam);
1100 AwtToolkit& tk = AwtToolkit::GetInstance();
1101 tk.m_inputMethodData = 0;
1102 ::SetEvent(tk.m_inputMethodWaitEvent);
1103 return 0;
1104 }
1105 case WM_AWT_ASSOCIATECONTEXT: {
1106 EnableNativeIMEStruct *data = (EnableNativeIMEStruct*)wParam;
1107
1108 jobject peer = data->peer;
1109 jobject self = data->self;
1110 jint context = data->context;
1111 jboolean useNativeCompWindow = data->useNativeCompWindow;
1112
1113 AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
1114 if (comp != NULL)
1115 {
1116 comp->SetInputMethod(self, useNativeCompWindow);
1117 comp->ImmAssociateContext((HIMC)((intptr_t)context));
1118 }
1119
1120 if (peer != NULL) {
1121 env->DeleteGlobalRef(peer);
1122 }
1123 if (self != NULL) {
1124 env->DeleteGlobalRef(self);
1125 }
1126
1127 delete data;
1128 AwtToolkit& tk = AwtToolkit::GetInstance();
1129 tk.m_inputMethodData = 0;
1130 ::SetEvent(tk.m_inputMethodWaitEvent);
1131 return 0;
1132 }
1133 case WM_AWT_GET_DEFAULT_IME_HANDLER: {
1134 LRESULT ret = (LRESULT)FALSE;
1135 jobject peer = (jobject)wParam;
1136 AwtToolkit& tk = AwtToolkit::GetInstance();
1137
1138 AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
1139 if (comp != NULL) {
1140 HWND defaultIMEHandler = ImmGetDefaultIMEWnd(comp->GetHWnd());
1141 if (defaultIMEHandler != NULL) {
1142 tk.SetInputMethodWindow(defaultIMEHandler);
1143 ret = (LRESULT)TRUE;
1144 }
1145 }
1146
1147 if (peer != NULL) {
1148 env->DeleteGlobalRef(peer);
1149 }
1150 tk.m_inputMethodData = ret;
1151 ::SetEvent(tk.m_inputMethodWaitEvent);
1152 return ret;
1153 }
1154 case WM_AWT_HANDLE_NATIVE_IME_EVENT: {
1155 jobject peer = (jobject)wParam;
1156 AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(peer);
1157 MSG* msg = (MSG*)lParam;
1158
1159 long modifiers = comp->GetJavaModifiers();
1160 if ((comp != NULL) && (msg->message==WM_CHAR || msg->message==WM_SYSCHAR)) {
1161 WCHAR unicodeChar = (WCHAR)msg->wParam;
1162 comp->SendKeyEvent(java_awt_event_KeyEvent_KEY_TYPED,
1163 0, //to be fixed nowMillis(),
1164 java_awt_event_KeyEvent_CHAR_UNDEFINED,
1165 unicodeChar,
1166 modifiers,
1167 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
1168 msg);
1169 } else if (comp != NULL) {
1170 MSG* pCopiedMsg = new MSG;
1171 *pCopiedMsg = *msg;
1172 comp->SendMessage(WM_AWT_HANDLE_EVENT, (WPARAM) FALSE,
1173 (LPARAM) pCopiedMsg);
1174 }
1175
1176 if (peer != NULL) {
1177 env->DeleteGlobalRef(peer);
1178 }
1179 return 0;
1180 }
1181 case WM_AWT_ENDCOMPOSITION: {
1182 /*right now we just cancel the composition string
1183 may need to commit it in the furture
1184 Changed to commit it according to the flag 10/29/98*/
1185 ImmNotifyIME((HIMC)wParam, NI_COMPOSITIONSTR,
1186 (lParam ? CPS_COMPLETE : CPS_CANCEL), 0);
1187 AwtToolkit& tk = AwtToolkit::GetInstance();
1188 tk.m_inputMethodData = 0;
1189 ::SetEvent(tk.m_inputMethodWaitEvent);
1190 return 0;
1191 }
1192 case WM_AWT_SETCONVERSIONSTATUS: {
1193 DWORD cmode;
1194 DWORD smode;
1195 ImmGetConversionStatus((HIMC)wParam, (LPDWORD)&cmode, (LPDWORD)&smode);
1196 ImmSetConversionStatus((HIMC)wParam, (DWORD)LOWORD(lParam), smode);
1197 AwtToolkit& tk = AwtToolkit::GetInstance();
1198 tk.m_inputMethodData = 0;
1199 ::SetEvent(tk.m_inputMethodWaitEvent);
1200 return 0;
1201 }
1202 case WM_AWT_GETCONVERSIONSTATUS: {
1203 DWORD cmode;
1204 DWORD smode;
1205 ImmGetConversionStatus((HIMC)wParam, (LPDWORD)&cmode, (LPDWORD)&smode);
1206 AwtToolkit& tk = AwtToolkit::GetInstance();
1207 tk.m_inputMethodData = cmode;
1208 ::SetEvent(tk.m_inputMethodWaitEvent);
1209 return cmode;
1210 }
1211 case WM_AWT_ACTIVATEKEYBOARDLAYOUT: {
1212 if (wParam && g_bUserHasChangedInputLang) {
1213 // Input language has been changed since the last WInputMethod.getNativeLocale()
1214 // call. So let's honor the user's selection.
1215 // Note: we need to check this flag inside the toolkit thread to synchronize access
1216 // to the flag.
1217 return FALSE;
1218 }
1219
1220 if (lParam == (LPARAM)::GetKeyboardLayout(0)) {
1221 // already active
1222 return FALSE;
1223 }
1224
1225 // Since ActivateKeyboardLayout does not post WM_INPUTLANGCHANGEREQUEST,
1226 // we explicitly need to do the same thing here.
1227 static BYTE keyboardState[AwtToolkit::KB_STATE_SIZE];
1228 AwtToolkit::GetKeyboardState(keyboardState);
1229 WORD ignored;
1230 ::ToAscii(VK_SPACE, ::MapVirtualKey(VK_SPACE, 0),
1231 keyboardState, &ignored, 0);
1232
1233 return (LRESULT)activateKeyboardLayout((HKL)lParam);
1234 }
1235 case WM_AWT_OPENCANDIDATEWINDOW: {
1236 jobject peerObject = (jobject)wParam;
1237 AwtComponent* p = (AwtComponent*)JNI_GET_PDATA(peerObject);
1238 DASSERT( !IsBadReadPtr(p, sizeof(AwtObject)));
1239 // fix for 4805862: use GET_X_LPARAM and GET_Y_LPARAM macros
1240 // instead of LOWORD and HIWORD
1241 p->OpenCandidateWindow(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1242 env->DeleteGlobalRef(peerObject);
1243 AwtToolkit& tk = AwtToolkit::GetInstance();
1244 tk.m_inputMethodData = 0;
1245 ::SetEvent(tk.m_inputMethodWaitEvent);
1246 return 0;
1247 }
1248
1249 /*
1250 * send this message via ::SendMessage() and the MPT will acquire the
1251 * HANDLE synchronized with the sender's thread. The HANDLE must be
1252 * signalled or deadlock may occur between the MPT and the caller.
1253 */
1254
1255 case WM_AWT_WAIT_FOR_SINGLE_OBJECT: {
1256 return ::WaitForSingleObject((HANDLE)lParam, INFINITE);
1257 }
1258 case WM_AWT_INVOKE_METHOD: {
1259 return (LRESULT)(*(void*(*)(void*))wParam)((void *)lParam);
1260 }
1261 case WM_AWT_INVOKE_VOID_METHOD: {
1262 return (LRESULT)(*(void*(*)(void))wParam)();
1263 }
1264
1265 case WM_AWT_SETOPENSTATUS: {
1266 ImmSetOpenStatus((HIMC)wParam, (BOOL)lParam);
1267 AwtToolkit& tk = AwtToolkit::GetInstance();
1268 tk.m_inputMethodData = 0;
1269 ::SetEvent(tk.m_inputMethodWaitEvent);
1270 return 0;
1271 }
1272 case WM_AWT_GETOPENSTATUS: {
1273 AwtToolkit& tk = AwtToolkit::GetInstance();
1274 tk.m_inputMethodData = (DWORD)ImmGetOpenStatus((HIMC)wParam);
1275 ::SetEvent(tk.m_inputMethodWaitEvent);
1276 return tk.m_inputMethodData;
1277 }
1278 case WM_DISPLAYCHANGE: {
1279 // Reinitialize screens
1280 initScreens(env);
1281
1282 // Notify Java side - call WToolkit.displayChanged()
1283 jclass clazz = env->FindClass("sun/awt/windows/WToolkit");
1284 DASSERT(clazz != NULL);
1285 if (!clazz) throw std::bad_alloc();
1286 env->CallStaticVoidMethod(clazz, AwtToolkit::displayChangeMID);
1287
1288 GetInstance().m_displayChanged = TRUE;
1289
1290 ::PostMessage(HWND_BROADCAST, WM_PALETTEISCHANGING, NULL, NULL);
1291 break;
1292 }
1293 case WM_AWT_SETCURSOR: {
1294 ::SetCursor((HCURSOR)wParam);
1295 return TRUE;
1296 }
1297 /* Session management */
1298 case WM_QUERYENDSESSION: {
1299 /* Shut down cleanly */
1300 if (!isSuddenTerminationEnabled) {
1301 return FALSE;
1302 }
1303 if (JVM_RaiseSignal(SIGTERM)) {
1304 AwtToolkit::GetInstance().m_vmSignalled = TRUE;
1305 }
1306 return TRUE;
1307 }
1308 case WM_ENDSESSION: {
1309 // Keep pumping messages until the shutdown sequence halts the VM,
1310 // or we exit the MessageLoop because of a WM_QUIT message
1311 AwtToolkit& tk = AwtToolkit::GetInstance();
1312
1313 // if WM_QUERYENDSESSION hasn't successfully raised SIGTERM
1314 // we ignore the ENDSESSION message
1315 if (!tk.m_vmSignalled) {
1316 return 0;
1317 }
1318 tk.MessageLoop(AwtToolkit::PrimaryIdleFunc,
1319 AwtToolkit::CommonPeekMessageFunc);
1320
1321 // Dispose here instead of in eventLoop so that we don't have
1322 // to return from the WM_ENDSESSION handler.
1323 tk.Dispose();
1324
1325 // Never return. The VM will halt the process.
1326 hang_if_shutdown();
1327
1328 // Should never get here.
1329 DASSERT(FALSE);
1330 break;
1331 }
1332 #ifndef WM_WTSSESSION_CHANGE
1333 #define WM_WTSSESSION_CHANGE 0x02B1
1334 #define WTS_CONSOLE_CONNECT 0x1
1335 #define WTS_CONSOLE_DISCONNECT 0x2
1336 #define WTS_REMOTE_CONNECT 0x3
1337 #define WTS_REMOTE_DISCONNECT 0x4
1338 #define WTS_SESSION_LOGON 0x5
1339 #define WTS_SESSION_LOGOFF 0x6
1340 #define WTS_SESSION_LOCK 0x7
1341 #define WTS_SESSION_UNLOCK 0x8
1342 #define WTS_SESSION_REMOTE_CONTROL 0x9
1343 #endif // WM_WTSSESSION_CHANGE
1344 case WM_WTSSESSION_CHANGE: {
1345 jclass clzz = env->FindClass("sun/awt/windows/WDesktopPeer");
1346 DASSERT(clzz != NULL);
1347 if (!clzz) throw std::bad_alloc();
1348
1349 if (wParam == WTS_CONSOLE_CONNECT
1350 || wParam == WTS_CONSOLE_DISCONNECT
1351 || wParam == WTS_REMOTE_CONNECT
1352 || wParam == WTS_REMOTE_DISCONNECT
1353 || wParam == WTS_SESSION_UNLOCK
1354 || wParam == WTS_SESSION_LOCK) {
1355
1356 BOOL activate = wParam == WTS_CONSOLE_CONNECT
1357 || wParam == WTS_REMOTE_CONNECT
1358 || wParam == WTS_SESSION_UNLOCK;
1359 jobject reason = reasonUnspecified;
1360
1361 switch (wParam) {
1362 case WTS_CONSOLE_CONNECT:
1363 case WTS_CONSOLE_DISCONNECT:
1364 reason = reasonConsole;
1365 break;
1366 case WTS_REMOTE_CONNECT:
1367 case WTS_REMOTE_DISCONNECT:
1368 reason = reasonRemote;
1369 break;
1370 case WTS_SESSION_UNLOCK:
1371 case WTS_SESSION_LOCK:
1372 reason = reasonLock;
1373 }
1374
1375 env->CallStaticVoidMethod(clzz, AwtToolkit::userSessionMID,
1376 activate
1377 ? JNI_TRUE
1378 : JNI_FALSE, reason);
1379 }
1380 break;
1381 }
1382 case WM_POWERBROADCAST: {
1383 jclass clzz = env->FindClass("sun/awt/windows/WDesktopPeer");
1384 DASSERT(clzz != NULL);
1385 if (!clzz) throw std::bad_alloc();
1386
1387 if (wParam == PBT_APMSUSPEND || wParam == PBT_APMRESUMEAUTOMATIC) {
1388 env->CallStaticVoidMethod(clzz, AwtToolkit::systemSleepMID,
1389 wParam == PBT_APMRESUMEAUTOMATIC
1390 ? JNI_TRUE
1391 : JNI_FALSE);
1392 }
1393 break;
1394 }
1395 case WM_SYNC_WAIT:
1396 SetEvent(AwtToolkit::GetInstance().m_waitEvent);
1397 break;
1398 }
1399
1400 return DefWindowProc(hWnd, message, wParam, lParam);
1401
1402 CATCH_BAD_ALLOC_RET(0);
1403 }
1404
GetMessageFilter(int code,WPARAM wParam,LPARAM lParam)1405 LRESULT CALLBACK AwtToolkit::GetMessageFilter(int code,
1406 WPARAM wParam, LPARAM lParam)
1407 {
1408 TRY;
1409
1410 if (code >= 0 && wParam == PM_REMOVE && lParam != 0) {
1411 if (AwtToolkit::GetInstance().PreProcessMsg(*(MSG*)lParam) !=
1412 mrPassAlong) {
1413 /* PreProcessMsg() wants us to eat it */
1414 ((MSG*)lParam)->message = WM_NULL;
1415 }
1416 }
1417 return ::CallNextHookEx(AwtToolkit::GetInstance().m_hGetMessageHook, code,
1418 wParam, lParam);
1419
1420 CATCH_BAD_ALLOC_RET(0);
1421 }
1422
InstallMouseLowLevelHook()1423 void AwtToolkit::InstallMouseLowLevelHook()
1424 {
1425 // We need the low-level hook since we need to process mouse move
1426 // messages outside of our windows.
1427 m_hMouseLLHook = ::SetWindowsHookEx(WH_MOUSE_LL,
1428 (HOOKPROC)MouseLowLevelHook,
1429 GetModuleHandle(), NULL);
1430
1431 // Reset the old value
1432 m_lastWindowUnderMouse = NULL;
1433 }
1434
UninstallMouseLowLevelHook()1435 void AwtToolkit::UninstallMouseLowLevelHook()
1436 {
1437 if (m_hMouseLLHook != 0) {
1438 ::UnhookWindowsHookEx(m_hMouseLLHook);
1439 m_hMouseLLHook = 0;
1440 }
1441 }
1442
MouseLowLevelHook(int code,WPARAM wParam,LPARAM lParam)1443 LRESULT CALLBACK AwtToolkit::MouseLowLevelHook(int code,
1444 WPARAM wParam, LPARAM lParam)
1445 {
1446 TRY;
1447
1448 if (code >= 0 && wParam == WM_MOUSEMOVE) {
1449 POINT pt = ((MSLLHOOKSTRUCT*)lParam)->pt;
1450
1451 // We can't use GA_ROOTOWNER since in this case we'll go up to
1452 // the root Java toplevel, not the actual owned toplevel.
1453 HWND hwnd = ::GetAncestor(::WindowFromPoint(pt), GA_ROOT);
1454
1455 AwtToolkit& tk = AwtToolkit::GetInstance();
1456
1457 if (tk.m_lastWindowUnderMouse != hwnd) {
1458 AwtWindow *fw = NULL, *tw = NULL;
1459
1460 if (tk.m_lastWindowUnderMouse) {
1461 fw = (AwtWindow*)
1462 AwtComponent::GetComponent(tk.m_lastWindowUnderMouse);
1463 }
1464 if (hwnd) {
1465 tw = (AwtWindow*)AwtComponent::GetComponent(hwnd);
1466 }
1467
1468 tk.m_lastWindowUnderMouse = hwnd;
1469
1470 if (fw) {
1471 fw->UpdateSecurityWarningVisibility();
1472 }
1473 // ... however, because we use GA_ROOT, we may find the warningIcon
1474 // which is not a Java windows.
1475 if (AwtWindow::IsWarningWindow(hwnd)) {
1476 hwnd = ::GetParent(hwnd);
1477 if (hwnd) {
1478 tw = (AwtWindow*)AwtComponent::GetComponent(hwnd);
1479 }
1480 tk.m_lastWindowUnderMouse = hwnd;
1481 }
1482 if (tw) {
1483 tw->UpdateSecurityWarningVisibility();
1484 }
1485
1486
1487 }
1488 }
1489
1490 return ::CallNextHookEx(AwtToolkit::GetInstance().m_hMouseLLHook, code,
1491 wParam, lParam);
1492
1493 CATCH_BAD_ALLOC_RET(0);
1494 }
1495
1496 /*
1497 * The main message loop
1498 */
1499
1500 const int AwtToolkit::EXIT_ENCLOSING_LOOP = 0;
1501 const int AwtToolkit::EXIT_ALL_ENCLOSING_LOOPS = -1;
1502
1503
1504 /**
1505 * Called upon event idle to ensure that we have released any
1506 * CriticalSections that we took during window event processing.
1507 *
1508 * Note that this gets used more often than you would think; some
1509 * window moves actually happen over more than one event burst. So,
1510 * for example, we might get a WINDOWPOSCHANGING event, then we
1511 * idle and release the lock here, then eventually we get the
1512 * WINDOWPOSCHANGED event.
1513 *
1514 * This method may be called from WToolkit.embeddedEventLoopIdleProcessing
1515 * if there is a separate event loop that must do the same CriticalSection
1516 * check.
1517 *
1518 * See bug #4526587 for more information.
1519 */
VerifyWindowMoveLockReleased()1520 void VerifyWindowMoveLockReleased()
1521 {
1522 if (windowMoveLockHeld) {
1523 windowMoveLockHeld = FALSE;
1524 windowMoveLock.Leave();
1525 }
1526 }
1527
1528 UINT
MessageLoop(IDLEPROC lpIdleFunc,PEEKMESSAGEPROC lpPeekMessageFunc)1529 AwtToolkit::MessageLoop(IDLEPROC lpIdleFunc,
1530 PEEKMESSAGEPROC lpPeekMessageFunc)
1531 {
1532 DTRACE_PRINTLN("AWT event loop started");
1533
1534 DASSERT(lpIdleFunc != NULL);
1535 DASSERT(lpPeekMessageFunc != NULL);
1536
1537 m_messageLoopResult = 0;
1538 while (!m_breakMessageLoop) {
1539
1540 (*lpIdleFunc)();
1541
1542 PumpWaitingMessages(lpPeekMessageFunc); /* pumps waiting messages */
1543
1544 // Catch problems with windowMoveLock critical section. In case we
1545 // misunderstood the way windows processes window move/resize
1546 // events, we don't want to hold onto the windowMoveLock CS forever.
1547 // If we've finished processing events for now, release the lock
1548 // if held.
1549 VerifyWindowMoveLockReleased();
1550 }
1551 if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
1552 ::PostQuitMessage(EXIT_ALL_ENCLOSING_LOOPS);
1553 m_breakMessageLoop = FALSE;
1554
1555 DTRACE_PRINTLN("AWT event loop ended");
1556
1557 return m_messageLoopResult;
1558 }
1559
1560 /*
1561 * Exit the enclosing message loop(s).
1562 *
1563 * The message will be ignored if Windows is currently is in an internal
1564 * message loop (such as a scroll bar drag). So we first send IDCANCEL and
1565 * WM_CANCELMODE messages to every Window on the thread.
1566 */
CancelAllThreadWindows(HWND hWnd,LPARAM)1567 static BOOL CALLBACK CancelAllThreadWindows(HWND hWnd, LPARAM)
1568 {
1569 TRY;
1570
1571 ::SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), (LPARAM)hWnd);
1572 ::SendMessage(hWnd, WM_CANCELMODE, 0, 0);
1573
1574 return TRUE;
1575
1576 CATCH_BAD_ALLOC_RET(FALSE);
1577 }
1578
DoQuitMessageLoop(void * param)1579 static void DoQuitMessageLoop(void* param) {
1580 int status = *static_cast<int*>(param);
1581
1582 AwtToolkit::GetInstance().QuitMessageLoop(status);
1583 }
1584
QuitMessageLoop(int status)1585 void AwtToolkit::QuitMessageLoop(int status) {
1586 /*
1587 * Fix for 4623377.
1588 * Reinvoke QuitMessageLoop on the toolkit thread, so that
1589 * m_breakMessageLoop is accessed on a single thread.
1590 */
1591 if (!AwtToolkit::IsMainThread()) {
1592 InvokeFunction(DoQuitMessageLoop, &status);
1593 return;
1594 }
1595
1596 /*
1597 * Fix for BugTraq ID 4445747.
1598 * EnumThreadWindows() is very slow during dnd on Win9X/ME.
1599 * This call is unnecessary during dnd, since we postpone processing of all
1600 * messages that can enter internal message loop until dnd is over.
1601 */
1602 if (status == EXIT_ALL_ENCLOSING_LOOPS) {
1603 ::EnumThreadWindows(MainThread(), (WNDENUMPROC)CancelAllThreadWindows,
1604 0);
1605 }
1606
1607 /*
1608 * Fix for 4623377.
1609 * Modal loop may not exit immediatelly after WM_CANCELMODE, so it still can
1610 * eat WM_QUIT message and the nested message loop will never exit.
1611 * The fix is to use AwtToolkit instance variables instead of WM_QUIT to
1612 * guarantee that we exit from the nested message loop when any possible
1613 * modal loop quits. In this case CancelAllThreadWindows is needed only to
1614 * ensure that the nested message loop exits quickly and doesn't wait until
1615 * a possible modal loop completes.
1616 */
1617 m_breakMessageLoop = TRUE;
1618 m_messageLoopResult = status;
1619
1620 /*
1621 * Fix for 4683602.
1622 * Post an empty message, to wake up the toolkit thread
1623 * if it is currently in WaitMessage(),
1624 */
1625 PostMessage(WM_NULL);
1626 }
1627
1628 /*
1629 * Called by the message loop to pump the message queue when there are
1630 * messages waiting. Can also be called anywhere to pump messages.
1631 */
PumpWaitingMessages(PEEKMESSAGEPROC lpPeekMessageFunc)1632 BOOL AwtToolkit::PumpWaitingMessages(PEEKMESSAGEPROC lpPeekMessageFunc)
1633 {
1634 MSG msg;
1635 BOOL foundOne = FALSE;
1636
1637 DASSERT(lpPeekMessageFunc != NULL);
1638
1639 while (!m_breakMessageLoop && (*lpPeekMessageFunc)(msg)) {
1640 foundOne = TRUE;
1641 ProcessMsg(msg);
1642 }
1643 return foundOne;
1644 }
1645
PumpToDestroy(class AwtComponent * p)1646 void AwtToolkit::PumpToDestroy(class AwtComponent* p)
1647 {
1648 MSG msg;
1649
1650 DASSERT(AwtToolkit::PrimaryIdleFunc != NULL);
1651 DASSERT(AwtToolkit::CommonPeekMessageFunc != NULL);
1652
1653 while (p->IsDestroyPaused() && !m_breakMessageLoop) {
1654
1655 PrimaryIdleFunc();
1656
1657 while (p->IsDestroyPaused() && !m_breakMessageLoop && CommonPeekMessageFunc(msg)) {
1658 ProcessMsg(msg);
1659 }
1660 }
1661 }
1662
ProcessMsg(MSG & msg)1663 void AwtToolkit::ProcessMsg(MSG& msg)
1664 {
1665 if (msg.message == WM_QUIT) {
1666 m_breakMessageLoop = TRUE;
1667 m_messageLoopResult = static_cast<UINT>(msg.wParam);
1668 if (m_messageLoopResult == EXIT_ALL_ENCLOSING_LOOPS)
1669 ::PostQuitMessage(static_cast<int>(msg.wParam)); // make sure all loops exit
1670 }
1671 else if (msg.message != WM_NULL) {
1672 /*
1673 * The AWT in standalone mode (that is, dynamically loaded from the
1674 * Java VM) doesn't have any translation tables to worry about, so
1675 * TranslateAccelerator isn't called.
1676 */
1677
1678 ::TranslateMessage(&msg);
1679 ::DispatchMessage(&msg);
1680 }
1681 }
1682
1683 VOID CALLBACK
PrimaryIdleFunc()1684 AwtToolkit::PrimaryIdleFunc() {
1685 AwtToolkit::SetBusy(FALSE);
1686 ::WaitMessage(); /* allow system to go idle */
1687 AwtToolkit::SetBusy(TRUE);
1688 }
1689
1690 VOID CALLBACK
SecondaryIdleFunc()1691 AwtToolkit::SecondaryIdleFunc() {
1692 ::WaitMessage(); /* allow system to go idle */
1693 }
1694
1695 BOOL
CommonPeekMessageFunc(MSG & msg)1696 AwtToolkit::CommonPeekMessageFunc(MSG& msg) {
1697 return ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
1698 }
1699
1700 /*
1701 * Perform pre-processing on a message before it is translated &
1702 * dispatched. Returns true to eat the message
1703 */
PreProcessMsg(MSG & msg)1704 BOOL AwtToolkit::PreProcessMsg(MSG& msg)
1705 {
1706 /*
1707 * Offer preprocessing first to the target component, then call out to
1708 * specific mouse and key preprocessor methods
1709 */
1710 AwtComponent* p = AwtComponent::GetComponent(msg.hwnd);
1711 if (p && p->PreProcessMsg(msg) == mrConsume)
1712 return TRUE;
1713
1714 if ((msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) ||
1715 (msg.message >= WM_NCMOUSEMOVE && msg.message <= WM_NCMBUTTONDBLCLK)) {
1716 if (PreProcessMouseMsg(p, msg)) {
1717 return TRUE;
1718 }
1719 }
1720 else if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) {
1721 if (PreProcessKeyMsg(p, msg))
1722 return TRUE;
1723 }
1724 return FALSE;
1725 }
1726
PreProcessMouseMsg(AwtComponent * p,MSG & msg)1727 BOOL AwtToolkit::PreProcessMouseMsg(AwtComponent* p, MSG& msg)
1728 {
1729 WPARAM mouseWParam;
1730 LPARAM mouseLParam;
1731
1732 /*
1733 * Fix for BugTraq ID 4395290.
1734 * Do not synthesize mouse enter/exit events during drag-and-drop,
1735 * since it messes up LightweightDispatcher.
1736 */
1737 if (AwtDropTarget::IsLocalDnD()) {
1738 return FALSE;
1739 }
1740
1741 if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) {
1742 mouseWParam = msg.wParam;
1743 mouseLParam = msg.lParam;
1744 } else {
1745 mouseWParam = GetMouseKeyState();
1746 }
1747
1748 /*
1749 * Get the window under the mouse, as it will be different if its
1750 * captured.
1751 */
1752 DWORD dwCurPos = ::GetMessagePos();
1753 DWORD dwScreenPos = dwCurPos;
1754 POINT curPos;
1755 // fix for 4805862
1756 // According to MSDN: do not use LOWORD and HIWORD macros to extract x and
1757 // y coordinates because these macros return incorrect results on systems
1758 // with multiple monitors (signed values are treated as unsigned)
1759 curPos.x = GET_X_LPARAM(dwCurPos);
1760 curPos.y = GET_Y_LPARAM(dwCurPos);
1761 HWND hWndFromPoint = ::WindowFromPoint(curPos);
1762 // hWndFromPoint == 0 if mouse is over a scrollbar
1763 AwtComponent* mouseComp =
1764 AwtComponent::GetComponent(hWndFromPoint);
1765 // Need extra copies for non-client area issues
1766 HWND hWndForWheel = hWndFromPoint;
1767
1768 // If the point under the mouse isn't in the client area,
1769 // ignore it to maintain compatibility with Solaris (#4095172)
1770 RECT windowRect;
1771 ::GetClientRect(hWndFromPoint, &windowRect);
1772 POINT topLeft;
1773 topLeft.x = 0;
1774 topLeft.y = 0;
1775 ::ClientToScreen(hWndFromPoint, &topLeft);
1776 windowRect.top += topLeft.y;
1777 windowRect.bottom += topLeft.y;
1778 windowRect.left += topLeft.x;
1779 windowRect.right += topLeft.x;
1780 if ((curPos.y < windowRect.top) ||
1781 (curPos.y >= windowRect.bottom) ||
1782 (curPos.x < windowRect.left) ||
1783 (curPos.x >= windowRect.right)) {
1784 mouseComp = NULL;
1785 hWndFromPoint = NULL;
1786 }
1787
1788 /*
1789 * Look for mouse transitions between windows & create
1790 * MouseExit & MouseEnter messages
1791 */
1792 // 6479820. Should check if a window is in manual resizing process: skip
1793 // sending any MouseExit/Enter events while inside resize-loop.
1794 // Note that window being in manual moving process could still
1795 // produce redundant enter/exit mouse events. In future, they can be
1796 // made skipped in a similar way.
1797 if (mouseComp != m_lastMouseOver && !AwtWindow::IsResizing()) {
1798 /*
1799 * Send the messages right to the windows so that they are in
1800 * the right sequence.
1801 */
1802 if (m_lastMouseOver) {
1803 dwCurPos = dwScreenPos;
1804 curPos.x = LOWORD(dwCurPos);
1805 curPos.y = HIWORD(dwCurPos);
1806 ::MapWindowPoints(HWND_DESKTOP, m_lastMouseOver->GetHWnd(),
1807 &curPos, 1);
1808 mouseLParam = MAKELPARAM((WORD)curPos.x, (WORD)curPos.y);
1809 m_lastMouseOver->SendMessage(WM_AWT_MOUSEEXIT, mouseWParam,
1810 mouseLParam);
1811 }
1812 if (mouseComp) {
1813 dwCurPos = dwScreenPos;
1814 curPos.x = LOWORD(dwCurPos);
1815 curPos.y = HIWORD(dwCurPos);
1816 ::MapWindowPoints(HWND_DESKTOP, mouseComp->GetHWnd(),
1817 &curPos, 1);
1818 mouseLParam = MAKELPARAM((WORD)curPos.x, (WORD)curPos.y);
1819 mouseComp->SendMessage(WM_AWT_MOUSEENTER, mouseWParam,
1820 mouseLParam);
1821 }
1822 m_lastMouseOver = mouseComp;
1823 }
1824
1825 /*
1826 * For MouseWheelEvents, hwnd must be changed to be the Component under
1827 * the mouse, not the Component with the input focus.
1828 */
1829
1830 if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL) {
1831 //i.e. mouse is over client area for this window
1832 DWORD hWndForWheelProcess;
1833 DWORD hWndForWheelThread = ::GetWindowThreadProcessId(hWndForWheel, &hWndForWheelProcess);
1834 if (::GetCurrentProcessId() == hWndForWheelProcess) {
1835 if (AwtToolkit::MainThread() == hWndForWheelThread) {
1836 msg.hwnd = hWndForWheel;
1837 } else {
1838 // Interop mode, redispatch the event to another toolkit.
1839 ::SendMessage(hWndForWheel, msg.message, mouseWParam, mouseLParam);
1840 return TRUE;
1841 }
1842 }
1843 }
1844
1845 /*
1846 * Make sure we get at least one last chance to check for transitions
1847 * before we sleep
1848 */
1849 if (m_lastMouseOver && !m_timer) {
1850 m_timer = ::SetTimer(m_toolkitHWnd, IDT_AWT_MOUSECHECK, 200, 0);
1851 }
1852 return FALSE; /* Now go ahead and process current message as usual */
1853 }
1854
PreProcessKeyMsg(AwtComponent * p,MSG & msg)1855 BOOL AwtToolkit::PreProcessKeyMsg(AwtComponent* p, MSG& msg)
1856 {
1857 // get keyboard state for use in AwtToolkit::GetKeyboardState
1858 CriticalSection::Lock l(m_lockKB);
1859 ::GetKeyboardState(m_lastKeyboardState);
1860 return FALSE;
1861 }
1862
SyncCall(void * (* ftn)(void *),void * param)1863 void *AwtToolkit::SyncCall(void *(*ftn)(void *), void *param) {
1864 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1865 if (!IsMainThread()) {
1866 CriticalSection::Lock l(GetSyncCS());
1867 return (*ftn)(param);
1868 } else {
1869 return (*ftn)(param);
1870 }
1871 }
1872
SyncCall(void (* ftn)(void *),void * param)1873 void AwtToolkit::SyncCall(void (*ftn)(void *), void *param) {
1874 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1875 if (!IsMainThread()) {
1876 CriticalSection::Lock l(GetSyncCS());
1877 (*ftn)(param);
1878 } else {
1879 (*ftn)(param);
1880 }
1881 }
1882
SyncCall(void * (* ftn)(void))1883 void *AwtToolkit::SyncCall(void *(*ftn)(void)) {
1884 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1885 if (!IsMainThread()) {
1886 CriticalSection::Lock l(GetSyncCS());
1887 return (*ftn)();
1888 } else {
1889 return (*ftn)();
1890 }
1891 }
1892
SyncCall(void (* ftn)(void))1893 void AwtToolkit::SyncCall(void (*ftn)(void)) {
1894 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1895 if (!IsMainThread()) {
1896 CriticalSection::Lock l(GetSyncCS());
1897 (*ftn)();
1898 } else {
1899 (*ftn)();
1900 }
1901 }
1902
isFreeIDAvailable()1903 jboolean AwtToolkit::isFreeIDAvailable()
1904 {
1905 return m_cmdIDs->isFreeIDAvailable();
1906 }
1907
CreateCmdID(AwtObject * object)1908 UINT AwtToolkit::CreateCmdID(AwtObject* object)
1909 {
1910 return m_cmdIDs->Add(object);
1911 }
1912
RemoveCmdID(UINT id)1913 void AwtToolkit::RemoveCmdID(UINT id)
1914 {
1915 m_cmdIDs->Remove(id);
1916 }
1917
LookupCmdID(UINT id)1918 AwtObject* AwtToolkit::LookupCmdID(UINT id)
1919 {
1920 return m_cmdIDs->Lookup(id);
1921 }
1922
GetAwtIcon()1923 HICON AwtToolkit::GetAwtIcon()
1924 {
1925 return ::LoadIcon(GetModuleHandle(), TEXT("AWT_ICON"));
1926 }
1927
GetAwtIconSm()1928 HICON AwtToolkit::GetAwtIconSm()
1929 {
1930 static HICON defaultIconSm = NULL;
1931 static int prevSmx = 0;
1932 static int prevSmy = 0;
1933
1934 int smx = GetSystemMetrics(SM_CXSMICON);
1935 int smy = GetSystemMetrics(SM_CYSMICON);
1936
1937 // Fixed 6364216: LoadImage() may leak memory
1938 if (defaultIconSm == NULL || smx != prevSmx || smy != prevSmy) {
1939 defaultIconSm = (HICON)LoadImage(GetModuleHandle(), TEXT("AWT_ICON"), IMAGE_ICON, smx, smy, 0);
1940 prevSmx = smx;
1941 prevSmy = smy;
1942 }
1943 return defaultIconSm;
1944 }
1945
1946 // The icon at index 0 must be gray. See AwtWindow::GetSecurityWarningIcon()
GetSecurityWarningIcon(UINT index,UINT w,UINT h)1947 HICON AwtToolkit::GetSecurityWarningIcon(UINT index, UINT w, UINT h)
1948 {
1949 //Note: should not exceed 10 because of the current implementation.
1950 static const int securityWarningIconCounter = 3;
1951
1952 static HICON securityWarningIcon[securityWarningIconCounter] = {NULL, NULL, NULL};;
1953 static UINT securityWarningIconWidth[securityWarningIconCounter] = {0, 0, 0};
1954 static UINT securityWarningIconHeight[securityWarningIconCounter] = {0, 0, 0};
1955
1956 index = AwtToolkit::CalculateWave(index, securityWarningIconCounter);
1957
1958 if (securityWarningIcon[index] == NULL ||
1959 w != securityWarningIconWidth[index] ||
1960 h != securityWarningIconHeight[index])
1961 {
1962 if (securityWarningIcon[index] != NULL)
1963 {
1964 ::DestroyIcon(securityWarningIcon[index]);
1965 }
1966
1967 static const wchar_t securityWarningIconName[] = L"SECURITY_WARNING_";
1968 wchar_t iconResourceName[sizeof(securityWarningIconName) + 2];
1969 ::ZeroMemory(iconResourceName, sizeof(iconResourceName));
1970 wcscpy(iconResourceName, securityWarningIconName);
1971
1972 wchar_t strIndex[2];
1973 ::ZeroMemory(strIndex, sizeof(strIndex));
1974 strIndex[0] = L'0' + index;
1975
1976 wcscat(iconResourceName, strIndex);
1977
1978 securityWarningIcon[index] = (HICON)::LoadImage(GetModuleHandle(),
1979 iconResourceName,
1980 IMAGE_ICON, w, h, LR_DEFAULTCOLOR);
1981 securityWarningIconWidth[index] = w;
1982 securityWarningIconHeight[index] = h;
1983 }
1984
1985 return securityWarningIcon[index];
1986 }
1987
SetHeapCheck(long flag)1988 void AwtToolkit::SetHeapCheck(long flag) {
1989 if (flag) {
1990 printf("heap checking not supported with this build\n");
1991 }
1992 }
1993
throw_if_shutdown(void)1994 void throw_if_shutdown(void) throw (awt_toolkit_shutdown)
1995 {
1996 AwtToolkit::GetInstance().VerifyActive();
1997 }
hang_if_shutdown(void)1998 void hang_if_shutdown(void)
1999 {
2000 try {
2001 AwtToolkit::GetInstance().VerifyActive();
2002 } catch (awt_toolkit_shutdown&) {
2003 // Never return. The VM will halt the process.
2004 ::WaitForSingleObject(::CreateEvent(NULL, TRUE, FALSE, NULL),
2005 INFINITE);
2006 // Should never get here.
2007 DASSERT(FALSE);
2008 }
2009 }
2010
2011 // for now we support only one embedder, but should be ready for future
RegisterEmbedderProcessId(HWND embedder)2012 void AwtToolkit::RegisterEmbedderProcessId(HWND embedder)
2013 {
2014 if (m_embedderProcessID) {
2015 // we already set embedder process and do not expect
2016 // two different processes to embed the same AwtToolkit
2017 return;
2018 }
2019
2020 embedder = ::GetAncestor(embedder, GA_ROOT);
2021 ::GetWindowThreadProcessId(embedder, &m_embedderProcessID);
2022 }
2023
2024 JNIEnv* AwtToolkit::m_env;
2025 DWORD AwtToolkit::m_threadId;
2026
SetEnv(JNIEnv * env)2027 void AwtToolkit::SetEnv(JNIEnv *env) {
2028 if (m_env != NULL) { // If already cashed (by means of embeddedInit() call).
2029 return;
2030 }
2031 m_threadId = GetCurrentThreadId();
2032 m_env = env;
2033 }
2034
GetEnv()2035 JNIEnv* AwtToolkit::GetEnv() {
2036 return (m_env == NULL || m_threadId != GetCurrentThreadId()) ?
2037 (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2) : m_env;
2038 }
2039
GetScreenInsets(int screenNum,RECT * rect)2040 BOOL AwtToolkit::GetScreenInsets(int screenNum, RECT * rect)
2041 {
2042 /* if primary display */
2043 if (screenNum == 0) {
2044 RECT rRW;
2045 if (::SystemParametersInfo(SPI_GETWORKAREA,0,(void *) &rRW,0) == TRUE) {
2046 rect->top = rRW.top;
2047 rect->left = rRW.left;
2048 rect->bottom = ::GetSystemMetrics(SM_CYSCREEN) - rRW.bottom;
2049 rect->right = ::GetSystemMetrics(SM_CXSCREEN) - rRW.right;
2050 return TRUE;
2051 }
2052 }
2053 /* if additional display */
2054 else {
2055 MONITORINFO *miInfo;
2056 miInfo = AwtWin32GraphicsDevice::GetMonitorInfo(screenNum);
2057 if (miInfo) {
2058 rect->top = miInfo->rcWork.top - miInfo->rcMonitor.top;
2059 rect->left = miInfo->rcWork.left - miInfo->rcMonitor.left;
2060 rect->bottom = miInfo->rcMonitor.bottom - miInfo->rcWork.bottom;
2061 rect->right = miInfo->rcMonitor.right - miInfo->rcWork.right;
2062 return TRUE;
2063 }
2064 }
2065 return FALSE;
2066 }
2067
2068
GetWindowRect(HWND hWnd,LPRECT lpRect)2069 void AwtToolkit::GetWindowRect(HWND hWnd, LPRECT lpRect)
2070 {
2071 try {
2072 if (S_OK == DwmAPI::DwmGetWindowAttribute(hWnd,
2073 DwmAPI::DWMWA_EXTENDED_FRAME_BOUNDS,
2074 lpRect, sizeof(*lpRect)))
2075 {
2076 return;
2077 }
2078 } catch (const DllUtil::Exception &) {}
2079
2080 ::GetWindowRect(hWnd, lpRect);
2081 }
2082
2083
2084 /************************************************************************
2085 * AWT preloading support
2086 */
EnsureInited()2087 bool AwtToolkit::PreloadAction::EnsureInited()
2088 {
2089 DWORD _initThreadId = GetInitThreadID();
2090 if (_initThreadId != 0) {
2091 // already inited
2092 // ensure the action is inited on correct thread
2093 PreloadThread &preloadThread
2094 = AwtToolkit::GetInstance().GetPreloadThread();
2095 if (_initThreadId == preloadThread.GetThreadId()) {
2096 if (!preloadThread.IsWrongThread()) {
2097 return true;
2098 }
2099 // inited on preloadThread (wrongThread), not cleaned yet
2100 // have to wait cleanup completion
2101 preloadThread.Wait4Finish();
2102 } else {
2103 // inited on other thread (Toolkit thread?)
2104 // consider as correctly inited
2105 return true;
2106 }
2107 }
2108
2109 // init on Toolkit thread
2110 AwtToolkit::GetInstance().InvokeFunction(InitWrapper, this);
2111
2112 return true;
2113 }
2114
GetInitThreadID()2115 DWORD AwtToolkit::PreloadAction::GetInitThreadID()
2116 {
2117 CriticalSection::Lock lock(initLock);
2118 return initThreadId;
2119 }
2120
Clean()2121 bool AwtToolkit::PreloadAction::Clean()
2122 {
2123 DWORD _initThreadId = GetInitThreadID();
2124 if (_initThreadId == ::GetCurrentThreadId()) {
2125 // inited on this thread
2126 Clean(false);
2127 return true;
2128 }
2129 return false;
2130 }
2131
2132 /*static*/
InitWrapper(void * param)2133 void AwtToolkit::PreloadAction::InitWrapper(void *param)
2134 {
2135 PreloadAction *pThis = (PreloadAction *)param;
2136 pThis->Init();
2137 }
2138
Init()2139 void AwtToolkit::PreloadAction::Init()
2140 {
2141 CriticalSection::Lock lock(initLock);
2142 if (initThreadId == 0) {
2143 initThreadId = ::GetCurrentThreadId();
2144 InitImpl();
2145 }
2146 }
2147
Clean(bool reInit)2148 void AwtToolkit::PreloadAction::Clean(bool reInit) {
2149 CriticalSection::Lock lock(initLock);
2150 if (initThreadId != 0) {
2151 //ASSERT(initThreadId == ::GetCurrentThreadId());
2152 CleanImpl(reInit);
2153 initThreadId = 0;
2154 }
2155 }
2156
2157 // PreloadThread implementation
PreloadThread()2158 AwtToolkit::PreloadThread::PreloadThread()
2159 : status(None), wrongThread(false), threadId(0),
2160 pActionChain(NULL), pLastProcessedAction(NULL),
2161 execFunc(NULL), execParam(NULL)
2162 {
2163 hFinished = ::CreateEvent(NULL, TRUE, FALSE, NULL);
2164 hAwake = ::CreateEvent(NULL, FALSE, FALSE, NULL);
2165 }
2166
~PreloadThread()2167 AwtToolkit::PreloadThread::~PreloadThread()
2168 {
2169 //Terminate(false);
2170 ::CloseHandle(hFinished);
2171 ::CloseHandle(hAwake);
2172 }
2173
AddAction(AwtToolkit::PreloadAction * pAction)2174 bool AwtToolkit::PreloadThread::AddAction(AwtToolkit::PreloadAction *pAction)
2175 {
2176 CriticalSection::Lock lock(threadLock);
2177
2178 if (status > Preloading) {
2179 // too late - the thread already terminated or run as toolkit thread
2180 return false;
2181 }
2182
2183 if (pActionChain == NULL) {
2184 // 1st action
2185 pActionChain = pAction;
2186 } else {
2187 // add the action to the chain
2188 PreloadAction *pChain = pActionChain;
2189 while (true) {
2190 PreloadAction *pNext = pChain->GetNext();
2191 if (pNext == NULL) {
2192 break;
2193 }
2194 pChain = pNext;
2195 }
2196 pChain->SetNext(pAction);
2197 }
2198
2199 if (status > None) {
2200 // the thread is already running (status == Preloading)
2201 AwakeThread();
2202 return true;
2203 }
2204
2205 // need to start thread
2206 ::ResetEvent(hAwake);
2207 ::ResetEvent(hFinished);
2208
2209 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0x100000, StaticThreadProc,
2210 this, 0, &threadId);
2211
2212 if (hThread == 0) {
2213 threadId = 0;
2214 return false;
2215 }
2216
2217 status = Preloading;
2218
2219 ::CloseHandle(hThread);
2220
2221 return true;
2222 }
2223
Terminate(bool wrongThread)2224 bool AwtToolkit::PreloadThread::Terminate(bool wrongThread)
2225 {
2226 CriticalSection::Lock lock(threadLock);
2227
2228 if (status != Preloading) {
2229 return false;
2230 }
2231
2232 execFunc = NULL;
2233 execParam = NULL;
2234 this->wrongThread = wrongThread;
2235 status = Cleaning;
2236 AwakeThread();
2237
2238 return true;
2239 }
2240
InvokeAndTerminate(void (_cdecl * fn)(void *),void * param)2241 bool AwtToolkit::PreloadThread::InvokeAndTerminate(void(_cdecl *fn)(void *), void *param)
2242 {
2243 CriticalSection::Lock lock(threadLock);
2244
2245 if (status != Preloading) {
2246 return false;
2247 }
2248
2249 execFunc = fn;
2250 execParam = param;
2251 status = fn == NULL ? Cleaning : RunningToolkit;
2252 AwakeThread();
2253
2254 return true;
2255 }
2256
OnPreloadThread()2257 bool AwtToolkit::PreloadThread::OnPreloadThread()
2258 {
2259 return GetThreadId() == ::GetCurrentThreadId();
2260 }
2261
2262 /*static*/
StaticThreadProc(void * param)2263 unsigned WINAPI AwtToolkit::PreloadThread::StaticThreadProc(void *param)
2264 {
2265 AwtToolkit::PreloadThread *pThis = (AwtToolkit::PreloadThread *)param;
2266 return pThis->ThreadProc();
2267 }
2268
ThreadProc()2269 unsigned AwtToolkit::PreloadThread::ThreadProc()
2270 {
2271 void(_cdecl *_execFunc)(void *) = NULL;
2272 void *_execParam = NULL;
2273 bool _wrongThread = false;
2274
2275 // initialization
2276 while (true) {
2277 PreloadAction *pAction;
2278 {
2279 CriticalSection::Lock lock(threadLock);
2280 if (status != Preloading) {
2281 // get invoke parameters
2282 _execFunc = execFunc;
2283 _execParam = execParam;
2284 _wrongThread = wrongThread;
2285 break;
2286 }
2287 pAction = GetNextAction();
2288 }
2289 if (pAction != NULL) {
2290 pAction->Init();
2291 } else {
2292 ::WaitForSingleObject(hAwake, INFINITE);
2293 }
2294 }
2295
2296 // call a function from InvokeAndTerminate
2297 if (_execFunc != NULL) {
2298 _execFunc(_execParam);
2299 } else {
2300 // time to terminate..
2301 }
2302
2303 // cleanup
2304 {
2305 CriticalSection::Lock lock(threadLock);
2306 pLastProcessedAction = NULL; // goto 1st action in the chain
2307 status = Cleaning;
2308 }
2309 for (PreloadAction *pAction = GetNextAction(); pAction != NULL;
2310 pAction = GetNextAction()) {
2311 pAction->Clean(_wrongThread);
2312 }
2313
2314 // don't clear threadId! it is used by PreloadAction::EnsureInited
2315
2316 {
2317 CriticalSection::Lock lock(threadLock);
2318 status = Finished;
2319 }
2320 ::SetEvent(hFinished);
2321 return 0;
2322 }
2323
GetNextAction()2324 AwtToolkit::PreloadAction* AwtToolkit::PreloadThread::GetNextAction()
2325 {
2326 CriticalSection::Lock lock(threadLock);
2327 PreloadAction *pAction = (pLastProcessedAction == NULL)
2328 ? pActionChain
2329 : pLastProcessedAction->GetNext();
2330 if (pAction != NULL) {
2331 pLastProcessedAction = pAction;
2332 }
2333
2334 return pAction;
2335 }
2336
2337
2338 extern "C" {
2339
2340 /* Terminates preload thread (if it's still alive
2341 * - it may occur if the application doesn't use AWT).
2342 * The function is called from launcher after completion main java thread.
2343 */
preloadStop()2344 __declspec(dllexport) void preloadStop()
2345 {
2346 AwtToolkit::GetInstance().GetPreloadThread().Terminate(false);
2347 }
2348
2349 }
2350
2351
2352 /************************************************************************
2353 * Toolkit native methods
2354 */
2355
2356 extern "C" {
2357
2358 /*
2359 * Class: java_awt_Toolkit
2360 * Method: initIDs
2361 * Signature: ()V
2362 */
2363 JNIEXPORT void JNICALL
Java_java_awt_Toolkit_initIDs(JNIEnv * env,jclass cls)2364 Java_java_awt_Toolkit_initIDs(JNIEnv *env, jclass cls) {
2365 TRY;
2366
2367 AwtToolkit::getDefaultToolkitMID =
2368 env->GetStaticMethodID(cls,"getDefaultToolkit","()Ljava/awt/Toolkit;");
2369 DASSERT(AwtToolkit::getDefaultToolkitMID != NULL);
2370 CHECK_NULL(AwtToolkit::getDefaultToolkitMID);
2371
2372 AwtToolkit::getFontMetricsMID =
2373 env->GetMethodID(cls, "getFontMetrics", "(Ljava/awt/Font;)Ljava/awt/FontMetrics;");
2374 DASSERT(AwtToolkit::getFontMetricsMID != NULL);
2375 CHECK_NULL(AwtToolkit::getFontMetricsMID);
2376
2377 jclass insetsClass = env->FindClass("java/awt/Insets");
2378 DASSERT(insetsClass != NULL);
2379 CHECK_NULL(insetsClass);
2380 AwtToolkit::insetsMID = env->GetMethodID(insetsClass, "<init>", "(IIII)V");
2381 DASSERT(AwtToolkit::insetsMID != NULL);
2382 CHECK_NULL(AwtToolkit::insetsMID);
2383
2384 CATCH_BAD_ALLOC;
2385 }
2386
2387
2388 } /* extern "C" */
2389
2390 /************************************************************************
2391 * WToolkit native methods
2392 */
2393
2394 extern "C" {
2395
2396 /*
2397 * Class: sun_awt_windows_WToolkit
2398 * Method: initIDs
2399 * Signature: ()V
2400 */
2401 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_initIDs(JNIEnv * env,jclass cls)2402 Java_sun_awt_windows_WToolkit_initIDs(JNIEnv *env, jclass cls)
2403 {
2404 TRY;
2405
2406 AwtToolkit::windowsSettingChangeMID =
2407 env->GetMethodID(cls, "windowsSettingChange", "()V");
2408 DASSERT(AwtToolkit::windowsSettingChangeMID != 0);
2409 CHECK_NULL(AwtToolkit::windowsSettingChangeMID);
2410
2411 AwtToolkit::displayChangeMID =
2412 env->GetStaticMethodID(cls, "displayChanged", "()V");
2413 DASSERT(AwtToolkit::displayChangeMID != 0);
2414 CHECK_NULL(AwtToolkit::displayChangeMID);
2415
2416 // Set various global IDs needed by JAWT code. Note: these
2417 // variables cannot be set by JAWT code directly due to
2418 // different permissions that that code may be run under
2419 // (bug 4796548). It would be nice to initialize these
2420 // variables lazily, but given the minimal number of calls
2421 // for this, it seems simpler to just do it at startup with
2422 // negligible penalty.
2423 jclass sDataClassLocal = env->FindClass("sun/java2d/SurfaceData");
2424 DASSERT(sDataClassLocal != 0);
2425 CHECK_NULL(sDataClassLocal);
2426
2427 jclass vImgClassLocal = env->FindClass("sun/awt/image/SunVolatileImage");
2428 DASSERT(vImgClassLocal != 0);
2429 CHECK_NULL(vImgClassLocal);
2430
2431 jclass vSMgrClassLocal =
2432 env->FindClass("sun/awt/image/VolatileSurfaceManager");
2433 DASSERT(vSMgrClassLocal != 0);
2434 CHECK_NULL(vSMgrClassLocal);
2435
2436 jclass componentClassLocal = env->FindClass("java/awt/Component");
2437 DASSERT(componentClassLocal != 0);
2438 CHECK_NULL(componentClassLocal);
2439
2440 jawtSMgrID = env->GetFieldID(vImgClassLocal, "volSurfaceManager",
2441 "Lsun/awt/image/VolatileSurfaceManager;");
2442 DASSERT(jawtSMgrID != 0);
2443 CHECK_NULL(jawtSMgrID);
2444
2445 jawtSDataID = env->GetFieldID(vSMgrClassLocal, "sdCurrent",
2446 "Lsun/java2d/SurfaceData;");
2447 DASSERT(jawtSDataID != 0);
2448 CHECK_NULL(jawtSDataID);
2449
2450 jawtPDataID = env->GetFieldID(sDataClassLocal, "pData", "J");
2451 DASSERT(jawtPDataID != 0);
2452 CHECK_NULL(jawtPDataID);
2453 // Save these classes in global references for later use
2454 jawtVImgClass = (jclass)env->NewGlobalRef(vImgClassLocal);
2455 CHECK_NULL(jawtVImgClass);
2456 jawtComponentClass = (jclass)env->NewGlobalRef(componentClassLocal);
2457
2458 jclass dPeerClassLocal = env->FindClass("sun/awt/windows/WDesktopPeer");
2459 DASSERT(dPeerClassLocal != 0);
2460 CHECK_NULL(dPeerClassLocal);
2461
2462 jclass reasonClassLocal = env->FindClass("java/awt/desktop/UserSessionEvent$Reason");
2463 CHECK_NULL(reasonClassLocal);
2464
2465 reasonUnspecified = GetStaticObject(env, reasonClassLocal, "UNSPECIFIED",
2466 "Ljava/awt/desktop/UserSessionEvent$Reason;");
2467 CHECK_NULL (reasonUnspecified);
2468 reasonUnspecified = env->NewGlobalRef(reasonUnspecified);
2469
2470 reasonConsole = GetStaticObject(env, reasonClassLocal, "CONSOLE",
2471 "Ljava/awt/desktop/UserSessionEvent$Reason;");
2472 CHECK_NULL (reasonConsole);
2473 reasonConsole = env->NewGlobalRef(reasonConsole);
2474
2475 reasonRemote = GetStaticObject(env, reasonClassLocal, "REMOTE",
2476 "Ljava/awt/desktop/UserSessionEvent$Reason;");
2477 CHECK_NULL (reasonRemote);
2478 reasonRemote = env->NewGlobalRef(reasonRemote);
2479
2480 reasonLock = GetStaticObject(env, reasonClassLocal, "LOCK",
2481 "Ljava/awt/desktop/UserSessionEvent$Reason;");
2482 CHECK_NULL (reasonLock);
2483 reasonLock = env->NewGlobalRef(reasonLock);
2484
2485
2486 AwtToolkit::userSessionMID =
2487 env->GetStaticMethodID(dPeerClassLocal, "userSessionCallback",
2488 "(ZLjava/awt/desktop/UserSessionEvent$Reason;)V");
2489 DASSERT(AwtToolkit::userSessionMID != 0);
2490 CHECK_NULL(AwtToolkit::userSessionMID);
2491
2492 AwtToolkit::systemSleepMID =
2493 env->GetStaticMethodID(dPeerClassLocal, "systemSleepCallback", "(Z)V");
2494 DASSERT(AwtToolkit::systemSleepMID != 0);
2495 CHECK_NULL(AwtToolkit::systemSleepMID);
2496
2497 CATCH_BAD_ALLOC;
2498 }
2499
2500
2501 /*
2502 * Class: sun_awt_windows_Toolkit
2503 * Method: disableCustomPalette
2504 * Signature: ()V
2505 */
2506 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_disableCustomPalette(JNIEnv * env,jclass cls)2507 Java_sun_awt_windows_WToolkit_disableCustomPalette(JNIEnv *env, jclass cls) {
2508 AwtPalette::DisableCustomPalette();
2509 }
2510
2511 /*
2512 * Class: sun_awt_windows_WToolkit
2513 * Method: embeddedInit
2514 * Signature: ()Z
2515 */
2516 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WToolkit_embeddedInit(JNIEnv * env,jclass cls)2517 Java_sun_awt_windows_WToolkit_embeddedInit(JNIEnv *env, jclass cls)
2518 {
2519 TRY;
2520
2521 AwtToolkit::SetEnv(env);
2522
2523 return AwtToolkit::GetInstance().Initialize(FALSE);
2524
2525 CATCH_BAD_ALLOC_RET(JNI_FALSE);
2526 }
2527
2528 /*
2529 * Class: sun_awt_windows_WToolkit
2530 * Method: embeddedDispose
2531 * Signature: ()Z
2532 */
2533 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WToolkit_embeddedDispose(JNIEnv * env,jclass cls)2534 Java_sun_awt_windows_WToolkit_embeddedDispose(JNIEnv *env, jclass cls)
2535 {
2536 TRY;
2537
2538 BOOL retval = AwtToolkit::GetInstance().Dispose();
2539 AwtToolkit::GetInstance().SetPeer(env, NULL);
2540 return retval;
2541
2542 CATCH_BAD_ALLOC_RET(JNI_FALSE);
2543 }
2544
2545 /*
2546 * Class: sun_awt_windows_WToolkit
2547 * Method: embeddedEventLoopIdleProcessing
2548 * Signature: ()V
2549 */
2550 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_embeddedEventLoopIdleProcessing(JNIEnv * env,jobject self)2551 Java_sun_awt_windows_WToolkit_embeddedEventLoopIdleProcessing(JNIEnv *env,
2552 jobject self)
2553 {
2554 VerifyWindowMoveLockReleased();
2555 }
2556
2557
2558 /*
2559 * Class: sun_awt_windows_WToolkit
2560 * Method: init
2561 * Signature: ()Z
2562 */
2563 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WToolkit_init(JNIEnv * env,jobject self)2564 Java_sun_awt_windows_WToolkit_init(JNIEnv *env, jobject self)
2565 {
2566 TRY;
2567
2568 AwtToolkit::SetEnv(env);
2569
2570 AwtToolkit::GetInstance().SetPeer(env, self);
2571
2572 // This call will fail if the Toolkit was already initialized.
2573 // In that case, we don't want to start another message pump.
2574 return AwtToolkit::GetInstance().Initialize(TRUE);
2575
2576 CATCH_BAD_ALLOC_RET(FALSE);
2577 }
2578
2579 /*
2580 * Class: sun_awt_windows_WToolkit
2581 * Method: eventLoop
2582 * Signature: ()V
2583 */
2584 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_eventLoop(JNIEnv * env,jobject self)2585 Java_sun_awt_windows_WToolkit_eventLoop(JNIEnv *env, jobject self)
2586 {
2587 TRY;
2588
2589 DASSERT(AwtToolkit::GetInstance().localPump());
2590
2591 AwtToolkit::SetBusy(TRUE);
2592
2593 AwtToolkit::GetInstance().MessageLoop(AwtToolkit::PrimaryIdleFunc,
2594 AwtToolkit::CommonPeekMessageFunc);
2595
2596 AwtToolkit::GetInstance().Dispose();
2597
2598 AwtToolkit::SetBusy(FALSE);
2599
2600 /*
2601 * IMPORTANT NOTES:
2602 * The AwtToolkit has been destructed by now.
2603 * DO NOT CALL any method of AwtToolkit!!!
2604 */
2605
2606 CATCH_BAD_ALLOC;
2607 }
2608
2609 /*
2610 * Class: sun_awt_windows_WToolkit
2611 * Method: shutdown
2612 * Signature: ()V
2613 */
2614 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_shutdown(JNIEnv * env,jobject self)2615 Java_sun_awt_windows_WToolkit_shutdown(JNIEnv *env, jobject self)
2616 {
2617 TRY;
2618
2619 AwtToolkit& tk = AwtToolkit::GetInstance();
2620
2621 tk.QuitMessageLoop(AwtToolkit::EXIT_ALL_ENCLOSING_LOOPS);
2622
2623 while (!tk.IsDisposed()) {
2624 Sleep(100);
2625 }
2626
2627 CATCH_BAD_ALLOC;
2628 }
2629
2630 /*
2631 * Class: sun_awt_windows_WToolkit
2632 * Method: startSecondaryEventLoop
2633 * Signature: ()V;
2634 */
2635 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_startSecondaryEventLoop(JNIEnv * env,jclass)2636 Java_sun_awt_windows_WToolkit_startSecondaryEventLoop(
2637 JNIEnv *env,
2638 jclass)
2639 {
2640 TRY;
2641
2642 DASSERT(AwtToolkit::MainThread() == ::GetCurrentThreadId());
2643
2644 AwtToolkit::GetInstance().MessageLoop(AwtToolkit::SecondaryIdleFunc,
2645 AwtToolkit::CommonPeekMessageFunc);
2646
2647 CATCH_BAD_ALLOC;
2648 }
2649
2650 /*
2651 * Class: sun_awt_windows_WToolkit
2652 * Method: quitSecondaryEventLoop
2653 * Signature: ()V;
2654 */
2655 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_quitSecondaryEventLoop(JNIEnv * env,jclass)2656 Java_sun_awt_windows_WToolkit_quitSecondaryEventLoop(
2657 JNIEnv *env,
2658 jclass)
2659 {
2660 TRY;
2661
2662 AwtToolkit::GetInstance().QuitMessageLoop(AwtToolkit::EXIT_ENCLOSING_LOOP);
2663
2664 CATCH_BAD_ALLOC;
2665 }
2666
2667 /*
2668 * Class: sun_awt_windows_WToolkit
2669 * Method: makeColorModel
2670 * Signature: ()Ljava/awt/image/ColorModel;
2671 */
2672 JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WToolkit_makeColorModel(JNIEnv * env,jclass cls)2673 Java_sun_awt_windows_WToolkit_makeColorModel(JNIEnv *env, jclass cls)
2674 {
2675 TRY;
2676
2677 return AwtWin32GraphicsDevice::GetColorModel(env, JNI_FALSE,
2678 AwtWin32GraphicsDevice::GetDefaultDeviceIndex());
2679
2680 CATCH_BAD_ALLOC_RET(NULL);
2681 }
2682
2683 /*
2684 * Class: sun_awt_windows_WToolkit
2685 * Method: getMaximumCursorColors
2686 * Signature: ()I
2687 */
2688 JNIEXPORT jint JNICALL
Java_sun_awt_windows_WToolkit_getMaximumCursorColors(JNIEnv * env,jobject self)2689 Java_sun_awt_windows_WToolkit_getMaximumCursorColors(JNIEnv *env, jobject self)
2690 {
2691 TRY;
2692
2693 HDC hIC = ::CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
2694
2695 int nColor = 256;
2696 switch (::GetDeviceCaps(hIC, BITSPIXEL) * ::GetDeviceCaps(hIC, PLANES)) {
2697 case 1: nColor = 2; break;
2698 case 4: nColor = 16; break;
2699 case 8: nColor = 256; break;
2700 case 16: nColor = 65536; break;
2701 case 24: nColor = 16777216; break;
2702 }
2703 ::DeleteDC(hIC);
2704 return nColor;
2705
2706 CATCH_BAD_ALLOC_RET(0);
2707 }
2708
2709 /*
2710 * Class: sun_awt_windows_WToolkit
2711 * Method: getSreenInsets
2712 * Signature: (I)Ljava/awt/Insets;
2713 */
2714 JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WToolkit_getScreenInsets(JNIEnv * env,jobject self,jint screen)2715 Java_sun_awt_windows_WToolkit_getScreenInsets(JNIEnv *env,
2716 jobject self,
2717 jint screen)
2718 {
2719 jobject insets = NULL;
2720 RECT rect;
2721
2722 TRY;
2723
2724 if (AwtToolkit::GetScreenInsets(screen, &rect)) {
2725 jclass insetsClass = env->FindClass("java/awt/Insets");
2726 DASSERT(insetsClass != NULL);
2727 CHECK_NULL_RETURN(insetsClass, NULL);
2728 Devices::InstanceAccess devices;
2729 AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
2730 insets = env->NewObject(insetsClass,
2731 AwtToolkit::insetsMID,
2732 device == NULL ? rect.top : device->ScaleDownY(rect.top),
2733 device == NULL ? rect.left : device->ScaleDownX(rect.left),
2734 device == NULL ? rect.bottom : device->ScaleDownY(rect.bottom),
2735 device == NULL ? rect.right : device->ScaleDownX(rect.right));
2736 }
2737
2738 if (safe_ExceptionOccurred(env)) {
2739 return 0;
2740 }
2741 return insets;
2742
2743 CATCH_BAD_ALLOC_RET(NULL);
2744 }
2745
2746
2747 /*
2748 * Class: sun_awt_windows_WToolkit
2749 * Method: nativeSync
2750 * Signature: ()V
2751 */
2752 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_nativeSync(JNIEnv * env,jobject self)2753 Java_sun_awt_windows_WToolkit_nativeSync(JNIEnv *env, jobject self)
2754 {
2755 TRY;
2756
2757 // Synchronize both GDI and DDraw
2758 VERIFY(::GdiFlush());
2759
2760 CATCH_BAD_ALLOC;
2761 }
2762
2763 /*
2764 * Class: sun_awt_windows_WToolkit
2765 * Method: beep
2766 * Signature: ()V
2767 */
2768 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_beep(JNIEnv * env,jobject self)2769 Java_sun_awt_windows_WToolkit_beep(JNIEnv *env, jobject self)
2770 {
2771 TRY;
2772
2773 VERIFY(::MessageBeep(MB_OK));
2774
2775 CATCH_BAD_ALLOC;
2776 }
2777
2778 /*
2779 * Class: sun_awt_windows_WToolkit
2780 * Method: getLockingKeyStateNative
2781 * Signature: (I)Z
2782 */
2783 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WToolkit_getLockingKeyStateNative(JNIEnv * env,jobject self,jint javaKey)2784 Java_sun_awt_windows_WToolkit_getLockingKeyStateNative(JNIEnv *env, jobject self, jint javaKey)
2785 {
2786 TRY;
2787
2788 UINT windowsKey, modifiers;
2789 AwtComponent::JavaKeyToWindowsKey(javaKey, &windowsKey, &modifiers);
2790
2791 if (windowsKey == 0) {
2792 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "Keyboard doesn't have requested key");
2793 return JNI_FALSE;
2794 }
2795
2796 // low order bit in keyboardState indicates whether the key is toggled
2797 BYTE keyboardState[AwtToolkit::KB_STATE_SIZE];
2798 AwtToolkit::GetKeyboardState(keyboardState);
2799 return keyboardState[windowsKey] & 0x01;
2800
2801 CATCH_BAD_ALLOC_RET(JNI_FALSE);
2802 }
2803
2804 /*
2805 * Class: sun_awt_windows_WToolkit
2806 * Method: setLockingKeyStateNative
2807 * Signature: (IZ)V
2808 */
2809 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_setLockingKeyStateNative(JNIEnv * env,jobject self,jint javaKey,jboolean state)2810 Java_sun_awt_windows_WToolkit_setLockingKeyStateNative(JNIEnv *env, jobject self, jint javaKey, jboolean state)
2811 {
2812 TRY;
2813
2814 UINT windowsKey, modifiers;
2815 AwtComponent::JavaKeyToWindowsKey(javaKey, &windowsKey, &modifiers);
2816
2817 if (windowsKey == 0) {
2818 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "Keyboard doesn't have requested key");
2819 return;
2820 }
2821
2822 // if the key isn't in the desired state yet, simulate key events to get there
2823 // low order bit in keyboardState indicates whether the key is toggled
2824 BYTE keyboardState[AwtToolkit::KB_STATE_SIZE];
2825 AwtToolkit::GetKeyboardState(keyboardState);
2826 if ((keyboardState[windowsKey] & 0x01) != state) {
2827 ::keybd_event(windowsKey, 0, 0, 0);
2828 ::keybd_event(windowsKey, 0, KEYEVENTF_KEYUP, 0);
2829 }
2830
2831 CATCH_BAD_ALLOC;
2832 }
2833
2834 /*
2835 * Class: sun_awt_windows_WToolkit
2836 * Method: loadSystemColors
2837 * Signature: ([I)V
2838 */
2839 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_loadSystemColors(JNIEnv * env,jobject self,jintArray colors)2840 Java_sun_awt_windows_WToolkit_loadSystemColors(JNIEnv *env, jobject self,
2841 jintArray colors)
2842 {
2843 TRY;
2844
2845 static int indexMap[] = {
2846 COLOR_DESKTOP, /* DESKTOP */
2847 COLOR_ACTIVECAPTION, /* ACTIVE_CAPTION */
2848 COLOR_CAPTIONTEXT, /* ACTIVE_CAPTION_TEXT */
2849 COLOR_ACTIVEBORDER, /* ACTIVE_CAPTION_BORDER */
2850 COLOR_INACTIVECAPTION, /* INACTIVE_CAPTION */
2851 COLOR_INACTIVECAPTIONTEXT, /* INACTIVE_CAPTION_TEXT */
2852 COLOR_INACTIVEBORDER, /* INACTIVE_CAPTION_BORDER */
2853 COLOR_WINDOW, /* WINDOW */
2854 COLOR_WINDOWFRAME, /* WINDOW_BORDER */
2855 COLOR_WINDOWTEXT, /* WINDOW_TEXT */
2856 COLOR_MENU, /* MENU */
2857 COLOR_MENUTEXT, /* MENU_TEXT */
2858 COLOR_WINDOW, /* TEXT */
2859 COLOR_WINDOWTEXT, /* TEXT_TEXT */
2860 COLOR_HIGHLIGHT, /* TEXT_HIGHLIGHT */
2861 COLOR_HIGHLIGHTTEXT, /* TEXT_HIGHLIGHT_TEXT */
2862 COLOR_GRAYTEXT, /* TEXT_INACTIVE_TEXT */
2863 COLOR_3DFACE, /* CONTROL */
2864 COLOR_BTNTEXT, /* CONTROL_TEXT */
2865 COLOR_3DLIGHT, /* CONTROL_HIGHLIGHT */
2866 COLOR_3DHILIGHT, /* CONTROL_LT_HIGHLIGHT */
2867 COLOR_3DSHADOW, /* CONTROL_SHADOW */
2868 COLOR_3DDKSHADOW, /* CONTROL_DK_SHADOW */
2869 COLOR_SCROLLBAR, /* SCROLLBAR */
2870 COLOR_INFOBK, /* INFO */
2871 COLOR_INFOTEXT, /* INFO_TEXT */
2872 };
2873
2874 jint colorLen = env->GetArrayLength(colors);
2875 jint* colorsPtr = NULL;
2876 try {
2877 colorsPtr = (jint *)env->GetPrimitiveArrayCritical(colors, 0);
2878 for (int i = 0; i < (sizeof indexMap)/(sizeof *indexMap) && i < colorLen; i++) {
2879 colorsPtr[i] = DesktopColor2RGB(indexMap[i]);
2880 }
2881 } catch (...) {
2882 if (colorsPtr != NULL) {
2883 env->ReleasePrimitiveArrayCritical(colors, colorsPtr, 0);
2884 }
2885 throw;
2886 }
2887
2888 env->ReleasePrimitiveArrayCritical(colors, colorsPtr, 0);
2889
2890 CATCH_BAD_ALLOC;
2891 }
2892
DSGetComponent(JNIEnv * env,void * platformInfo)2893 extern "C" JNIEXPORT jobject JNICALL DSGetComponent
2894 (JNIEnv* env, void* platformInfo)
2895 {
2896 TRY;
2897
2898 HWND hWnd = (HWND)platformInfo;
2899 if (!::IsWindow(hWnd))
2900 return NULL;
2901
2902 AwtComponent* comp = AwtComponent::GetComponent(hWnd);
2903 if (comp == NULL)
2904 return NULL;
2905
2906 return comp->GetTarget(env);
2907
2908 CATCH_BAD_ALLOC_RET(NULL);
2909 }
2910
2911 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_postDispose(JNIEnv * env,jclass clazz)2912 Java_sun_awt_windows_WToolkit_postDispose(JNIEnv *env, jclass clazz)
2913 {
2914 #ifdef DEBUG
2915 TRY_NO_VERIFY;
2916
2917 // If this method was called, that means runFinalizersOnExit is turned
2918 // on and the VM is exiting cleanly. We should signal the debug memory
2919 // manager to generate a leaks report.
2920 AwtDebugSupport::GenerateLeaksReport();
2921
2922 CATCH_BAD_ALLOC;
2923 #endif
2924 }
2925
2926 /*
2927 * Class: sun_awt_windows_WToolkit
2928 * Method: setDynamicLayoutNative
2929 * Signature: (Z)V
2930 */
2931 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_setDynamicLayoutNative(JNIEnv * env,jobject self,jboolean dynamic)2932 Java_sun_awt_windows_WToolkit_setDynamicLayoutNative(JNIEnv *env,
2933 jobject self, jboolean dynamic)
2934 {
2935 TRY;
2936
2937 AwtToolkit::GetInstance().SetDynamicLayout(dynamic);
2938
2939 CATCH_BAD_ALLOC;
2940 }
2941
2942 /*
2943 * Class: sun_awt_windows_WToolkit
2944 * Method: isDynamicLayoutSupportedNative
2945 * Signature: ()Z
2946 */
2947 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WToolkit_isDynamicLayoutSupportedNative(JNIEnv * env,jobject self)2948 Java_sun_awt_windows_WToolkit_isDynamicLayoutSupportedNative(JNIEnv *env,
2949 jobject self)
2950 {
2951 TRY;
2952
2953 return (jboolean) AwtToolkit::GetInstance().IsDynamicLayoutSupported();
2954
2955 CATCH_BAD_ALLOC_RET(FALSE);
2956 }
2957
2958 /*
2959 * Class: sun_awt_windows_WToolkit
2960 * Method: printWindowsVersion
2961 * Signature: ()Ljava/lang/String;
2962 */
2963 JNIEXPORT jstring JNICALL
Java_sun_awt_windows_WToolkit_getWindowsVersion(JNIEnv * env,jclass cls)2964 Java_sun_awt_windows_WToolkit_getWindowsVersion(JNIEnv *env, jclass cls)
2965 {
2966 TRY;
2967
2968 WCHAR szVer[128];
2969
2970 DWORD version = ::GetVersion();
2971 swprintf(szVer, 128, L"0x%x = %ld", version, version);
2972 int l = lstrlen(szVer);
2973
2974 if (IS_WIN2000) {
2975 if (IS_WINXP) {
2976 if (IS_WINVISTA) {
2977 swprintf(szVer + l, 128, L" (Windows Vista)");
2978 } else {
2979 swprintf(szVer + l, 128, L" (Windows XP)");
2980 }
2981 } else {
2982 swprintf(szVer + l, 128, L" (Windows 2000)");
2983 }
2984 } else {
2985 swprintf(szVer + l, 128, L" (Unknown)");
2986 }
2987
2988 return JNU_NewStringPlatform(env, szVer);
2989
2990 CATCH_BAD_ALLOC_RET(NULL);
2991 }
2992
2993 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_showTouchKeyboard(JNIEnv * env,jobject self,jboolean causedByTouchEvent)2994 Java_sun_awt_windows_WToolkit_showTouchKeyboard(JNIEnv *env, jobject self,
2995 jboolean causedByTouchEvent)
2996 {
2997 AwtToolkit& tk = AwtToolkit::GetInstance();
2998 if (!tk.IsWin8OrLater() || !tk.IsTouchKeyboardAutoShowEnabled()) {
2999 return;
3000 }
3001
3002 if (causedByTouchEvent ||
3003 (tk.IsTouchKeyboardAutoShowSystemEnabled() &&
3004 !tk.IsAnyKeyboardAttached())) {
3005 tk.ShowTouchKeyboard();
3006 }
3007 }
3008
3009 JNIEXPORT void JNICALL
Java_sun_awt_windows_WToolkit_hideTouchKeyboard(JNIEnv * env,jobject self)3010 Java_sun_awt_windows_WToolkit_hideTouchKeyboard(JNIEnv *env, jobject self)
3011 {
3012 AwtToolkit& tk = AwtToolkit::GetInstance();
3013 if (!tk.IsWin8OrLater() || !tk.IsTouchKeyboardAutoShowEnabled()) {
3014 return;
3015 }
3016 tk.HideTouchKeyboard();
3017 }
3018
3019 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WToolkit_syncNativeQueue(JNIEnv * env,jobject self,jlong timeout)3020 Java_sun_awt_windows_WToolkit_syncNativeQueue(JNIEnv *env, jobject self, jlong timeout)
3021 {
3022 if (timeout <= 0) {
3023 return JNI_FALSE;
3024 }
3025 AwtToolkit & tk = AwtToolkit::GetInstance();
3026 DWORD eventNumber = tk.eventNumber;
3027 tk.PostMessage(WM_SYNC_WAIT, 0, 0);
3028 for(long t = 2; t < timeout &&
3029 WAIT_TIMEOUT == ::WaitForSingleObject(tk.m_waitEvent, 2); t+=2) {
3030 if (tk.isInDoDragDropLoop) {
3031 break;
3032 }
3033 }
3034 DWORD newEventNumber = tk.eventNumber;
3035 return (newEventNumber - eventNumber) > 2;
3036 }
3037
3038 } /* extern "C" */
3039
3040 /* Convert a Windows desktop color index into an RGB value. */
DesktopColor2RGB(int colorIndex)3041 COLORREF DesktopColor2RGB(int colorIndex) {
3042 DWORD sysColor = ::GetSysColor(colorIndex);
3043 return ((GetRValue(sysColor)<<16) | (GetGValue(sysColor)<<8) |
3044 (GetBValue(sysColor)) | 0xff000000);
3045 }
3046
3047
3048 /*
3049 * Class: sun_awt_SunToolkit
3050 * Method: closeSplashScreen
3051 * Signature: ()V
3052 */
3053 extern "C" JNIEXPORT void JNICALL
Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv * env,jclass cls)3054 Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv *env, jclass cls)
3055 {
3056 typedef void (*SplashClose_t)();
3057 HMODULE hSplashDll = GetModuleHandle(_T("splashscreen.dll"));
3058 if (!hSplashDll) {
3059 return; // dll not loaded
3060 }
3061 SplashClose_t splashClose = (SplashClose_t)GetProcAddress(hSplashDll,
3062 "SplashClose");
3063 if (splashClose) {
3064 splashClose();
3065 }
3066 }
3067
3068 /*
3069 * accessible from awt_Component
3070 */
areExtraMouseButtonsEnabled()3071 BOOL AwtToolkit::areExtraMouseButtonsEnabled() {
3072 return m_areExtraMouseButtonsEnabled;
3073 }
3074
3075 /*
3076 * Class: sun_awt_windows_WToolkit
3077 * Method: setExtraMouseButtonsEnabledNative
3078 * Signature: (Z)V
3079 */
Java_sun_awt_windows_WToolkit_setExtraMouseButtonsEnabledNative(JNIEnv * env,jclass self,jboolean enable)3080 extern "C" JNIEXPORT void JNICALL Java_sun_awt_windows_WToolkit_setExtraMouseButtonsEnabledNative
3081 (JNIEnv *env, jclass self, jboolean enable){
3082 TRY;
3083 AwtToolkit::GetInstance().setExtraMouseButtonsEnabled(enable);
3084 CATCH_BAD_ALLOC;
3085 }
3086
setExtraMouseButtonsEnabled(BOOL enable)3087 void AwtToolkit::setExtraMouseButtonsEnabled(BOOL enable) {
3088 m_areExtraMouseButtonsEnabled = enable;
3089 }
3090
Java_sun_awt_windows_WToolkit_getNumberOfButtonsImpl(JNIEnv *,jobject self)3091 JNIEXPORT jint JNICALL Java_sun_awt_windows_WToolkit_getNumberOfButtonsImpl
3092 (JNIEnv *, jobject self) {
3093 return AwtToolkit::GetNumberOfButtons();
3094 }
3095
GetNumberOfButtons()3096 UINT AwtToolkit::GetNumberOfButtons() {
3097 return MOUSE_BUTTONS_WINDOWS_SUPPORTED;
3098 }
3099
IsWin8OrLater()3100 bool AwtToolkit::IsWin8OrLater() {
3101 return m_isWin8OrLater;
3102 }
3103
IsTouchKeyboardAutoShowEnabled()3104 bool AwtToolkit::IsTouchKeyboardAutoShowEnabled() {
3105 return m_touchKbrdAutoShowIsEnabled;
3106 }
3107
IsAnyKeyboardAttached()3108 bool AwtToolkit::IsAnyKeyboardAttached() {
3109 UINT numDevs = 0;
3110 UINT numDevsRet = 0;
3111 const UINT devListTypeSize = sizeof(RAWINPUTDEVICELIST);
3112 if ((::GetRawInputDeviceList(NULL, &numDevs, devListTypeSize) != 0) ||
3113 (numDevs == 0)) {
3114 return false;
3115 }
3116
3117 RAWINPUTDEVICELIST* pDevList = new RAWINPUTDEVICELIST[numDevs];
3118 while (((numDevsRet = ::GetRawInputDeviceList(pDevList, &numDevs,
3119 devListTypeSize)) == (UINT)-1) &&
3120 (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
3121 if (pDevList != NULL) {
3122 delete[] pDevList;
3123 }
3124 pDevList = new RAWINPUTDEVICELIST[numDevs];
3125 }
3126
3127 bool keyboardIsAttached = false;
3128 if (numDevsRet != (UINT)-1) {
3129 for (UINT i = 0; i < numDevsRet; i++) {
3130 if (pDevList[i].dwType == RIM_TYPEKEYBOARD) {
3131 keyboardIsAttached = true;
3132 break;
3133 }
3134 }
3135 }
3136
3137 if (pDevList != NULL) {
3138 delete[] pDevList;
3139 }
3140 return keyboardIsAttached;
3141 }
3142
IsTouchKeyboardAutoShowSystemEnabled()3143 bool AwtToolkit::IsTouchKeyboardAutoShowSystemEnabled() {
3144 const TCHAR tabTipKeyName[] = _T("SOFTWARE\\Microsoft\\TabletTip\\1.7");
3145 HKEY hTabTipKey = NULL;
3146 if (::RegOpenKeyEx(HKEY_CURRENT_USER, tabTipKeyName, 0, KEY_READ,
3147 &hTabTipKey) != ERROR_SUCCESS) {
3148 return false;
3149 }
3150
3151 const TCHAR enableAutoInvokeValName[] = _T("EnableDesktopModeAutoInvoke");
3152 DWORD keyValType = 0;
3153 bool autoShowIsEnabled = false;
3154 if (::RegQueryValueEx(hTabTipKey, enableAutoInvokeValName, NULL,
3155 &keyValType, NULL, NULL) == ERROR_SUCCESS) {
3156 if (keyValType == REG_DWORD) {
3157 DWORD enableAutoInvokeVal = 0;
3158 DWORD bytesCopied = sizeof(DWORD);
3159 if (::RegQueryValueEx(hTabTipKey, enableAutoInvokeValName, NULL,
3160 NULL, (LPBYTE)(DWORD*)&enableAutoInvokeVal,
3161 &bytesCopied) == ERROR_SUCCESS) {
3162 autoShowIsEnabled = (enableAutoInvokeVal == 0 ? false : true);
3163 }
3164 }
3165 }
3166
3167 if (hTabTipKey != NULL) {
3168 ::RegCloseKey(hTabTipKey);
3169 }
3170 return autoShowIsEnabled;
3171 }
3172
ShowTouchKeyboard()3173 void AwtToolkit::ShowTouchKeyboard() {
3174 if (m_isWin8OrLater && m_touchKbrdAutoShowIsEnabled &&
3175 (m_touchKbrdExeFilePath != NULL)) {
3176 int retVal = (int)((intptr_t)::ShellExecute(NULL, _T("open"),
3177 m_touchKbrdExeFilePath, NULL, NULL, SW_SHOW));
3178 if (retVal <= 32) {
3179 DTRACE_PRINTLN1("AwtToolkit::ShowTouchKeyboard: Failed"
3180 ", retVal='%d'", retVal);
3181 }
3182 }
3183 }
3184
HideTouchKeyboard()3185 void AwtToolkit::HideTouchKeyboard() {
3186 if (m_isWin8OrLater && m_touchKbrdAutoShowIsEnabled) {
3187 HWND hwnd = GetTouchKeyboardWindow();
3188 if (hwnd != NULL) {
3189 ::PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
3190 }
3191 }
3192 }
3193
TIRegisterTouchWindow(HWND hWnd,ULONG ulFlags)3194 BOOL AwtToolkit::TIRegisterTouchWindow(HWND hWnd, ULONG ulFlags) {
3195 if (m_pRegisterTouchWindow == NULL) {
3196 return FALSE;
3197 }
3198 return m_pRegisterTouchWindow(hWnd, ulFlags);
3199 }
3200
TIGetTouchInputInfo(HTOUCHINPUT hTouchInput,UINT cInputs,PTOUCHINPUT pInputs,int cbSize)3201 BOOL AwtToolkit::TIGetTouchInputInfo(HTOUCHINPUT hTouchInput,
3202 UINT cInputs, PTOUCHINPUT pInputs, int cbSize) {
3203 if (m_pGetTouchInputInfo == NULL) {
3204 return FALSE;
3205 }
3206 return m_pGetTouchInputInfo(hTouchInput, cInputs, pInputs, cbSize);
3207 }
3208
TICloseTouchInputHandle(HTOUCHINPUT hTouchInput)3209 BOOL AwtToolkit::TICloseTouchInputHandle(HTOUCHINPUT hTouchInput) {
3210 if (m_pCloseTouchInputHandle == NULL) {
3211 return FALSE;
3212 }
3213 return m_pCloseTouchInputHandle(hTouchInput);
3214 }
3215
3216 /*
3217 * The fuction intended for access to an IME API. It posts IME message to the queue and
3218 * waits untill the message processing is completed.
3219 *
3220 * On Windows 10 the IME may process the messages send via SenMessage() from other threads
3221 * when the IME is called by TranslateMessage(). This may cause an reentrancy issue when
3222 * the windows procedure processing the sent message call an IME function and leaves
3223 * the IME functionality in an unexpected state.
3224 * This function avoids reentrancy issue and must be used for sending of all IME messages
3225 * instead of SendMessage().
3226 */
InvokeInputMethodFunction(UINT msg,WPARAM wParam,LPARAM lParam)3227 LRESULT AwtToolkit::InvokeInputMethodFunction(UINT msg, WPARAM wParam, LPARAM lParam) {
3228 /*
3229 * DND runs on the main thread. So it is necessary to use SendMessage() to call an IME
3230 * function once the DND is active; otherwise a hang is possible since DND may wait for
3231 * the IME completion.
3232 */
3233 CriticalSection::Lock lock(m_inputMethodLock);
3234 if (isInDoDragDropLoop) {
3235 SendMessage(msg, wParam, lParam);
3236 ::ResetEvent(m_inputMethodWaitEvent);
3237 return m_inputMethodData;
3238 } else {
3239 if (PostMessage(msg, wParam, lParam)) {
3240 ::WaitForSingleObject(m_inputMethodWaitEvent, INFINITE);
3241 return m_inputMethodData;
3242 }
3243 return 0;
3244 }
3245 }
3246
3247