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