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