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