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