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