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