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