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