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