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