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