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