1 /* 2 * Copyright (c) 1996, 2017, 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 #include "awt.h" 27 28 #include <windowsx.h> 29 #include <zmouse.h> 30 31 #include "jlong.h" 32 #include "awt_AWTEvent.h" 33 #include "awt_BitmapUtil.h" 34 #include "awt_Component.h" 35 #include "awt_Cursor.h" 36 #include "awt_Dimension.h" 37 #include "awt_Frame.h" 38 #include "awt_InputEvent.h" 39 #include "awt_InputTextInfor.h" 40 #include "awt_Insets.h" 41 #include "awt_KeyEvent.h" 42 #include "awt_MenuItem.h" 43 #include "awt_MouseEvent.h" 44 #include "awt_Palette.h" 45 #include "awt_Toolkit.h" 46 #include "awt_Window.h" 47 #include "awt_Win32GraphicsDevice.h" 48 #include "Hashtable.h" 49 #include "ComCtl32Util.h" 50 51 #include <Region.h> 52 53 #include <jawt.h> 54 55 #include <java_awt_Toolkit.h> 56 #include <java_awt_FontMetrics.h> 57 #include <java_awt_Color.h> 58 #include <java_awt_Event.h> 59 #include <java_awt_event_KeyEvent.h> 60 #include <java_awt_Insets.h> 61 #include <sun_awt_windows_WPanelPeer.h> 62 #include <java_awt_event_InputEvent.h> 63 #include <java_awt_event_ActionEvent.h> 64 #include <java_awt_event_InputMethodEvent.h> 65 #include <sun_awt_windows_WInputMethod.h> 66 #include <java_awt_event_MouseEvent.h> 67 #include <java_awt_event_MouseWheelEvent.h> 68 69 // Begin -- Win32 SDK include files 70 #include <imm.h> 71 #include <ime.h> 72 // End -- Win32 SDK include files 73 74 #include <awt_DnDDT.h> 75 76 LPCTSTR szAwtComponentClassName = TEXT("SunAwtComponent"); 77 // register a message that no other window in the process (even in a plugin 78 // scenario) will be using 79 const UINT AwtComponent::WmAwtIsComponent = 80 ::RegisterWindowMessage(szAwtComponentClassName); 81 82 static HWND g_hwndDown = NULL; 83 static DCList activeDCList; 84 static DCList passiveDCList; 85 86 extern void CheckFontSmoothingSettings(HWND); 87 88 extern "C" { 89 // Remember the input language has changed by some user's action 90 // (Alt+Shift or through the language icon on the Taskbar) to control the 91 // race condition between the toolkit thread and the AWT event thread. 92 // This flag remains TRUE until the next WInputMethod.getNativeLocale() is 93 // issued. 94 BOOL g_bUserHasChangedInputLang = FALSE; 95 } 96 97 BOOL AwtComponent::sm_suppressFocusAndActivation = FALSE; 98 BOOL AwtComponent::sm_restoreFocusAndActivation = FALSE; 99 HWND AwtComponent::sm_focusOwner = NULL; 100 HWND AwtComponent::sm_focusedWindow = NULL; 101 BOOL AwtComponent::sm_bMenuLoop = FALSE; 102 BOOL AwtComponent::sm_inSynthesizeFocus = FALSE; 103 104 /************************************************************************/ 105 // Struct for _Reshape() and ReshapeNoCheck() methods 106 struct ReshapeStruct { 107 jobject component; 108 jint x, y; 109 jint w, h; 110 }; 111 // Struct for _NativeHandleEvent() method 112 struct NativeHandleEventStruct { 113 jobject component; 114 jobject event; 115 }; 116 // Struct for _SetForeground() and _SetBackground() methods 117 struct SetColorStruct { 118 jobject component; 119 jint rgb; 120 }; 121 // Struct for _SetFont() method 122 struct SetFontStruct { 123 jobject component; 124 jobject font; 125 }; 126 // Struct for _CreatePrintedPixels() method 127 struct CreatePrintedPixelsStruct { 128 jobject component; 129 int srcx, srcy; 130 int srcw, srch; 131 jint alpha; 132 }; 133 // Struct for _SetRectangularShape() method 134 struct SetRectangularShapeStruct { 135 jobject component; 136 jint x1, x2, y1, y2; 137 jobject region; 138 }; 139 // Struct for _GetInsets function 140 struct GetInsetsStruct { 141 jobject window; 142 RECT *insets; 143 }; 144 // Struct for _SetZOrder function 145 struct SetZOrderStruct { 146 jobject component; 147 jlong above; 148 }; 149 // Struct for _SetFocus function 150 struct SetFocusStruct { 151 jobject component; 152 jboolean doSetFocus; 153 }; 154 /************************************************************************/ 155 156 ////////////////////////////////////////////////////////////////////////// 157 158 /************************************************************************* 159 * AwtComponent fields 160 */ 161 162 163 jfieldID AwtComponent::peerID; 164 jfieldID AwtComponent::xID; 165 jfieldID AwtComponent::yID; 166 jfieldID AwtComponent::widthID; 167 jfieldID AwtComponent::heightID; 168 jfieldID AwtComponent::visibleID; 169 jfieldID AwtComponent::backgroundID; 170 jfieldID AwtComponent::foregroundID; 171 jfieldID AwtComponent::enabledID; 172 jfieldID AwtComponent::parentID; 173 jfieldID AwtComponent::graphicsConfigID; 174 jfieldID AwtComponent::peerGCID; 175 jfieldID AwtComponent::focusableID; 176 jfieldID AwtComponent::appContextID; 177 jfieldID AwtComponent::cursorID; 178 jfieldID AwtComponent::hwndID; 179 180 jmethodID AwtComponent::getFontMID; 181 jmethodID AwtComponent::getToolkitMID; 182 jmethodID AwtComponent::isEnabledMID; 183 jmethodID AwtComponent::getLocationOnScreenMID; 184 jmethodID AwtComponent::replaceSurfaceDataMID; 185 jmethodID AwtComponent::replaceSurfaceDataLaterMID; 186 jmethodID AwtComponent::disposeLaterMID; 187 188 HKL AwtComponent::m_hkl = ::GetKeyboardLayout(0); 189 LANGID AwtComponent::m_idLang = LOWORD(::GetKeyboardLayout(0)); 190 UINT AwtComponent::m_CodePage 191 = AwtComponent::LangToCodePage(m_idLang); 192 193 jint *AwtComponent::masks; 194 195 static BOOL bLeftShiftIsDown = false; 196 static BOOL bRightShiftIsDown = false; 197 static UINT lastShiftKeyPressed = 0; // init to safe value 198 199 // Added by waleed to initialize the RTL Flags 200 BOOL AwtComponent::sm_rtl = PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC || 201 PRIMARYLANGID(GetInputLanguage()) == LANG_HEBREW; 202 BOOL AwtComponent::sm_rtlReadingOrder = 203 PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC; 204 205 BOOL AwtComponent::sm_PrimaryDynamicTableBuilt = FALSE; 206 207 HWND AwtComponent::sm_cursorOn; 208 BOOL AwtComponent::m_QueryNewPaletteCalled = FALSE; 209 210 CriticalSection windowMoveLock; 211 BOOL windowMoveLockHeld = FALSE; 212 213 /************************************************************************ 214 * AwtComponent methods 215 */ 216 217 AwtComponent::AwtComponent() 218 { 219 m_mouseButtonClickAllowed = 0; 220 m_touchDownOccurred = FALSE; 221 m_touchUpOccurred = FALSE; 222 m_touchDownPoint.x = m_touchDownPoint.y = 0; 223 m_touchUpPoint.x = m_touchUpPoint.y = 0; 224 m_callbacksEnabled = FALSE; 225 m_hwnd = NULL; 226 227 m_colorForeground = 0; 228 m_colorBackground = 0; 229 m_backgroundColorSet = FALSE; 230 m_penForeground = NULL; 231 m_brushBackground = NULL; 232 m_DefWindowProc = NULL; 233 m_nextControlID = 1; 234 m_childList = NULL; 235 m_myControlID = 0; 236 m_hdwp = NULL; 237 m_validationNestCount = 0; 238 239 m_dropTarget = NULL; 240 241 m_InputMethod = NULL; 242 m_useNativeCompWindow = TRUE; 243 m_PendingLeadByte = 0; 244 m_bitsCandType = 0; 245 246 windowMoveLockPosX = 0; 247 windowMoveLockPosY = 0; 248 windowMoveLockPosCX = 0; 249 windowMoveLockPosCY = 0; 250 251 m_hCursorCache = NULL; 252 253 m_bSubclassed = FALSE; 254 m_bPauseDestroy = FALSE; 255 256 m_MessagesProcessing = 0; 257 m_wheelRotationAmountX = 0; 258 m_wheelRotationAmountY = 0; 259 if (!sm_PrimaryDynamicTableBuilt) { 260 // do it once. 261 AwtComponent::BuildPrimaryDynamicTable(); 262 sm_PrimaryDynamicTableBuilt = TRUE; 263 } 264 265 deadKeyActive = FALSE; 266 } 267 268 AwtComponent::~AwtComponent() 269 { 270 DASSERT(AwtToolkit::IsMainThread()); 271 272 /* Disconnect all links. */ 273 UnlinkObjects(); 274 275 /* 276 * All the messages for this component are processed, native 277 * resources are freed, and Java object is not connected to 278 * the native one anymore. So we can safely destroy component's 279 * handle. 280 */ 281 DestroyHWnd(); 282 } 283 284 void AwtComponent::Dispose() 285 { 286 // NOTE: in case the component/toplevel was focused, Java should 287 // have already taken care of proper transferring it or clearing. 288 289 if (m_hdwp != NULL) { 290 // end any deferred window positioning, regardless 291 // of m_validationNestCount 292 ::EndDeferWindowPos(m_hdwp); 293 } 294 295 // Send final message to release all DCs associated with this component 296 SendMessage(WM_AWT_RELEASE_ALL_DCS); 297 298 /* Stop message filtering. */ 299 UnsubclassHWND(); 300 301 /* Release global ref to input method */ 302 SetInputMethod(NULL, TRUE); 303 304 if (m_childList != NULL) 305 delete m_childList; 306 307 DestroyDropTarget(); 308 ReleaseDragCapture(0); 309 310 if (m_myControlID != 0) { 311 AwtComponent* parent = GetParent(); 312 if (parent != NULL) 313 parent->RemoveChild(m_myControlID); 314 } 315 316 ::RemoveProp(GetHWnd(), DrawingStateProp); 317 318 /* Release any allocated resources. */ 319 if (m_penForeground != NULL) { 320 m_penForeground->Release(); 321 m_penForeground = NULL; 322 } 323 if (m_brushBackground != NULL) { 324 m_brushBackground->Release(); 325 m_brushBackground = NULL; 326 } 327 328 if (m_bPauseDestroy) { 329 // AwtComponent::WmNcDestroy could be released now 330 m_bPauseDestroy = FALSE; 331 m_hwnd = NULL; 332 } 333 334 // The component instance is deleted using AwtObject::Dispose() method 335 AwtObject::Dispose(); 336 } 337 338 /* store component pointer in window extra bytes */ 339 void AwtComponent::SetComponentInHWND() { 340 DASSERT(::GetWindowLongPtr(GetHWnd(), GWLP_USERDATA) == NULL); 341 ::SetWindowLongPtr(GetHWnd(), GWLP_USERDATA, (LONG_PTR)this); 342 } 343 344 /* 345 * static function to get AwtComponent pointer from hWnd -- 346 * you don't want to call this from inside a wndproc to avoid 347 * infinite recursion 348 */ 349 AwtComponent* AwtComponent::GetComponent(HWND hWnd) { 350 // Requests for Toolkit hwnd resolution happen pretty often. Check first. 351 if (hWnd == AwtToolkit::GetInstance().GetHWnd()) { 352 return NULL; 353 } 354 355 // check that it's an AWT component from the same toolkit as the caller 356 if (::IsWindow(hWnd) && 357 AwtToolkit::MainThread() == ::GetWindowThreadProcessId(hWnd, NULL)) 358 { 359 DASSERT(WmAwtIsComponent != 0); 360 if (::SendMessage(hWnd, WmAwtIsComponent, 0, 0L)) { 361 return GetComponentImpl(hWnd); 362 } 363 } 364 return NULL; 365 } 366 367 /* 368 * static function to get AwtComponent pointer from hWnd-- 369 * different from GetComponent because caller knows the 370 * hwnd is an AWT component hwnd 371 */ 372 AwtComponent* AwtComponent::GetComponentImpl(HWND hWnd) { 373 AwtComponent *component = 374 (AwtComponent *)::GetWindowLongPtr(hWnd, GWLP_USERDATA); 375 DASSERT(!component || !IsBadReadPtr(component, sizeof(AwtComponent)) ); 376 DASSERT(!component || component->GetHWnd() == hWnd ); 377 return component; 378 } 379 380 /* 381 * Single window proc for all the components. Delegates real work to 382 * the component's WindowProc() member function. 383 */ 384 LRESULT CALLBACK AwtComponent::WndProc(HWND hWnd, UINT message, 385 WPARAM wParam, LPARAM lParam) 386 { 387 TRY; 388 389 AwtComponent * self = AwtComponent::GetComponentImpl(hWnd); 390 if (self == NULL || self->GetHWnd() != hWnd || 391 message == WM_UNDOCUMENTED_CLIENTSHUTDOWN) // handle log-off gracefully 392 { 393 return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam); 394 } else { 395 return self->WindowProc(message, wParam, lParam); 396 } 397 398 CATCH_BAD_ALLOC_RET(0); 399 } 400 401 BOOL AwtComponent::IsFocusable() { 402 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 403 jobject peer = GetPeer(env); 404 jobject target = env->GetObjectField(peer, AwtObject::targetID); 405 BOOL res = env->GetBooleanField(target, focusableID); 406 AwtWindow *pCont = GetContainer(); 407 if (pCont) { 408 res &= pCont->IsFocusableWindow(); 409 } 410 env->DeleteLocalRef(target); 411 return res; 412 } 413 414 /************************************************************************ 415 * AwtComponent dynamic methods 416 * 417 * Window class registration routines 418 */ 419 420 /* 421 * Fix for 4964237: Win XP: Changing theme changes java dialogs title icon 422 */ 423 void AwtComponent::FillClassInfo(WNDCLASSEX *lpwc) 424 { 425 lpwc->cbSize = sizeof(WNDCLASSEX); 426 lpwc->style = 0L;//CS_OWNDC; 427 lpwc->lpfnWndProc = (WNDPROC)::DefWindowProc; 428 lpwc->cbClsExtra = 0; 429 lpwc->cbWndExtra = 0; 430 lpwc->hInstance = AwtToolkit::GetInstance().GetModuleHandle(), 431 lpwc->hIcon = AwtToolkit::GetInstance().GetAwtIcon(); 432 lpwc->hCursor = NULL; 433 lpwc->hbrBackground = NULL; 434 lpwc->lpszMenuName = NULL; 435 lpwc->lpszClassName = GetClassName(); 436 //Fixed 6233560: PIT: Java Cup Logo on the title bar of top-level windows look blurred, Win32 437 lpwc->hIconSm = AwtToolkit::GetInstance().GetAwtIconSm(); 438 } 439 440 void AwtComponent::RegisterClass() 441 { 442 WNDCLASSEX wc; 443 if (!::GetClassInfoEx(AwtToolkit::GetInstance().GetModuleHandle(), GetClassName(), &wc)) { 444 FillClassInfo(&wc); 445 ATOM ret = ::RegisterClassEx(&wc); 446 DASSERT(ret != 0); 447 } 448 } 449 450 void AwtComponent::UnregisterClass() 451 { 452 ::UnregisterClass(GetClassName(), AwtToolkit::GetInstance().GetModuleHandle()); 453 } 454 455 /* 456 * Copy the graphicsConfig reference from Component into WComponentPeer 457 */ 458 void AwtComponent::InitPeerGraphicsConfig(JNIEnv *env, jobject peer) 459 { 460 jobject target = env->GetObjectField(peer, AwtObject::targetID); 461 //Get graphicsConfig object ref from Component 462 jobject compGC = env->GetObjectField(target, 463 AwtComponent::graphicsConfigID); 464 465 //Set peer's graphicsConfig to Component's graphicsConfig 466 if (compGC != NULL) { 467 jclass win32GCCls = env->FindClass("sun/awt/Win32GraphicsConfig"); 468 DASSERT(win32GCCls != NULL); 469 DASSERT(env->IsInstanceOf(compGC, win32GCCls)); 470 if (win32GCCls == NULL) { 471 throw std::bad_alloc(); 472 } 473 env->SetObjectField(peer, AwtComponent::peerGCID, compGC); 474 } 475 } 476 477 void 478 AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title, 479 DWORD windowStyle, 480 DWORD windowExStyle, 481 int x, int y, int w, int h, 482 HWND hWndParent, HMENU hMenu, 483 COLORREF colorForeground, 484 COLORREF colorBackground, 485 jobject peer) 486 { 487 if (env->EnsureLocalCapacity(2) < 0) { 488 return; 489 } 490 491 /* 492 * The window class of multifont label must be "BUTTON" because 493 * "STATIC" class can't get WM_DRAWITEM message, and m_peerObject 494 * member is referred in the GetClassName method of AwtLabel class. 495 * So m_peerObject member must be set here. 496 */ 497 if (m_peerObject == NULL) { 498 m_peerObject = env->NewGlobalRef(peer); 499 } else { 500 assert(env->IsSameObject(m_peerObject, peer)); 501 } 502 503 RegisterClass(); 504 505 jobject target = env->GetObjectField(peer, AwtObject::targetID); 506 jboolean visible = env->GetBooleanField(target, AwtComponent::visibleID); 507 m_visible = visible; 508 509 if (visible) { 510 windowStyle |= WS_VISIBLE; 511 } else { 512 windowStyle &= ~WS_VISIBLE; 513 } 514 515 InitPeerGraphicsConfig(env, peer); 516 517 SetLastError(0); 518 HWND hwnd = ::CreateWindowEx(windowExStyle, 519 GetClassName(), 520 title, 521 windowStyle, 522 x, y, w, h, 523 hWndParent, 524 hMenu, 525 AwtToolkit::GetInstance().GetModuleHandle(), 526 NULL); 527 528 // fix for 5088782 529 // check if CreateWindowsEx() returns not null value and if it does - 530 // create an InternalError or OutOfMemoryError based on GetLastError(). 531 // This error is set to createError field of WObjectPeer and then 532 // checked and thrown in WComponentPeer constructor. We can't throw an 533 // error here because this code is invoked on Toolkit thread 534 if (hwnd == NULL) 535 { 536 DWORD dw = ::GetLastError(); 537 jobject createError = NULL; 538 if (dw == ERROR_OUTOFMEMORY) 539 { 540 jstring errorMsg = JNU_NewStringPlatform(env, L"too many window handles"); 541 if (errorMsg == NULL || env->ExceptionCheck()) { 542 env->ExceptionClear(); 543 createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "()V"); 544 } else { 545 createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", 546 "(Ljava/lang/String;)V", 547 errorMsg); 548 env->DeleteLocalRef(errorMsg); 549 } 550 } 551 else 552 { 553 TCHAR *buf; 554 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 555 NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 556 (LPTSTR)&buf, 0, NULL); 557 jstring s = JNU_NewStringPlatform(env, buf); 558 if (s == NULL || env->ExceptionCheck()) { 559 env->ExceptionClear(); 560 createError = JNU_NewObjectByName(env, "java/lang/InternalError", "()V"); 561 } else { 562 createError = JNU_NewObjectByName(env, "java/lang/InternalError", 563 "(Ljava/lang/String;)V", s); 564 env->DeleteLocalRef(s); 565 } 566 LocalFree(buf); 567 } 568 if (createError != NULL) { 569 env->SetObjectField(peer, AwtObject::createErrorID, createError); 570 env->DeleteLocalRef(createError); 571 } 572 env->DeleteLocalRef(target); 573 return; 574 } 575 576 m_hwnd = hwnd; 577 578 ::ImmAssociateContext(m_hwnd, NULL); 579 580 SetDrawState((jint)JAWT_LOCK_SURFACE_CHANGED | 581 (jint)JAWT_LOCK_BOUNDS_CHANGED | 582 (jint)JAWT_LOCK_CLIP_CHANGED); 583 584 LinkObjects(env, peer); 585 586 /* Subclass the window now so that we can snoop on its messages */ 587 SubclassHWND(); 588 589 AwtToolkit& tk = AwtToolkit::GetInstance(); 590 if (tk.IsWin8OrLater() && tk.IsTouchKeyboardAutoShowEnabled()) { 591 tk.TIRegisterTouchWindow(GetHWnd(), TWF_WANTPALM); 592 } 593 594 /* 595 * Fix for 4046446. 596 */ 597 SetWindowPos(GetHWnd(), 0, x, y, w, h, SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOACTIVATE); 598 599 /* Set default colors. */ 600 m_colorForeground = colorForeground; 601 m_colorBackground = colorBackground; 602 603 /* 604 * Only set background color if the color is actually set on the 605 * target -- this avoids inheriting a parent's color unnecessarily, 606 * and has to be done here because there isn't an API to get the 607 * real background color from outside the AWT package. 608 */ 609 jobject bkgrd = env->GetObjectField(target, AwtComponent::backgroundID) ; 610 if (bkgrd != NULL) { 611 JNU_CallMethodByName(env, NULL, peer, "setBackground", 612 "(Ljava/awt/Color;)V", bkgrd); 613 DASSERT(!safe_ExceptionOccurred(env)); 614 } 615 env->DeleteLocalRef(target); 616 env->DeleteLocalRef(bkgrd); 617 } 618 619 /* 620 * Destroy this window's HWND 621 */ 622 void AwtComponent::DestroyHWnd() { 623 if (m_hwnd != NULL) { 624 AwtToolkit::DestroyComponentHWND(m_hwnd); 625 //AwtToolkit::DestroyComponent(this); 626 m_hwnd = NULL; 627 } 628 } 629 630 /* 631 * Returns hwnd for target on non Toolkit thread 632 */ 633 HWND 634 AwtComponent::GetHWnd(JNIEnv* env, jobject target) { 635 if (JNU_IsNull(env, target)) { 636 return 0; 637 } 638 jobject peer = env->GetObjectField(target, AwtComponent::peerID); 639 if (JNU_IsNull(env, peer)) { 640 return 0; 641 } 642 HWND hwnd = reinterpret_cast<HWND>(static_cast<LONG_PTR> ( 643 env->GetLongField(peer, AwtComponent::hwndID))); 644 env->DeleteLocalRef(peer); 645 return hwnd; 646 } 647 // 648 // Propagate the background color to synchronize Java field and peer's field. 649 // This is needed to fix 4148334 650 // 651 void AwtComponent::UpdateBackground(JNIEnv *env, jobject target) 652 { 653 if (env->EnsureLocalCapacity(1) < 0) { 654 return; 655 } 656 657 jobject bkgrnd = env->GetObjectField(target, AwtComponent::backgroundID); 658 659 if (bkgrnd == NULL) { 660 bkgrnd = JNU_NewObjectByName(env, "java/awt/Color", "(III)V", 661 GetRValue(m_colorBackground), 662 GetGValue(m_colorBackground), 663 GetBValue(m_colorBackground)); 664 if (bkgrnd != NULL) { 665 env->SetObjectField(target, AwtComponent::backgroundID, bkgrnd); 666 } 667 } 668 env->DeleteLocalRef(bkgrnd); 669 } 670 671 /* 672 * Install our window proc as the proc for our HWND, and save off the 673 * previous proc as the default 674 */ 675 void AwtComponent::SubclassHWND() 676 { 677 if (m_bSubclassed) { 678 return; 679 } 680 const WNDPROC wndproc = WndProc; // let compiler type check WndProc 681 m_DefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(GetHWnd(), wndproc); 682 m_bSubclassed = TRUE; 683 } 684 685 /* 686 * Reinstall the original window proc as the proc for our HWND 687 */ 688 void AwtComponent::UnsubclassHWND() 689 { 690 if (!m_bSubclassed) { 691 return; 692 } 693 ComCtl32Util::GetInstance().UnsubclassHWND(GetHWnd(), WndProc, m_DefWindowProc); 694 m_bSubclassed = FALSE; 695 } 696 697 ///////////////////////////////////// 698 // (static method) 699 // Determines the top-level ancestor for a given window. If the given 700 // window is a top-level window, return itself. 701 // 702 // 'Top-level' includes dialogs as well. 703 // 704 HWND AwtComponent::GetTopLevelParentForWindow(HWND hwndDescendant) { 705 if (hwndDescendant == NULL) { 706 return NULL; 707 } 708 709 DASSERT(IsWindow(hwndDescendant)); 710 HWND hwnd = hwndDescendant; 711 for(;;) { 712 DWORD style = ::GetWindowLong(hwnd, GWL_STYLE); 713 // a) found a non-child window so terminate 714 // b) found real toplevel window (e.g. EmbeddedFrame 715 // that is child though) 716 if ( (style & WS_CHILD) == 0 || 717 AwtComponent::IsTopLevelHWnd(hwnd) ) 718 { 719 break; 720 } 721 hwnd = ::GetParent(hwnd); 722 } 723 724 return hwnd; 725 } 726 //////////////////// 727 728 jobject AwtComponent::FindHeavyweightUnderCursor(BOOL useCache) { 729 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 730 if (env->EnsureLocalCapacity(1) < 0) { 731 return NULL; 732 } 733 734 HWND hit = NULL; 735 POINT p = { 0, 0 }; 736 AwtComponent *comp = NULL; 737 738 if (useCache) { 739 if (sm_cursorOn == NULL) { 740 return NULL; 741 } 742 743 744 DASSERT(::IsWindow(sm_cursorOn)); 745 VERIFY(::GetCursorPos(&p)); 746 /* 747 * Fix for BugTraq ID 4304024. 748 * Allow a non-default cursor only for the client area. 749 */ 750 comp = AwtComponent::GetComponent(sm_cursorOn); 751 if (comp != NULL && 752 ::SendMessage(sm_cursorOn, WM_NCHITTEST, 0, 753 MAKELPARAM(p.x, p.y)) == HTCLIENT) { 754 goto found; 755 } 756 } 757 758 ::GetCursorPos(&p); 759 hit = ::WindowFromPoint(p); 760 while (hit != NULL) { 761 comp = AwtComponent::GetComponent(hit); 762 763 if (comp != NULL) { 764 INT nHittest = (INT)::SendMessage(hit, WM_NCHITTEST, 765 0, MAKELPARAM(p.x, p.y)); 766 /* 767 * Fix for BugTraq ID 4304024. 768 * Allow a non-default cursor only for the client area. 769 */ 770 if (nHittest != HTCLIENT) { 771 /* 772 * When over the non-client area, send WM_SETCURSOR 773 * to revert the cursor to an arrow. 774 */ 775 ::SendMessage(hit, WM_SETCURSOR, (WPARAM)hit, 776 MAKELPARAM(nHittest, WM_MOUSEMOVE)); 777 return NULL; 778 } else { 779 sm_cursorOn = hit; 780 goto found; 781 } 782 } 783 784 if ((::GetWindowLong(hit, GWL_STYLE) & WS_CHILD) == 0) { 785 return NULL; 786 } 787 hit = ::GetParent(hit); 788 } 789 790 return NULL; 791 792 found: 793 jobject localRef = comp->GetTarget(env); 794 jobject globalRef = env->NewGlobalRef(localRef); 795 env->DeleteLocalRef(localRef); 796 return globalRef; 797 } 798 799 void AwtComponent::SetColor(COLORREF c) 800 { 801 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); 802 int grayscale = AwtWin32GraphicsDevice::GetGrayness(screen); 803 if (grayscale != GS_NOTGRAY) { 804 int g; 805 806 g = (int) (.299 * (c & 0xFF) + .587 * ((c >> 8) & 0xFF) + 807 .114 * ((c >> 16) & 0xFF) + 0.5); 808 // c = g | (g << 8) | (g << 16); 809 c = PALETTERGB(g, g, g); 810 } 811 812 if (m_colorForeground == c) { 813 return; 814 } 815 816 m_colorForeground = c; 817 if (m_penForeground != NULL) { 818 m_penForeground->Release(); 819 m_penForeground = NULL; 820 } 821 VERIFY(::InvalidateRect(GetHWnd(), NULL, FALSE)); 822 } 823 824 void AwtComponent::SetBackgroundColor(COLORREF c) 825 { 826 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); 827 int grayscale = AwtWin32GraphicsDevice::GetGrayness(screen); 828 if (grayscale != GS_NOTGRAY) { 829 int g; 830 831 g = (int) (.299 * (c & 0xFF) + .587 * ((c >> 8) & 0xFF) + 832 .114 * ((c >> 16) & 0xFF) + 0.5); 833 // c = g | (g << 8) | (g << 16); 834 c = PALETTERGB(g, g, g); 835 } 836 837 if (m_colorBackground == c) { 838 return; 839 } 840 m_colorBackground = c; 841 m_backgroundColorSet = TRUE; 842 if (m_brushBackground != NULL) { 843 m_brushBackground->Release(); 844 m_brushBackground = NULL; 845 } 846 VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE)); 847 } 848 849 HPEN AwtComponent::GetForegroundPen() 850 { 851 if (m_penForeground == NULL) { 852 m_penForeground = AwtPen::Get(m_colorForeground); 853 } 854 return (HPEN)m_penForeground->GetHandle(); 855 } 856 857 COLORREF AwtComponent::GetBackgroundColor() 858 { 859 if (m_backgroundColorSet == FALSE) { 860 AwtComponent* c = this; 861 while ((c = c->GetParent()) != NULL) { 862 if (c->IsBackgroundColorSet()) { 863 return c->GetBackgroundColor(); 864 } 865 } 866 } 867 return m_colorBackground; 868 } 869 870 HBRUSH AwtComponent::GetBackgroundBrush() 871 { 872 if (m_backgroundColorSet == FALSE) { 873 if (m_brushBackground != NULL) { 874 m_brushBackground->Release(); 875 m_brushBackground = NULL; 876 } 877 AwtComponent* c = this; 878 while ((c = c->GetParent()) != NULL) { 879 if (c->IsBackgroundColorSet()) { 880 m_brushBackground = 881 AwtBrush::Get(c->GetBackgroundColor()); 882 break; 883 } 884 } 885 } 886 if (m_brushBackground == NULL) { 887 m_brushBackground = AwtBrush::Get(m_colorBackground); 888 } 889 return (HBRUSH)m_brushBackground->GetHandle(); 890 } 891 892 void AwtComponent::SetFont(AwtFont* font) 893 { 894 DASSERT(font != NULL); 895 if (font->GetAscent() < 0) { 896 AwtFont::SetupAscent(font); 897 } 898 SendMessage(WM_SETFONT, (WPARAM)font->GetHFont(), MAKELPARAM(FALSE, 0)); 899 VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE)); 900 } 901 902 AwtComponent* AwtComponent::GetParent() 903 { 904 HWND hwnd = ::GetParent(GetHWnd()); 905 if (hwnd == NULL) { 906 return NULL; 907 } 908 return GetComponent(hwnd); 909 } 910 911 AwtWindow* AwtComponent::GetContainer() 912 { 913 AwtComponent* comp = this; 914 while (comp != NULL) { 915 if (comp->IsContainer()) { 916 return (AwtWindow*)comp; 917 } 918 comp = comp->GetParent(); 919 } 920 return NULL; 921 } 922 923 void AwtComponent::Show() 924 { 925 m_visible = true; 926 ::ShowWindow(GetHWnd(), SW_SHOWNA); 927 } 928 929 void AwtComponent::Hide() 930 { 931 m_visible = false; 932 ::ShowWindow(GetHWnd(), SW_HIDE); 933 } 934 935 BOOL 936 AwtComponent::SetWindowPos(HWND wnd, HWND after, 937 int x, int y, int w, int h, UINT flags) 938 { 939 // Conditions we shouldn't handle: 940 // z-order changes, correct window dimensions 941 if (after != NULL || (w < 32767 && h < 32767) 942 || ((::GetWindowLong(wnd, GWL_STYLE) & WS_CHILD) == 0)) 943 { 944 return ::SetWindowPos(wnd, after, x, y, w, h, flags); 945 } 946 WINDOWPLACEMENT wp; 947 ::ZeroMemory(&wp, sizeof(wp)); 948 949 wp.length = sizeof(wp); 950 ::GetWindowPlacement(wnd, &wp); 951 wp.rcNormalPosition.left = x; 952 wp.rcNormalPosition.top = y; 953 wp.rcNormalPosition.right = x + w; 954 wp.rcNormalPosition.bottom = y + h; 955 if ( flags & SWP_NOACTIVATE ) { 956 wp.showCmd = SW_SHOWNOACTIVATE; 957 } 958 ::SetWindowPlacement(wnd, &wp); 959 return 1; 960 } 961 962 void AwtComponent::Reshape(int x, int y, int w, int h) { 963 ReshapeNoScale(ScaleUpX(x), ScaleUpY(y), ScaleUpX(w), ScaleUpY(h)); 964 } 965 966 void AwtComponent::ReshapeNoScale(int x, int y, int w, int h) 967 { 968 #if defined(DEBUG) 969 RECT rc; 970 ::GetWindowRect(GetHWnd(), &rc); 971 ::MapWindowPoints(HWND_DESKTOP, ::GetParent(GetHWnd()), (LPPOINT)&rc, 2); 972 DTRACE_PRINTLN4("AwtComponent::Reshape from %d, %d, %d, %d", rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); 973 #endif 974 975 AwtWindow* container = GetContainer(); 976 AwtComponent* parent = GetParent(); 977 if (container != NULL && container == parent) { 978 container->SubtractInsetPoint(x, y); 979 } 980 DTRACE_PRINTLN4("AwtComponent::Reshape to %d, %d, %d, %d", x, y, w, h); 981 UINT flags = SWP_NOACTIVATE | SWP_NOZORDER; 982 983 RECT r; 984 985 ::GetWindowRect(GetHWnd(), &r); 986 // if the component size is changing , don't copy window bits 987 if (r.right - r.left != w || r.bottom - r.top != h) { 988 flags |= SWP_NOCOPYBITS; 989 } 990 991 if (parent && _tcscmp(parent->GetClassName(), TEXT("SunAwtScrollPane")) == 0) { 992 if (x > 0) { 993 x = 0; 994 } 995 if (y > 0) { 996 y = 0; 997 } 998 } 999 if (m_hdwp != NULL) { 1000 m_hdwp = ::DeferWindowPos(m_hdwp, GetHWnd(), 0, x, y, w, h, flags); 1001 DASSERT(m_hdwp != NULL); 1002 } else { 1003 /* 1004 * Fox for 4046446 1005 * If window has dimensions above the short int limit, ::SetWindowPos doesn't work. 1006 * We should use SetWindowPlacement instead. 1007 */ 1008 SetWindowPos(GetHWnd(), 0, x, y, w, h, flags); 1009 } 1010 } 1011 1012 void AwtComponent::SetScrollValues(UINT bar, int min, int value, int max) 1013 { 1014 int minTmp, maxTmp; 1015 1016 ::GetScrollRange(GetHWnd(), bar, &minTmp, &maxTmp); 1017 if (min == INT_MAX) { 1018 min = minTmp; 1019 } 1020 if (value == INT_MAX) { 1021 value = ::GetScrollPos(GetHWnd(), bar); 1022 } 1023 if (max == INT_MAX) { 1024 max = maxTmp; 1025 } 1026 if (min == max) { 1027 max++; 1028 } 1029 ::SetScrollRange(GetHWnd(), bar, min, max, FALSE); 1030 ::SetScrollPos(GetHWnd(), bar, value, TRUE); 1031 } 1032 1033 /* 1034 * Save Global Reference of sun.awt.windows.WInputMethod object 1035 */ 1036 void AwtComponent::SetInputMethod(jobject im, BOOL useNativeCompWindow) 1037 { 1038 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1039 1040 if (m_InputMethod!=NULL) 1041 env->DeleteGlobalRef(m_InputMethod); 1042 1043 if (im!=NULL){ 1044 m_InputMethod = env->NewGlobalRef(im); 1045 m_useNativeCompWindow = useNativeCompWindow; 1046 } else { 1047 m_InputMethod = NULL; 1048 m_useNativeCompWindow = TRUE; 1049 } 1050 1051 } 1052 1053 /* 1054 * Opportunity to process and/or eat a message before it is dispatched 1055 */ 1056 MsgRouting AwtComponent::PreProcessMsg(MSG& msg) 1057 { 1058 return mrPassAlong; 1059 } 1060 1061 static UINT lastMessage = WM_NULL; 1062 1063 #ifndef SPY_MESSAGES 1064 #define SpyWinMessage(hwin,msg,str) 1065 #else 1066 1067 #define FMT_MSG(x,y) case x: _stprintf(szBuf, \ 1068 "0x%8.8x(%s):%s\n", hwnd, szComment, y); break; 1069 #define WIN_MSG(x) FMT_MSG(x,#x) 1070 1071 void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment) { 1072 1073 TCHAR szBuf[256]; 1074 1075 switch (message) { 1076 WIN_MSG(WM_NULL) 1077 WIN_MSG(WM_CREATE) 1078 WIN_MSG(WM_DESTROY) 1079 WIN_MSG(WM_MOVE) 1080 WIN_MSG(WM_SIZE) 1081 WIN_MSG(WM_ACTIVATE) 1082 WIN_MSG(WM_SETFOCUS) 1083 WIN_MSG(WM_KILLFOCUS) 1084 WIN_MSG(WM_ENABLE) 1085 WIN_MSG(WM_SETREDRAW) 1086 WIN_MSG(WM_SETTEXT) 1087 WIN_MSG(WM_GETTEXT) 1088 WIN_MSG(WM_GETTEXTLENGTH) 1089 WIN_MSG(WM_PAINT) 1090 WIN_MSG(WM_CLOSE) 1091 WIN_MSG(WM_QUERYENDSESSION) 1092 WIN_MSG(WM_QUIT) 1093 WIN_MSG(WM_QUERYOPEN) 1094 WIN_MSG(WM_ERASEBKGND) 1095 WIN_MSG(WM_SYSCOLORCHANGE) 1096 WIN_MSG(WM_ENDSESSION) 1097 WIN_MSG(WM_SHOWWINDOW) 1098 FMT_MSG(WM_WININICHANGE,"WM_WININICHANGE/WM_SETTINGCHANGE") 1099 WIN_MSG(WM_DEVMODECHANGE) 1100 WIN_MSG(WM_ACTIVATEAPP) 1101 WIN_MSG(WM_FONTCHANGE) 1102 WIN_MSG(WM_TIMECHANGE) 1103 WIN_MSG(WM_CANCELMODE) 1104 WIN_MSG(WM_SETCURSOR) 1105 WIN_MSG(WM_MOUSEACTIVATE) 1106 WIN_MSG(WM_CHILDACTIVATE) 1107 WIN_MSG(WM_QUEUESYNC) 1108 WIN_MSG(WM_GETMINMAXINFO) 1109 WIN_MSG(WM_PAINTICON) 1110 WIN_MSG(WM_ICONERASEBKGND) 1111 WIN_MSG(WM_NEXTDLGCTL) 1112 WIN_MSG(WM_SPOOLERSTATUS) 1113 WIN_MSG(WM_DRAWITEM) 1114 WIN_MSG(WM_MEASUREITEM) 1115 WIN_MSG(WM_DELETEITEM) 1116 WIN_MSG(WM_VKEYTOITEM) 1117 WIN_MSG(WM_CHARTOITEM) 1118 WIN_MSG(WM_SETFONT) 1119 WIN_MSG(WM_GETFONT) 1120 WIN_MSG(WM_SETHOTKEY) 1121 WIN_MSG(WM_GETHOTKEY) 1122 WIN_MSG(WM_QUERYDRAGICON) 1123 WIN_MSG(WM_COMPAREITEM) 1124 FMT_MSG(0x003D, "WM_GETOBJECT") 1125 WIN_MSG(WM_COMPACTING) 1126 WIN_MSG(WM_COMMNOTIFY) 1127 WIN_MSG(WM_WINDOWPOSCHANGING) 1128 WIN_MSG(WM_WINDOWPOSCHANGED) 1129 WIN_MSG(WM_POWER) 1130 WIN_MSG(WM_COPYDATA) 1131 WIN_MSG(WM_CANCELJOURNAL) 1132 WIN_MSG(WM_NOTIFY) 1133 WIN_MSG(WM_INPUTLANGCHANGEREQUEST) 1134 WIN_MSG(WM_INPUTLANGCHANGE) 1135 WIN_MSG(WM_TCARD) 1136 WIN_MSG(WM_HELP) 1137 WIN_MSG(WM_USERCHANGED) 1138 WIN_MSG(WM_NOTIFYFORMAT) 1139 WIN_MSG(WM_CONTEXTMENU) 1140 WIN_MSG(WM_STYLECHANGING) 1141 WIN_MSG(WM_STYLECHANGED) 1142 WIN_MSG(WM_DISPLAYCHANGE) 1143 WIN_MSG(WM_GETICON) 1144 WIN_MSG(WM_SETICON) 1145 WIN_MSG(WM_NCCREATE) 1146 WIN_MSG(WM_NCDESTROY) 1147 WIN_MSG(WM_NCCALCSIZE) 1148 WIN_MSG(WM_NCHITTEST) 1149 WIN_MSG(WM_NCPAINT) 1150 WIN_MSG(WM_NCACTIVATE) 1151 WIN_MSG(WM_GETDLGCODE) 1152 WIN_MSG(WM_SYNCPAINT) 1153 WIN_MSG(WM_NCMOUSEMOVE) 1154 WIN_MSG(WM_NCLBUTTONDOWN) 1155 WIN_MSG(WM_NCLBUTTONUP) 1156 WIN_MSG(WM_NCLBUTTONDBLCLK) 1157 WIN_MSG(WM_NCRBUTTONDOWN) 1158 WIN_MSG(WM_NCRBUTTONUP) 1159 WIN_MSG(WM_NCRBUTTONDBLCLK) 1160 WIN_MSG(WM_NCMBUTTONDOWN) 1161 WIN_MSG(WM_NCMBUTTONUP) 1162 WIN_MSG(WM_NCMBUTTONDBLCLK) 1163 WIN_MSG(WM_KEYDOWN) 1164 WIN_MSG(WM_KEYUP) 1165 WIN_MSG(WM_CHAR) 1166 WIN_MSG(WM_DEADCHAR) 1167 WIN_MSG(WM_SYSKEYDOWN) 1168 WIN_MSG(WM_SYSKEYUP) 1169 WIN_MSG(WM_SYSCHAR) 1170 WIN_MSG(WM_SYSDEADCHAR) 1171 WIN_MSG(WM_IME_STARTCOMPOSITION) 1172 WIN_MSG(WM_IME_ENDCOMPOSITION) 1173 WIN_MSG(WM_IME_COMPOSITION) 1174 WIN_MSG(WM_INITDIALOG) 1175 WIN_MSG(WM_COMMAND) 1176 WIN_MSG(WM_SYSCOMMAND) 1177 WIN_MSG(WM_TIMER) 1178 WIN_MSG(WM_HSCROLL) 1179 WIN_MSG(WM_VSCROLL) 1180 WIN_MSG(WM_INITMENU) 1181 WIN_MSG(WM_INITMENUPOPUP) 1182 WIN_MSG(WM_MENUSELECT) 1183 WIN_MSG(WM_MENUCHAR) 1184 WIN_MSG(WM_ENTERIDLE) 1185 FMT_MSG(0x0122, "WM_MENURBUTTONUP") 1186 FMT_MSG(0x0123, "WM_MENUDRAG") 1187 FMT_MSG(0x0124, "WM_MENUGETOBJECT") 1188 FMT_MSG(0x0125, "WM_UNINITMENUPOPUP") 1189 FMT_MSG(0x0126, "WM_MENUCOMMAND") 1190 WIN_MSG(WM_CTLCOLORMSGBOX) 1191 WIN_MSG(WM_CTLCOLOREDIT) 1192 WIN_MSG(WM_CTLCOLORLISTBOX) 1193 WIN_MSG(WM_CTLCOLORBTN) 1194 WIN_MSG(WM_CTLCOLORDLG) 1195 WIN_MSG(WM_CTLCOLORSCROLLBAR) 1196 WIN_MSG(WM_CTLCOLORSTATIC) 1197 WIN_MSG(WM_MOUSEMOVE) 1198 WIN_MSG(WM_LBUTTONDOWN) 1199 WIN_MSG(WM_LBUTTONUP) 1200 WIN_MSG(WM_LBUTTONDBLCLK) 1201 WIN_MSG(WM_RBUTTONDOWN) 1202 WIN_MSG(WM_RBUTTONUP) 1203 WIN_MSG(WM_RBUTTONDBLCLK) 1204 WIN_MSG(WM_MBUTTONDOWN) 1205 WIN_MSG(WM_MBUTTONUP) 1206 WIN_MSG(WM_MBUTTONDBLCLK) 1207 WIN_MSG(WM_XBUTTONDBLCLK) 1208 WIN_MSG(WM_XBUTTONDOWN) 1209 WIN_MSG(WM_XBUTTONUP) 1210 WIN_MSG(WM_MOUSEWHEEL) 1211 WIN_MSG(WM_MOUSEHWHEEL) 1212 WIN_MSG(WM_PARENTNOTIFY) 1213 WIN_MSG(WM_ENTERMENULOOP) 1214 WIN_MSG(WM_EXITMENULOOP) 1215 WIN_MSG(WM_NEXTMENU) 1216 WIN_MSG(WM_SIZING) 1217 WIN_MSG(WM_CAPTURECHANGED) 1218 WIN_MSG(WM_MOVING) 1219 WIN_MSG(WM_POWERBROADCAST) 1220 WIN_MSG(WM_DEVICECHANGE) 1221 WIN_MSG(WM_MDICREATE) 1222 WIN_MSG(WM_MDIDESTROY) 1223 WIN_MSG(WM_MDIACTIVATE) 1224 WIN_MSG(WM_MDIRESTORE) 1225 WIN_MSG(WM_MDINEXT) 1226 WIN_MSG(WM_MDIMAXIMIZE) 1227 WIN_MSG(WM_MDITILE) 1228 WIN_MSG(WM_MDICASCADE) 1229 WIN_MSG(WM_MDIICONARRANGE) 1230 WIN_MSG(WM_MDIGETACTIVE) 1231 WIN_MSG(WM_MDISETMENU) 1232 WIN_MSG(WM_ENTERSIZEMOVE) 1233 WIN_MSG(WM_EXITSIZEMOVE) 1234 WIN_MSG(WM_DROPFILES) 1235 WIN_MSG(WM_MDIREFRESHMENU) 1236 WIN_MSG(WM_IME_SETCONTEXT) 1237 WIN_MSG(WM_IME_NOTIFY) 1238 WIN_MSG(WM_IME_CONTROL) 1239 WIN_MSG(WM_IME_COMPOSITIONFULL) 1240 WIN_MSG(WM_IME_SELECT) 1241 WIN_MSG(WM_IME_CHAR) 1242 FMT_MSG(WM_IME_REQUEST) 1243 WIN_MSG(WM_IME_KEYDOWN) 1244 WIN_MSG(WM_IME_KEYUP) 1245 FMT_MSG(0x02A1, "WM_MOUSEHOVER") 1246 FMT_MSG(0x02A3, "WM_MOUSELEAVE") 1247 WIN_MSG(WM_CUT) 1248 WIN_MSG(WM_COPY) 1249 WIN_MSG(WM_PASTE) 1250 WIN_MSG(WM_CLEAR) 1251 WIN_MSG(WM_UNDO) 1252 WIN_MSG(WM_RENDERFORMAT) 1253 WIN_MSG(WM_RENDERALLFORMATS) 1254 WIN_MSG(WM_DESTROYCLIPBOARD) 1255 WIN_MSG(WM_DRAWCLIPBOARD) 1256 WIN_MSG(WM_PAINTCLIPBOARD) 1257 WIN_MSG(WM_VSCROLLCLIPBOARD) 1258 WIN_MSG(WM_SIZECLIPBOARD) 1259 WIN_MSG(WM_ASKCBFORMATNAME) 1260 WIN_MSG(WM_CHANGECBCHAIN) 1261 WIN_MSG(WM_HSCROLLCLIPBOARD) 1262 WIN_MSG(WM_QUERYNEWPALETTE) 1263 WIN_MSG(WM_PALETTEISCHANGING) 1264 WIN_MSG(WM_PALETTECHANGED) 1265 WIN_MSG(WM_HOTKEY) 1266 WIN_MSG(WM_PRINT) 1267 WIN_MSG(WM_PRINTCLIENT) 1268 WIN_MSG(WM_HANDHELDFIRST) 1269 WIN_MSG(WM_HANDHELDLAST) 1270 WIN_MSG(WM_AFXFIRST) 1271 WIN_MSG(WM_AFXLAST) 1272 WIN_MSG(WM_PENWINFIRST) 1273 WIN_MSG(WM_PENWINLAST) 1274 WIN_MSG(WM_AWT_COMPONENT_CREATE) 1275 WIN_MSG(WM_AWT_DESTROY_WINDOW) 1276 WIN_MSG(WM_AWT_MOUSEENTER) 1277 WIN_MSG(WM_AWT_MOUSEEXIT) 1278 WIN_MSG(WM_AWT_COMPONENT_SHOW) 1279 WIN_MSG(WM_AWT_COMPONENT_HIDE) 1280 WIN_MSG(WM_AWT_COMPONENT_SETFOCUS) 1281 WIN_MSG(WM_AWT_WINDOW_SETACTIVE) 1282 WIN_MSG(WM_AWT_LIST_SETMULTISELECT) 1283 WIN_MSG(WM_AWT_HANDLE_EVENT) 1284 WIN_MSG(WM_AWT_PRINT_COMPONENT) 1285 WIN_MSG(WM_AWT_RESHAPE_COMPONENT) 1286 WIN_MSG(WM_AWT_SETALWAYSONTOP) 1287 WIN_MSG(WM_AWT_BEGIN_VALIDATE) 1288 WIN_MSG(WM_AWT_END_VALIDATE) 1289 WIN_MSG(WM_AWT_FORWARD_CHAR) 1290 WIN_MSG(WM_AWT_FORWARD_BYTE) 1291 WIN_MSG(WM_AWT_SET_SCROLL_INFO) 1292 WIN_MSG(WM_AWT_CREATECONTEXT) 1293 WIN_MSG(WM_AWT_DESTROYCONTEXT) 1294 WIN_MSG(WM_AWT_ASSOCIATECONTEXT) 1295 WIN_MSG(WM_AWT_GET_DEFAULT_IME_HANDLER) 1296 WIN_MSG(WM_AWT_HANDLE_NATIVE_IME_EVENT) 1297 WIN_MSG(WM_AWT_PRE_KEYDOWN) 1298 WIN_MSG(WM_AWT_PRE_KEYUP) 1299 WIN_MSG(WM_AWT_PRE_SYSKEYDOWN) 1300 WIN_MSG(WM_AWT_PRE_SYSKEYUP) 1301 WIN_MSG(WM_AWT_ENDCOMPOSITION,) 1302 WIN_MSG(WM_AWT_DISPOSE,) 1303 WIN_MSG(WM_AWT_DELETEOBJECT,) 1304 WIN_MSG(WM_AWT_SETCONVERSIONSTATUS,) 1305 WIN_MSG(WM_AWT_GETCONVERSIONSTATUS,) 1306 WIN_MSG(WM_AWT_SETOPENSTATUS,) 1307 WIN_MSG(WM_AWT_GETOPENSTATUS) 1308 WIN_MSG(WM_AWT_ACTIVATEKEYBOARDLAYOUT) 1309 WIN_MSG(WM_AWT_OPENCANDIDATEWINDOW) 1310 WIN_MSG(WM_AWT_DLG_SHOWMODAL,) 1311 WIN_MSG(WM_AWT_DLG_ENDMODAL,) 1312 WIN_MSG(WM_AWT_SETCURSOR,) 1313 WIN_MSG(WM_AWT_WAIT_FOR_SINGLE_OBJECT,) 1314 WIN_MSG(WM_AWT_INVOKE_METHOD,) 1315 WIN_MSG(WM_AWT_INVOKE_VOID_METHOD,) 1316 WIN_MSG(WM_AWT_EXECUTE_SYNC,) 1317 WIN_MSG(WM_AWT_CURSOR_SYNC) 1318 WIN_MSG(WM_AWT_GETDC) 1319 WIN_MSG(WM_AWT_RELEASEDC) 1320 WIN_MSG(WM_AWT_RELEASE_ALL_DCS) 1321 WIN_MSG(WM_AWT_SHOWCURSOR) 1322 WIN_MSG(WM_AWT_HIDECURSOR) 1323 WIN_MSG(WM_AWT_CREATE_PRINTED_PIXELS) 1324 WIN_MSG(WM_AWT_OBJECTLISTCLEANUP) 1325 default: 1326 sprintf(szBuf, "0x%8.8x(%s):Unknown message 0x%8.8x\n", 1327 hwnd, szComment, message); 1328 break; 1329 } 1330 printf(szBuf); 1331 } 1332 1333 #endif /* SPY_MESSAGES */ 1334 1335 /* 1336 * Dispatch messages for this window class--general component 1337 */ 1338 LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 1339 { 1340 CounterHelper ch(&m_MessagesProcessing); 1341 1342 JNILocalFrame lframe(AwtToolkit::GetEnv(), 10); 1343 SpyWinMessage(GetHWnd(), message, 1344 (message == WM_AWT_RELEASE_ALL_DCS) ? TEXT("Disposed Component") : GetClassName()); 1345 1346 LRESULT retValue = 0; 1347 MsgRouting mr = mrDoDefault; 1348 AwtToolkit::GetInstance().eventNumber++; 1349 1350 static BOOL ignoreNextLBTNUP = FALSE; //Ignore next LBUTTONUP msg? 1351 1352 lastMessage = message; 1353 1354 if (message == WmAwtIsComponent) { 1355 // special message to identify AWT HWND's without using 1356 // resource hogging ::SetProp 1357 return (LRESULT)TRUE; 1358 } 1359 1360 DWORD curPos = 0; 1361 1362 UINT switchMessage = message; 1363 switch (switchMessage) { 1364 case WM_AWT_GETDC: 1365 { 1366 HDC hDC; 1367 // First, release the DCs scheduled for deletion 1368 ReleaseDCList(GetHWnd(), passiveDCList); 1369 1370 GetDCReturnStruct *returnStruct = new GetDCReturnStruct; 1371 returnStruct->gdiLimitReached = FALSE; 1372 if (AwtGDIObject::IncrementIfAvailable()) { 1373 hDC = ::GetDCEx(GetHWnd(), NULL, 1374 DCX_CACHE | DCX_CLIPCHILDREN | 1375 DCX_CLIPSIBLINGS); 1376 if (hDC != NULL) { 1377 // Add new DC to list of DC's associated with this Component 1378 activeDCList.AddDC(hDC, GetHWnd()); 1379 } else { 1380 // Creation failed; decrement counter in AwtGDIObject 1381 AwtGDIObject::Decrement(); 1382 } 1383 } else { 1384 hDC = NULL; 1385 returnStruct->gdiLimitReached = TRUE; 1386 } 1387 returnStruct->hDC = hDC; 1388 retValue = (LRESULT)returnStruct; 1389 mr = mrConsume; 1390 break; 1391 } 1392 case WM_AWT_RELEASEDC: 1393 { 1394 HDC hDC = (HDC)wParam; 1395 MoveDCToPassiveList(hDC, GetHWnd()); 1396 ReleaseDCList(GetHWnd(), passiveDCList); 1397 mr = mrConsume; 1398 break; 1399 } 1400 case WM_AWT_RELEASE_ALL_DCS: 1401 { 1402 // Called during Component destruction. Gets current list of 1403 // DC's associated with Component and releases each DC. 1404 ReleaseDCList(GetHWnd(), activeDCList); 1405 ReleaseDCList(GetHWnd(), passiveDCList); 1406 mr = mrConsume; 1407 break; 1408 } 1409 case WM_AWT_SHOWCURSOR: 1410 ::ShowCursor(TRUE); 1411 break; 1412 case WM_AWT_HIDECURSOR: 1413 ::ShowCursor(FALSE); 1414 break; 1415 case WM_CREATE: mr = WmCreate(); break; 1416 case WM_CLOSE: mr = WmClose(); break; 1417 case WM_DESTROY: mr = WmDestroy(); break; 1418 case WM_NCDESTROY: mr = WmNcDestroy(); break; 1419 1420 case WM_ERASEBKGND: 1421 mr = WmEraseBkgnd((HDC)wParam, *(BOOL*)&retValue); break; 1422 case WM_PAINT: 1423 CheckFontSmoothingSettings(GetHWnd()); 1424 /* Set draw state */ 1425 SetDrawState(GetDrawState() | JAWT_LOCK_CLIP_CHANGED); 1426 mr = WmPaint((HDC)wParam); 1427 break; 1428 1429 case WM_GETMINMAXINFO: 1430 mr = WmGetMinMaxInfo((LPMINMAXINFO)lParam); 1431 break; 1432 1433 case WM_WINDOWPOSCHANGING: 1434 { 1435 // We process this message so that we can synchronize access to 1436 // a moving window. The Scale/Blt functions in Win32BlitLoops 1437 // take the same windowMoveLock to ensure that a window is not 1438 // moving while we are trying to copy pixels into it. 1439 WINDOWPOS *lpPosInfo = (WINDOWPOS *)lParam; 1440 if ((lpPosInfo->flags & (SWP_NOMOVE | SWP_NOSIZE)) != 1441 (SWP_NOMOVE | SWP_NOSIZE)) 1442 { 1443 // Move or Size command. 1444 // Windows tends to send erroneous events that the window 1445 // is about to move when the coordinates are exactly the 1446 // same as the last time. This can cause problems with 1447 // our windowMoveLock CriticalSection because we enter it 1448 // here and never get to WM_WINDOWPOSCHANGED to release it. 1449 // So make sure this is a real move/size event before bothering 1450 // to grab the critical section. 1451 BOOL takeLock = FALSE; 1452 if (!(lpPosInfo->flags & SWP_NOMOVE) && 1453 ((windowMoveLockPosX != lpPosInfo->x) || 1454 (windowMoveLockPosY != lpPosInfo->y))) 1455 { 1456 // Real move event 1457 takeLock = TRUE; 1458 windowMoveLockPosX = lpPosInfo->x; 1459 windowMoveLockPosY = lpPosInfo->y; 1460 } 1461 if (!(lpPosInfo->flags & SWP_NOSIZE) && 1462 ((windowMoveLockPosCX != lpPosInfo->cx) || 1463 (windowMoveLockPosCY != lpPosInfo->cy))) 1464 { 1465 // Real size event 1466 takeLock = TRUE; 1467 windowMoveLockPosCX = lpPosInfo->cx; 1468 windowMoveLockPosCY = lpPosInfo->cy; 1469 } 1470 if (takeLock) { 1471 if (!windowMoveLockHeld) { 1472 windowMoveLock.Enter(); 1473 windowMoveLockHeld = TRUE; 1474 } 1475 } 1476 } 1477 mr = WmWindowPosChanging(lParam); 1478 break; 1479 } 1480 case WM_WINDOWPOSCHANGED: 1481 { 1482 // Release lock grabbed in the POSCHANGING message 1483 if (windowMoveLockHeld) { 1484 windowMoveLockHeld = FALSE; 1485 windowMoveLock.Leave(); 1486 } 1487 mr = WmWindowPosChanged(lParam); 1488 break; 1489 } 1490 case WM_MOVE: { 1491 RECT r; 1492 ::GetWindowRect(GetHWnd(), &r); 1493 mr = WmMove(r.left, r.top); 1494 break; 1495 } 1496 case WM_SIZE: 1497 { 1498 RECT r; 1499 // fix 4128317 : use GetClientRect for full 32-bit int precision and 1500 // to avoid negative client area dimensions overflowing 16-bit params - robi 1501 ::GetClientRect( GetHWnd(), &r ); 1502 mr = WmSize(static_cast<UINT>(wParam), r.right - r.left, r.bottom - r.top); 1503 //mr = WmSize(wParam, LOWORD(lParam), HIWORD(lParam)); 1504 SetCompositionWindow(r); 1505 break; 1506 } 1507 case WM_SIZING: 1508 mr = WmSizing(); 1509 break; 1510 case WM_SHOWWINDOW: 1511 mr = WmShowWindow(static_cast<BOOL>(wParam), 1512 static_cast<UINT>(lParam)); break; 1513 case WM_SYSCOMMAND: 1514 mr = WmSysCommand(static_cast<UINT>(wParam & 0xFFF0), 1515 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 1516 break; 1517 case WM_ENTERSIZEMOVE: 1518 mr = WmEnterSizeMove(); 1519 break; 1520 case WM_EXITSIZEMOVE: 1521 mr = WmExitSizeMove(); 1522 break; 1523 // Bug #4039858 (Selecting menu item causes bogus mouse click event) 1524 case WM_ENTERMENULOOP: 1525 mr = WmEnterMenuLoop((BOOL)wParam); 1526 sm_bMenuLoop = TRUE; 1527 // we need to release grab if menu is shown 1528 if (AwtWindow::GetGrabbedWindow() != NULL) { 1529 AwtWindow::GetGrabbedWindow()->Ungrab(); 1530 } 1531 break; 1532 case WM_EXITMENULOOP: 1533 mr = WmExitMenuLoop((BOOL)wParam); 1534 sm_bMenuLoop = FALSE; 1535 break; 1536 1537 // We don't expect any focus messages on non-proxy component, 1538 // except those that came from Java. 1539 case WM_SETFOCUS: 1540 if (sm_inSynthesizeFocus) { 1541 mr = WmSetFocus((HWND)wParam); 1542 } else { 1543 mr = mrConsume; 1544 } 1545 break; 1546 case WM_KILLFOCUS: 1547 if (sm_inSynthesizeFocus) { 1548 mr = WmKillFocus((HWND)wParam); 1549 } else { 1550 mr = mrConsume; 1551 } 1552 break; 1553 case WM_ACTIVATE: { 1554 UINT nState = LOWORD(wParam); 1555 BOOL fMinimized = (BOOL)HIWORD(wParam); 1556 mr = mrConsume; 1557 1558 if (!sm_suppressFocusAndActivation && 1559 (!fMinimized || (nState == WA_INACTIVE))) 1560 { 1561 mr = WmActivate(nState, fMinimized, (HWND)lParam); 1562 1563 // When the window is deactivated, send WM_IME_ENDCOMPOSITION 1564 // message to deactivate the composition window so that 1565 // it won't receive keyboard input focus. 1566 HIMC hIMC; 1567 HWND hwnd = ImmGetHWnd(); 1568 if ((hIMC = ImmGetContext(hwnd)) != NULL) { 1569 ImmReleaseContext(hwnd, hIMC); 1570 DefWindowProc(WM_IME_ENDCOMPOSITION, 0, 0); 1571 } 1572 } 1573 break; 1574 } 1575 case WM_MOUSEACTIVATE: { 1576 AwtWindow *window = GetContainer(); 1577 if (window && window->IsFocusableWindow()) { 1578 // AWT/Swing will later request focus to a proper component 1579 // on handling the Java mouse event. Anyway, we have to 1580 // activate the window here as it works both for AWT & Swing. 1581 // Do it in our own fassion, 1582 window->AwtSetActiveWindow(TRUE, LOWORD(lParam)/*hittest*/); 1583 } 1584 mr = mrConsume; 1585 retValue = MA_NOACTIVATE; 1586 break; 1587 } 1588 case WM_CTLCOLORMSGBOX: 1589 case WM_CTLCOLOREDIT: 1590 case WM_CTLCOLORLISTBOX: 1591 case WM_CTLCOLORBTN: 1592 case WM_CTLCOLORDLG: 1593 case WM_CTLCOLORSCROLLBAR: 1594 case WM_CTLCOLORSTATIC: 1595 mr = WmCtlColor((HDC)wParam, (HWND)lParam, 1596 message-WM_CTLCOLORMSGBOX+CTLCOLOR_MSGBOX, 1597 *(HBRUSH*)&retValue); 1598 break; 1599 case WM_HSCROLL: 1600 mr = WmHScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); 1601 break; 1602 case WM_VSCROLL: 1603 mr = WmVScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); 1604 break; 1605 // 4664415: We're seeing a WM_LBUTTONUP when the user releases the 1606 // mouse button after a WM_NCLBUTTONDBLCLK. We want to ignore this 1607 // WM_LBUTTONUP, so we set a flag in WM_NCLBUTTONDBLCLK and look for the 1608 // flag on a WM_LBUTTONUP. -bchristi 1609 case WM_NCLBUTTONDBLCLK: 1610 mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON | DBL_CLICK); 1611 if (mr == mrDoDefault) { 1612 ignoreNextLBTNUP = TRUE; 1613 } 1614 break; 1615 case WM_NCLBUTTONDOWN: 1616 mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON); 1617 ignoreNextLBTNUP = FALSE; 1618 break; 1619 case WM_NCLBUTTONUP: 1620 mr = WmNcMouseUp(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON); 1621 break; 1622 case WM_NCRBUTTONDOWN: 1623 mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RIGHT_BUTTON); 1624 break; 1625 case WM_LBUTTONUP: 1626 if (ignoreNextLBTNUP) { 1627 ignoreNextLBTNUP = FALSE; 1628 return mrDoDefault; 1629 } 1630 //fall-through 1631 case WM_LBUTTONDOWN: 1632 ignoreNextLBTNUP = FALSE; 1633 //fall-through 1634 case WM_LBUTTONDBLCLK: 1635 case WM_RBUTTONDOWN: 1636 case WM_RBUTTONDBLCLK: 1637 case WM_RBUTTONUP: 1638 case WM_MBUTTONDOWN: 1639 case WM_MBUTTONDBLCLK: 1640 case WM_MBUTTONUP: 1641 case WM_XBUTTONDBLCLK: 1642 case WM_XBUTTONDOWN: 1643 case WM_XBUTTONUP: 1644 case WM_MOUSEMOVE: 1645 case WM_MOUSEWHEEL: 1646 case WM_MOUSEHWHEEL: 1647 case WM_AWT_MOUSEENTER: 1648 case WM_AWT_MOUSEEXIT: 1649 curPos = ::GetMessagePos(); 1650 POINT myPos; 1651 myPos.x = GET_X_LPARAM(curPos); 1652 myPos.y = GET_Y_LPARAM(curPos); 1653 ::ScreenToClient(GetHWnd(), &myPos); 1654 switch(switchMessage) { 1655 case WM_AWT_MOUSEENTER: 1656 mr = WmMouseEnter(static_cast<UINT>(wParam), myPos.x, myPos.y); 1657 break; 1658 case WM_LBUTTONDOWN: 1659 case WM_LBUTTONDBLCLK: 1660 mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y, 1661 LEFT_BUTTON); 1662 break; 1663 case WM_LBUTTONUP: 1664 mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y, 1665 LEFT_BUTTON); 1666 break; 1667 case WM_MOUSEMOVE: 1668 mr = WmMouseMove(static_cast<UINT>(wParam), myPos.x, myPos.y); 1669 break; 1670 case WM_MBUTTONDOWN: 1671 case WM_MBUTTONDBLCLK: 1672 mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y, 1673 MIDDLE_BUTTON); 1674 break; 1675 case WM_XBUTTONDOWN: 1676 case WM_XBUTTONDBLCLK: 1677 if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) { 1678 if (HIWORD(wParam) == 1) { 1679 mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y, 1680 X1_BUTTON); 1681 } 1682 if (HIWORD(wParam) == 2) { 1683 mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y, 1684 X2_BUTTON); 1685 } 1686 } 1687 break; 1688 case WM_XBUTTONUP: 1689 if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) { 1690 if (HIWORD(wParam) == 1) { 1691 mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y, 1692 X1_BUTTON); 1693 } 1694 if (HIWORD(wParam) == 2) { 1695 mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y, 1696 X2_BUTTON); 1697 } 1698 } 1699 break; 1700 case WM_RBUTTONDOWN: 1701 case WM_RBUTTONDBLCLK: 1702 mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y, 1703 RIGHT_BUTTON); 1704 break; 1705 case WM_RBUTTONUP: 1706 mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y, 1707 RIGHT_BUTTON); 1708 break; 1709 case WM_MBUTTONUP: 1710 mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y, 1711 MIDDLE_BUTTON); 1712 break; 1713 case WM_AWT_MOUSEEXIT: 1714 mr = WmMouseExit(static_cast<UINT>(wParam), myPos.x, myPos.y); 1715 break; 1716 case WM_MOUSEWHEEL: 1717 case WM_MOUSEHWHEEL: 1718 mr = WmMouseWheel(GET_KEYSTATE_WPARAM(wParam), 1719 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 1720 GET_WHEEL_DELTA_WPARAM(wParam), 1721 switchMessage == WM_MOUSEHWHEEL); 1722 break; 1723 } 1724 break; 1725 case WM_TOUCH: 1726 WmTouch(wParam, lParam); 1727 break; 1728 case WM_SETCURSOR: 1729 mr = mrDoDefault; 1730 if (LOWORD(lParam) == HTCLIENT) { 1731 if (AwtComponent* comp = 1732 AwtComponent::GetComponent((HWND)wParam)) { 1733 AwtCursor::UpdateCursor(comp); 1734 mr = mrConsume; 1735 } 1736 } 1737 break; 1738 1739 case WM_KEYDOWN: 1740 mr = WmKeyDown(static_cast<UINT>(wParam), 1741 LOWORD(lParam), HIWORD(lParam), FALSE); 1742 break; 1743 case WM_KEYUP: 1744 mr = WmKeyUp(static_cast<UINT>(wParam), 1745 LOWORD(lParam), HIWORD(lParam), FALSE); 1746 break; 1747 case WM_SYSKEYDOWN: 1748 mr = WmKeyDown(static_cast<UINT>(wParam), 1749 LOWORD(lParam), HIWORD(lParam), TRUE); 1750 break; 1751 case WM_SYSKEYUP: 1752 mr = WmKeyUp(static_cast<UINT>(wParam), 1753 LOWORD(lParam), HIWORD(lParam), TRUE); 1754 break; 1755 case WM_IME_SETCONTEXT: 1756 // lParam is passed as pointer and it can be modified. 1757 mr = WmImeSetContext(static_cast<BOOL>(wParam), &lParam); 1758 CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); 1759 break; 1760 case WM_IME_NOTIFY: 1761 mr = WmImeNotify(wParam, lParam); 1762 CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); 1763 break; 1764 case WM_IME_STARTCOMPOSITION: 1765 mr = WmImeStartComposition(); 1766 CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); 1767 break; 1768 case WM_IME_ENDCOMPOSITION: 1769 mr = WmImeEndComposition(); 1770 CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); 1771 break; 1772 case WM_IME_COMPOSITION: { 1773 WORD dbcschar = static_cast<WORD>(wParam); 1774 mr = WmImeComposition(dbcschar, lParam); 1775 CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); 1776 break; 1777 } 1778 case WM_IME_CONTROL: 1779 case WM_IME_COMPOSITIONFULL: 1780 case WM_IME_SELECT: 1781 case WM_IME_KEYUP: 1782 case WM_IME_KEYDOWN: 1783 case WM_IME_REQUEST: 1784 CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); 1785 break; 1786 case WM_CHAR: 1787 mr = WmChar(static_cast<UINT>(wParam), 1788 LOWORD(lParam), HIWORD(lParam), FALSE); 1789 break; 1790 case WM_SYSCHAR: 1791 mr = WmChar(static_cast<UINT>(wParam), 1792 LOWORD(lParam), HIWORD(lParam), TRUE); 1793 break; 1794 case WM_IME_CHAR: 1795 mr = WmIMEChar(static_cast<UINT>(wParam), 1796 LOWORD(lParam), HIWORD(lParam), FALSE); 1797 break; 1798 1799 case WM_INPUTLANGCHANGEREQUEST: { 1800 DTRACE_PRINTLN4("WM_INPUTLANGCHANGEREQUEST: hwnd = 0x%X (%s);"// 1801 "0x%08X -> 0x%08X", 1802 GetHWnd(), GetClassName(), 1803 (UINT_PTR)GetKeyboardLayout(), (UINT_PTR)lParam); 1804 // 4267428: make sure keyboard layout is turned undead. 1805 static BYTE keyboardState[AwtToolkit::KB_STATE_SIZE]; 1806 AwtToolkit::GetKeyboardState(keyboardState); 1807 WORD ignored; 1808 ::ToAsciiEx(VK_SPACE, ::MapVirtualKey(VK_SPACE, 0), 1809 keyboardState, &ignored, 0, GetKeyboardLayout()); 1810 1811 // Set this flag to block ActivateKeyboardLayout from 1812 // WInputMethod.activate() 1813 g_bUserHasChangedInputLang = TRUE; 1814 CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); 1815 break; 1816 } 1817 case WM_INPUTLANGCHANGE: 1818 DTRACE_PRINTLN3("WM_INPUTLANGCHANGE: hwnd = 0x%X (%s);"// 1819 "new = 0x%08X", 1820 GetHWnd(), GetClassName(), (UINT)lParam); 1821 mr = WmInputLangChange(static_cast<UINT>(wParam), reinterpret_cast<HKL>(lParam)); 1822 CallProxyDefWindowProc(message, wParam, lParam, retValue, mr); 1823 // should return non-zero if we process this message 1824 retValue = 1; 1825 break; 1826 1827 case WM_AWT_FORWARD_CHAR: 1828 mr = WmForwardChar(LOWORD(wParam), lParam, HIWORD(wParam)); 1829 break; 1830 1831 case WM_AWT_FORWARD_BYTE: 1832 mr = HandleEvent( (MSG *) lParam, (BOOL) wParam); 1833 break; 1834 1835 case WM_PASTE: 1836 mr = WmPaste(); 1837 break; 1838 case WM_TIMER: 1839 mr = WmTimer(wParam); 1840 break; 1841 1842 case WM_COMMAND: 1843 mr = WmCommand(LOWORD(wParam), (HWND)lParam, HIWORD(wParam)); 1844 break; 1845 case WM_COMPAREITEM: 1846 mr = WmCompareItem(static_cast<UINT>(wParam), 1847 *(COMPAREITEMSTRUCT*)lParam, retValue); 1848 break; 1849 case WM_DELETEITEM: 1850 mr = WmDeleteItem(static_cast<UINT>(wParam), 1851 *(DELETEITEMSTRUCT*)lParam); 1852 break; 1853 case WM_DRAWITEM: 1854 mr = WmDrawItem(static_cast<UINT>(wParam), 1855 *(DRAWITEMSTRUCT*)lParam); 1856 break; 1857 case WM_MEASUREITEM: 1858 mr = WmMeasureItem(static_cast<UINT>(wParam), 1859 *(MEASUREITEMSTRUCT*)lParam); 1860 break; 1861 1862 case WM_AWT_HANDLE_EVENT: 1863 mr = HandleEvent( (MSG *) lParam, (BOOL) wParam); 1864 break; 1865 1866 case WM_PRINT: 1867 mr = WmPrint((HDC)wParam, lParam); 1868 break; 1869 case WM_PRINTCLIENT: 1870 mr = WmPrintClient((HDC)wParam, lParam); 1871 break; 1872 1873 case WM_NCCALCSIZE: 1874 mr = WmNcCalcSize((BOOL)wParam, (LPNCCALCSIZE_PARAMS)lParam, 1875 retValue); 1876 break; 1877 case WM_NCPAINT: 1878 mr = WmNcPaint((HRGN)wParam); 1879 break; 1880 case WM_NCHITTEST: 1881 mr = WmNcHitTest(LOWORD(lParam), HIWORD(lParam), retValue); 1882 break; 1883 1884 case WM_AWT_RESHAPE_COMPONENT: { 1885 RECT* r = (RECT*)lParam; 1886 WPARAM checkEmbedded = wParam; 1887 if (checkEmbedded == CHECK_EMBEDDED && IsEmbeddedFrame()) { 1888 ::OffsetRect(r, -r->left, -r->top); 1889 } 1890 Reshape(r->left, r->top, r->right - r->left, r->bottom - r->top); 1891 delete r; 1892 mr = mrConsume; 1893 break; 1894 } 1895 1896 case WM_AWT_SETALWAYSONTOP: { 1897 AwtWindow* w = (AwtWindow*)lParam; 1898 BOOL value = (BOOL)wParam; 1899 UINT flags = SWP_NOMOVE | SWP_NOSIZE; 1900 // transient windows shouldn't change the owner window's position in the z-order 1901 if (w->IsRetainingHierarchyZOrder()) { 1902 flags |= SWP_NOOWNERZORDER; 1903 } 1904 ::SetWindowPos(w->GetHWnd(), (value != 0 ? HWND_TOPMOST : HWND_NOTOPMOST), 1905 0,0,0,0, flags); 1906 break; 1907 } 1908 1909 case WM_AWT_BEGIN_VALIDATE: 1910 BeginValidate(); 1911 mr = mrConsume; 1912 break; 1913 case WM_AWT_END_VALIDATE: 1914 EndValidate(); 1915 mr = mrConsume; 1916 break; 1917 1918 case WM_PALETTEISCHANGING: 1919 mr = WmPaletteIsChanging((HWND)wParam); 1920 mr = mrDoDefault; 1921 break; 1922 case WM_QUERYNEWPALETTE: 1923 mr = WmQueryNewPalette(retValue); 1924 break; 1925 case WM_PALETTECHANGED: 1926 mr = WmPaletteChanged((HWND)wParam); 1927 break; 1928 case WM_STYLECHANGED: 1929 mr = WmStyleChanged(static_cast<int>(wParam), (LPSTYLESTRUCT)lParam); 1930 break; 1931 case WM_SETTINGCHANGE: 1932 CheckFontSmoothingSettings(NULL); 1933 mr = WmSettingChange(static_cast<UINT>(wParam), (LPCTSTR)lParam); 1934 break; 1935 case WM_CONTEXTMENU: 1936 mr = WmContextMenu((HWND)wParam, 1937 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 1938 break; 1939 1940 /* 1941 * These messages are used to route Win32 calls to the 1942 * creating thread, since these calls fail unless executed 1943 * there. 1944 */ 1945 case WM_AWT_COMPONENT_SHOW: 1946 Show(); 1947 mr = mrConsume; 1948 break; 1949 case WM_AWT_COMPONENT_HIDE: 1950 Hide(); 1951 mr = mrConsume; 1952 break; 1953 1954 case WM_AWT_COMPONENT_SETFOCUS: 1955 if ((BOOL)wParam) { 1956 retValue = SynthesizeWmSetFocus(GetHWnd(), NULL); 1957 } else { 1958 retValue = SynthesizeWmKillFocus(GetHWnd(), NULL); 1959 } 1960 mr = mrConsume; 1961 break; 1962 case WM_AWT_WINDOW_SETACTIVE: 1963 retValue = (LRESULT)((AwtWindow*)this)->AwtSetActiveWindow((BOOL)wParam); 1964 mr = mrConsume; 1965 break; 1966 1967 case WM_AWT_SET_SCROLL_INFO: { 1968 SCROLLINFO *si = (SCROLLINFO *) lParam; 1969 ::SetScrollInfo(GetHWnd(), (int) wParam, si, TRUE); 1970 delete si; 1971 mr = mrConsume; 1972 break; 1973 } 1974 case WM_AWT_CREATE_PRINTED_PIXELS: { 1975 CreatePrintedPixelsStruct* cpps = (CreatePrintedPixelsStruct*)wParam; 1976 SIZE loc = { cpps->srcx, cpps->srcy }; 1977 SIZE size = { cpps->srcw, cpps->srch }; 1978 retValue = (LRESULT)CreatePrintedPixels(loc, size, cpps->alpha); 1979 mr = mrConsume; 1980 break; 1981 } 1982 case WM_UNDOCUMENTED_CLICKMENUBAR: 1983 { 1984 if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) { 1985 mr = mrConsume; 1986 } 1987 } 1988 } 1989 1990 /* 1991 * If not a specific Consume, it was a specific DoDefault, or a 1992 * PassAlong (since the default is the next in chain), then call the 1993 * default proc. 1994 */ 1995 if (mr != mrConsume) { 1996 retValue = DefWindowProc(message, wParam, lParam); 1997 } 1998 1999 return retValue; 2000 } 2001 /* 2002 * Call this instance's default window proc, or if none set, call the stock 2003 * Window's one. 2004 */ 2005 LRESULT AwtComponent::DefWindowProc(UINT msg, WPARAM wParam, LPARAM lParam) 2006 { 2007 return ComCtl32Util::GetInstance().DefWindowProc(m_DefWindowProc, GetHWnd(), msg, wParam, lParam); 2008 } 2009 2010 /* 2011 * This message should only be received when a window is destroyed by 2012 * Windows, and not Java. Window termination has been reworked so 2013 * this method should never be called during termination. 2014 */ 2015 MsgRouting AwtComponent::WmDestroy() 2016 { 2017 return mrConsume; 2018 } 2019 2020 /* 2021 * This message should only be received when a window is destroyed by 2022 * Windows, and not Java. It is sent only after child windows were destroyed. 2023 */ 2024 MsgRouting AwtComponent::WmNcDestroy() 2025 { 2026 if (m_peerObject != NULL) { // is not being terminating 2027 // Stay in this handler until AwtComponent::Dispose is called. 2028 m_bPauseDestroy = TRUE; 2029 2030 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 2031 // Post invocation event for WObjectPeer.dispose to EDT 2032 env->CallVoidMethod(m_peerObject, AwtComponent::disposeLaterMID); 2033 // Wait until AwtComponent::Dispose is called 2034 AwtToolkit::GetInstance().PumpToDestroy(this); 2035 } 2036 2037 return mrConsume; 2038 } 2039 2040 MsgRouting AwtComponent::WmGetMinMaxInfo(LPMINMAXINFO lpmmi) 2041 { 2042 return mrDoDefault; 2043 } 2044 2045 MsgRouting AwtComponent::WmMove(int x, int y) 2046 { 2047 SetDrawState(GetDrawState() | static_cast<jint>(JAWT_LOCK_BOUNDS_CHANGED) 2048 | static_cast<jint>(JAWT_LOCK_CLIP_CHANGED)); 2049 return mrDoDefault; 2050 } 2051 2052 MsgRouting AwtComponent::WmSize(UINT type, int w, int h) 2053 { 2054 SetDrawState(GetDrawState() | static_cast<jint>(JAWT_LOCK_BOUNDS_CHANGED) 2055 | static_cast<jint>(JAWT_LOCK_CLIP_CHANGED)); 2056 return mrDoDefault; 2057 } 2058 2059 MsgRouting AwtComponent::WmSizing() 2060 { 2061 return mrDoDefault; 2062 } 2063 2064 MsgRouting AwtComponent::WmSysCommand(UINT uCmdType, int xPos, int yPos) 2065 { 2066 return mrDoDefault; 2067 } 2068 2069 MsgRouting AwtComponent::WmEnterSizeMove() 2070 { 2071 return mrDoDefault; 2072 } 2073 2074 MsgRouting AwtComponent::WmExitSizeMove() 2075 { 2076 return mrDoDefault; 2077 } 2078 2079 MsgRouting AwtComponent::WmEnterMenuLoop(BOOL isTrackPopupMenu) 2080 { 2081 return mrDoDefault; 2082 } 2083 2084 MsgRouting AwtComponent::WmExitMenuLoop(BOOL isTrackPopupMenu) 2085 { 2086 return mrDoDefault; 2087 } 2088 2089 MsgRouting AwtComponent::WmShowWindow(BOOL show, UINT status) 2090 { 2091 return mrDoDefault; 2092 } 2093 2094 MsgRouting AwtComponent::WmSetFocus(HWND hWndLostFocus) 2095 { 2096 m_wheelRotationAmountX = 0; 2097 m_wheelRotationAmountY = 0; 2098 return mrDoDefault; 2099 } 2100 2101 MsgRouting AwtComponent::WmKillFocus(HWND hWndGotFocus) 2102 { 2103 m_wheelRotationAmountX = 0; 2104 m_wheelRotationAmountY = 0; 2105 return mrDoDefault; 2106 } 2107 2108 MsgRouting AwtComponent::WmCtlColor(HDC hDC, HWND hCtrl, 2109 UINT ctlColor, HBRUSH& retBrush) 2110 { 2111 AwtComponent* child = AwtComponent::GetComponent(hCtrl); 2112 if (child) { 2113 ::SetBkColor(hDC, child->GetBackgroundColor()); 2114 ::SetTextColor(hDC, child->GetColor()); 2115 retBrush = child->GetBackgroundBrush(); 2116 return mrConsume; 2117 } 2118 return mrDoDefault; 2119 /* 2120 switch (ctlColor) { 2121 case CTLCOLOR_MSGBOX: 2122 case CTLCOLOR_EDIT: 2123 case CTLCOLOR_LISTBOX: 2124 case CTLCOLOR_BTN: 2125 case CTLCOLOR_DLG: 2126 case CTLCOLOR_SCROLLBAR: 2127 case CTLCOLOR_STATIC: 2128 } 2129 */ 2130 } 2131 2132 MsgRouting AwtComponent::WmHScroll(UINT scrollCode, UINT pos, 2133 HWND hScrollbar) { 2134 if (hScrollbar && hScrollbar != GetHWnd()) { 2135 /* the last test should never happen */ 2136 AwtComponent* sb = GetComponent(hScrollbar); 2137 if (sb) { 2138 sb->WmHScroll(scrollCode, pos, hScrollbar); 2139 } 2140 } 2141 return mrDoDefault; 2142 } 2143 2144 MsgRouting AwtComponent::WmVScroll(UINT scrollCode, UINT pos, HWND hScrollbar) 2145 { 2146 if (hScrollbar && hScrollbar != GetHWnd()) { 2147 /* the last test should never happen */ 2148 AwtComponent* sb = GetComponent(hScrollbar); 2149 if (sb) { 2150 sb->WmVScroll(scrollCode, pos, hScrollbar); 2151 } 2152 } 2153 return mrDoDefault; 2154 } 2155 2156 2157 MsgRouting AwtComponent::WmPaint(HDC) 2158 { 2159 /* Get the rectangle that covers all update regions, if any exist. */ 2160 RECT r; 2161 if (::GetUpdateRect(GetHWnd(), &r, FALSE)) { 2162 if ((r.right-r.left) > 0 && (r.bottom-r.top) > 0 && 2163 m_peerObject != NULL && m_callbacksEnabled) { 2164 /* 2165 * Always call handlePaint, because the underlying control 2166 * will have painted itself (the "background") before any 2167 * paint method is called. 2168 */ 2169 DoCallback("handlePaint", "(IIII)V", 2170 r.left, r.top, r.right-r.left, r.bottom-r.top); 2171 } 2172 } 2173 return mrDoDefault; 2174 } 2175 2176 void AwtComponent::PaintUpdateRgn(const RECT *insets) 2177 { 2178 // Fix 4530093: Don't Validate if can't actually paint 2179 if (m_peerObject == NULL || !m_callbacksEnabled) { 2180 2181 // Fix 4745222: If we don't ValidateRgn, windows will keep sending 2182 // WM_PAINT messages until we do. This causes java to go into 2183 // a tight loop that increases CPU to 100% and starves main 2184 // thread which needs to complete initialization, but cant. 2185 ::ValidateRgn(GetHWnd(), NULL); 2186 2187 return; 2188 } 2189 2190 HRGN rgn = ::CreateRectRgn(0,0,1,1); 2191 int updated = ::GetUpdateRgn(GetHWnd(), rgn, FALSE); 2192 /* 2193 * Now remove all update regions from this window -- do it 2194 * here instead of after the Java upcall, in case any new 2195 * updating is requested. 2196 */ 2197 ::ValidateRgn(GetHWnd(), NULL); 2198 2199 if (updated == COMPLEXREGION || updated == SIMPLEREGION) { 2200 if (insets != NULL) { 2201 ::OffsetRgn(rgn, insets->left, insets->top); 2202 } 2203 DWORD size = ::GetRegionData(rgn, 0, NULL); 2204 if (size == 0) { 2205 ::DeleteObject((HGDIOBJ)rgn); 2206 return; 2207 } 2208 char* buffer = new char[size]; // safe because sizeof(char)==1 2209 memset(buffer, 0, size); 2210 LPRGNDATA rgndata = (LPRGNDATA)buffer; 2211 rgndata->rdh.dwSize = sizeof(RGNDATAHEADER); 2212 rgndata->rdh.iType = RDH_RECTANGLES; 2213 int retCode = ::GetRegionData(rgn, size, rgndata); 2214 VERIFY(retCode); 2215 if (retCode == 0) { 2216 delete [] buffer; 2217 ::DeleteObject((HGDIOBJ)rgn); 2218 return; 2219 } 2220 /* 2221 * Updating rects are divided into mostly vertical and mostly horizontal 2222 * Each group is united together and if not empty painted separately 2223 */ 2224 RECT* r = (RECT*)(buffer + rgndata->rdh.dwSize); 2225 RECT* un[2] = {0, 0}; 2226 DWORD i; 2227 for (i = 0; i < rgndata->rdh.nCount; i++, r++) { 2228 int width = r->right-r->left; 2229 int height = r->bottom-r->top; 2230 if (width > 0 && height > 0) { 2231 int toAdd = (width > height) ? 0: 1; 2232 if (un[toAdd] != 0) { 2233 ::UnionRect(un[toAdd], un[toAdd], r); 2234 } else { 2235 un[toAdd] = r; 2236 } 2237 } 2238 } 2239 for(i = 0; i < 2; i++) { 2240 if (un[i] != 0) { 2241 DoCallback("handleExpose", "(IIII)V", 2242 ScaleDownX(un[i]->left), 2243 ScaleDownY(un[i]->top), 2244 ScaleDownX(un[i]->right - un[i]->left), 2245 ScaleDownY(un[i]->bottom - un[i]->top)); 2246 } 2247 } 2248 delete [] buffer; 2249 } 2250 ::DeleteObject((HGDIOBJ)rgn); 2251 } 2252 2253 MsgRouting AwtComponent::WmMouseEnter(UINT flags, int x, int y) 2254 { 2255 SendMouseEvent(java_awt_event_MouseEvent_MOUSE_ENTERED, 2256 ::JVM_CurrentTimeMillis(NULL, 0), x, y, GetJavaModifiers(), 0, JNI_FALSE); 2257 if ((flags & ALL_MK_BUTTONS) == 0) { 2258 AwtCursor::UpdateCursor(this); 2259 } 2260 sm_cursorOn = GetHWnd(); 2261 return mrConsume; /* Don't pass our synthetic event on! */ 2262 } 2263 2264 MSG* 2265 AwtComponent::CreateMessage(UINT message, WPARAM wParam, LPARAM lParam, 2266 int x = 0, int y = 0) 2267 { 2268 MSG* pMsg = new MSG; 2269 InitMessage(pMsg, message, wParam, lParam, x, y); 2270 return pMsg; 2271 } 2272 2273 2274 jint 2275 AwtComponent::GetDrawState(HWND hwnd) { 2276 return (jint)(INT_PTR)(::GetProp(hwnd, DrawingStateProp)); 2277 } 2278 2279 void 2280 AwtComponent::SetDrawState(HWND hwnd, jint state) { 2281 ::SetProp(hwnd, DrawingStateProp, (HANDLE)(INT_PTR)state); 2282 } 2283 2284 void 2285 AwtComponent::InitMessage(MSG* msg, UINT message, WPARAM wParam, LPARAM lParam, 2286 int x = 0, int y = 0) 2287 { 2288 msg->message = message; 2289 msg->wParam = wParam; 2290 msg->lParam = lParam; 2291 msg->time = ::GetMessageTime(); 2292 msg->pt.x = x; 2293 msg->pt.y = y; 2294 } 2295 2296 MsgRouting AwtComponent::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) { 2297 return mrDoDefault; 2298 } 2299 MsgRouting AwtComponent::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) { 2300 return mrDoDefault; 2301 } 2302 2303 MsgRouting AwtComponent::WmWindowPosChanging(LPARAM windowPos) { 2304 return mrDoDefault; 2305 } 2306 MsgRouting AwtComponent::WmWindowPosChanged(LPARAM windowPos) { 2307 return mrDoDefault; 2308 } 2309 2310 void AwtComponent::WmTouch(WPARAM wParam, LPARAM lParam) { 2311 AwtToolkit& tk = AwtToolkit::GetInstance(); 2312 if (!tk.IsWin8OrLater() || !tk.IsTouchKeyboardAutoShowEnabled()) { 2313 return; 2314 } 2315 2316 UINT inputsCount = LOWORD(wParam); 2317 TOUCHINPUT* pInputs = new TOUCHINPUT[inputsCount]; 2318 if (pInputs != NULL) { 2319 if (tk.TIGetTouchInputInfo((HTOUCHINPUT)lParam, inputsCount, pInputs, 2320 sizeof(TOUCHINPUT)) != 0) { 2321 for (UINT i = 0; i < inputsCount; i++) { 2322 TOUCHINPUT ti = pInputs[i]; 2323 if (ti.dwFlags & TOUCHEVENTF_PRIMARY) { 2324 if (ti.dwFlags & TOUCHEVENTF_DOWN) { 2325 m_touchDownPoint.x = ti.x / 100; 2326 m_touchDownPoint.y = ti.y / 100; 2327 ::ScreenToClient(GetHWnd(), &m_touchDownPoint); 2328 m_touchDownOccurred = TRUE; 2329 } else if (ti.dwFlags & TOUCHEVENTF_UP) { 2330 m_touchUpPoint.x = ti.x / 100; 2331 m_touchUpPoint.y = ti.y / 100; 2332 ::ScreenToClient(GetHWnd(), &m_touchUpPoint); 2333 m_touchUpOccurred = TRUE; 2334 } 2335 } 2336 } 2337 } 2338 delete[] pInputs; 2339 } 2340 } 2341 2342 /* Double-click variables. */ 2343 static jlong multiClickTime = ::GetDoubleClickTime(); 2344 static int multiClickMaxX = ::GetSystemMetrics(SM_CXDOUBLECLK); 2345 static int multiClickMaxY = ::GetSystemMetrics(SM_CYDOUBLECLK); 2346 static AwtComponent* lastClickWnd = NULL; 2347 static jlong lastTime = 0; 2348 static int lastClickX = 0; 2349 static int lastClickY = 0; 2350 static int lastButton = 0; 2351 static int clickCount = 0; 2352 2353 // A static method that makes the clickCount available in the derived classes 2354 // overriding WmMouseDown(). 2355 int AwtComponent::GetClickCount() 2356 { 2357 return clickCount; 2358 } 2359 2360 MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button) 2361 { 2362 jlong now = ::JVM_CurrentTimeMillis(NULL, 0); 2363 2364 if (lastClickWnd == this && 2365 lastButton == button && 2366 (now - lastTime) <= multiClickTime && 2367 abs(x - lastClickX) <= multiClickMaxX && 2368 abs(y - lastClickY) <= multiClickMaxY) 2369 { 2370 clickCount++; 2371 } else { 2372 clickCount = 1; 2373 lastClickWnd = this; 2374 lastButton = button; 2375 lastClickX = x; 2376 lastClickY = y; 2377 } 2378 /* 2379 *Set appropriate bit of the mask on WM_MOUSE_DOWN message. 2380 */ 2381 m_mouseButtonClickAllowed |= GetButtonMK(button); 2382 lastTime = now; 2383 2384 BOOL causedByTouchEvent = FALSE; 2385 if (m_touchDownOccurred && 2386 (abs(m_touchDownPoint.x - x) <= TOUCH_MOUSE_COORDS_DELTA) && 2387 (abs(m_touchDownPoint.y - y) <= TOUCH_MOUSE_COORDS_DELTA)) { 2388 causedByTouchEvent = TRUE; 2389 m_touchDownOccurred = FALSE; 2390 } 2391 2392 MSG msg; 2393 InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); 2394 2395 AwtWindow *toplevel = GetContainer(); 2396 if (toplevel && !toplevel->IsSimpleWindow()) { 2397 /* 2398 * The frame should be focused by click in case it is 2399 * the active window but not the focused window. See 6886678. 2400 */ 2401 if (toplevel->GetHWnd() == ::GetActiveWindow() && 2402 toplevel->GetHWnd() != AwtComponent::GetFocusedWindow()) 2403 { 2404 toplevel->AwtSetActiveWindow(); 2405 } 2406 } 2407 2408 SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y, 2409 GetJavaModifiers(), clickCount, JNI_FALSE, 2410 GetButton(button), &msg, causedByTouchEvent); 2411 /* 2412 * NOTE: this call is intentionally placed after all other code, 2413 * since AwtComponent::WmMouseDown() assumes that the cached id of the 2414 * latest retrieved message (see lastMessage in awt_Component.cpp) 2415 * matches the mouse message being processed. 2416 * SetCapture() sends WM_CAPTURECHANGED and breaks that 2417 * assumption. 2418 */ 2419 SetDragCapture(flags); 2420 2421 AwtWindow * owner = (AwtWindow*)GetComponent(GetTopLevelParentForWindow(GetHWnd())); 2422 if (AwtWindow::GetGrabbedWindow() != NULL && owner != NULL) { 2423 if (!AwtWindow::GetGrabbedWindow()->IsOneOfOwnersOf(owner)) { 2424 AwtWindow::GetGrabbedWindow()->Ungrab(); 2425 } 2426 } 2427 return mrConsume; 2428 } 2429 2430 MsgRouting AwtComponent::WmMouseUp(UINT flags, int x, int y, int button) 2431 { 2432 BOOL causedByTouchEvent = FALSE; 2433 if (m_touchUpOccurred && 2434 (abs(m_touchUpPoint.x - x) <= TOUCH_MOUSE_COORDS_DELTA) && 2435 (abs(m_touchUpPoint.y - y) <= TOUCH_MOUSE_COORDS_DELTA)) { 2436 causedByTouchEvent = TRUE; 2437 m_touchUpOccurred = FALSE; 2438 } 2439 2440 MSG msg; 2441 InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); 2442 2443 SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, ::JVM_CurrentTimeMillis(NULL, 0), 2444 x, y, GetJavaModifiers(), clickCount, 2445 (GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ? 2446 TRUE : FALSE), GetButton(button), &msg, causedByTouchEvent); 2447 /* 2448 * If no movement, then report a click following the button release. 2449 * When WM_MOUSEUP comes to a window without previous WM_MOUSEDOWN, 2450 * spurous MOUSE_CLICK is about to happen. See 6430553. 2451 */ 2452 if ((m_mouseButtonClickAllowed & GetButtonMK(button)) != 0) { //CLICK allowed 2453 SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED, 2454 ::JVM_CurrentTimeMillis(NULL, 0), x, y, GetJavaModifiers(), 2455 clickCount, JNI_FALSE, GetButton(button)); 2456 } 2457 // Exclude button from allowed to generate CLICK messages 2458 m_mouseButtonClickAllowed &= ~GetButtonMK(button); 2459 2460 if ((flags & ALL_MK_BUTTONS) == 0) { 2461 // only update if all buttons have been released 2462 AwtCursor::UpdateCursor(this); 2463 } 2464 /* 2465 * NOTE: this call is intentionally placed after all other code, 2466 * since AwtComponent::WmMouseUp() assumes that the cached id of the 2467 * latest retrieved message (see lastMessage in awt_Component.cpp) 2468 * matches the mouse message being processed. 2469 * ReleaseCapture() sends WM_CAPTURECHANGED and breaks that 2470 * assumption. 2471 */ 2472 ReleaseDragCapture(flags); 2473 2474 return mrConsume; 2475 } 2476 2477 MsgRouting AwtComponent::WmMouseMove(UINT flags, int x, int y) 2478 { 2479 static AwtComponent* lastComp = NULL; 2480 static int lastX = 0; 2481 static int lastY = 0; 2482 2483 /* 2484 * Only report mouse move and drag events if a move or drag 2485 * actually happened -- Windows sends a WM_MOUSEMOVE in case the 2486 * app wants to modify the cursor. 2487 */ 2488 if (lastComp != this || x != lastX || y != lastY) { 2489 lastComp = this; 2490 lastX = x; 2491 lastY = y; 2492 BOOL extraButtonsEnabled = AwtToolkit::GetInstance().areExtraMouseButtonsEnabled(); 2493 if (((flags & (ALL_MK_BUTTONS)) != 0) || 2494 (extraButtonsEnabled && (flags & (X_BUTTONS)) != 0)) 2495 // if (( extraButtonsEnabled && ( (flags & (ALL_MK_BUTTONS | X_BUTTONS)) != 0 )) || 2496 // ( !extraButtonsEnabled && (((flags & (ALL_MK_BUTTONS)) != 0 )) && ((flags & (X_BUTTONS)) == 0) )) 2497 { 2498 // 6404008 : if Dragged event fired we shouldn't fire 2499 // Clicked event: m_firstDragSent set to TRUE. 2500 // This is a partial backout of 5039416 fix. 2501 MSG msg; 2502 InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); 2503 SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, ::JVM_CurrentTimeMillis(NULL, 0), x, y, 2504 GetJavaModifiers(), 0, JNI_FALSE, 2505 java_awt_event_MouseEvent_NOBUTTON, &msg); 2506 //dragging means no more CLICKs until next WM_MOUSE_DOWN/WM_MOUSE_UP message sequence 2507 m_mouseButtonClickAllowed = 0; 2508 } else { 2509 MSG msg; 2510 InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); 2511 SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, ::JVM_CurrentTimeMillis(NULL, 0), x, y, 2512 GetJavaModifiers(), 0, JNI_FALSE, 2513 java_awt_event_MouseEvent_NOBUTTON, &msg); 2514 } 2515 } 2516 2517 return mrConsume; 2518 } 2519 2520 MsgRouting AwtComponent::WmMouseExit(UINT flags, int x, int y) 2521 { 2522 SendMouseEvent(java_awt_event_MouseEvent_MOUSE_EXITED, ::JVM_CurrentTimeMillis(NULL, 0), x, 2523 y, GetJavaModifiers(), 0, JNI_FALSE); 2524 sm_cursorOn = NULL; 2525 return mrConsume; /* Don't pass our synthetic event on! */ 2526 } 2527 2528 MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y, 2529 int wheelRotation, BOOL isHorizontal) 2530 { 2531 // convert coordinates to be Component-relative, not screen relative 2532 // for wheeling when outside the window, this works similar to 2533 // coordinates during a drag 2534 POINT eventPt; 2535 eventPt.x = x; 2536 eventPt.y = y; 2537 DTRACE_PRINT2(" original coords: %i,%i\n", x, y); 2538 ::ScreenToClient(GetHWnd(), &eventPt); 2539 DTRACE_PRINT2(" new coords: %i,%i\n\n", eventPt.x, eventPt.y); 2540 2541 // set some defaults 2542 jint scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL; 2543 jint scrollUnits = 3; 2544 2545 BOOL result; 2546 UINT platformUnits; 2547 jint roundedWheelRotation; 2548 jdouble preciseWheelRotation; 2549 2550 // AWT interprets wheel rotation differently than win32, so we need to 2551 // decode wheel amount. 2552 jint modifiers = GetJavaModifiers(); 2553 if (isHorizontal) { 2554 modifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK; 2555 m_wheelRotationAmountX += wheelRotation; 2556 roundedWheelRotation = m_wheelRotationAmountX / (WHEEL_DELTA); 2557 preciseWheelRotation = (jdouble) wheelRotation / (WHEEL_DELTA); 2558 result = ::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, 2559 &platformUnits, 0); 2560 } else { 2561 m_wheelRotationAmountY += wheelRotation; 2562 roundedWheelRotation = m_wheelRotationAmountY / (-1 * WHEEL_DELTA); 2563 preciseWheelRotation = (jdouble) wheelRotation / (-1 * WHEEL_DELTA); 2564 result = ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, 2565 &platformUnits, 0); 2566 } 2567 2568 MSG msg; 2569 InitMessage(&msg, lastMessage, MAKEWPARAM(flags, wheelRotation), 2570 MAKELPARAM(x, y)); 2571 2572 if (result) { 2573 if (platformUnits == WHEEL_PAGESCROLL) { 2574 scrollType = java_awt_event_MouseWheelEvent_WHEEL_BLOCK_SCROLL; 2575 scrollUnits = 1; 2576 } 2577 else { 2578 scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL; 2579 scrollUnits = platformUnits; 2580 } 2581 } 2582 2583 DTRACE_PRINTLN("calling SendMouseWheelEvent"); 2584 2585 SendMouseWheelEvent(java_awt_event_MouseEvent_MOUSE_WHEEL, ::JVM_CurrentTimeMillis(NULL, 0), 2586 eventPt.x, eventPt.y, modifiers, 0, 0, scrollType, 2587 scrollUnits, roundedWheelRotation, preciseWheelRotation, &msg); 2588 2589 m_wheelRotationAmountX %= WHEEL_DELTA; 2590 m_wheelRotationAmountY %= WHEEL_DELTA; 2591 // this message could be propagated up to the parent chain 2592 // by the mouse message post processors 2593 return mrConsume; 2594 } 2595 2596 jint AwtComponent::GetKeyLocation(UINT wkey, UINT flags) { 2597 // Rector+Newcomer page 413 2598 // The extended keys are the Alt and Control on the right of 2599 // the space bar, the non-Numpad arrow keys, the non-Numpad 2600 // Insert, PageUp, etc. keys, and the Numpad Divide and Enter keys. 2601 // Note that neither Shift key is extended. 2602 // Although not listed in Rector+Newcomer, both Windows keys 2603 // (91 and 92) are extended keys, the Context Menu key 2604 // (property key or application key - 93) is extended, 2605 // and so is the NumLock key. 2606 2607 // wkey is the wParam, flags is the HIWORD of the lParam 2608 2609 // "Extended" bit is 24th in lParam, so it's 8th in flags = HIWORD(lParam) 2610 BOOL extended = ((1<<8) & flags); 2611 2612 if (IsNumPadKey(wkey, extended)) { 2613 return java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD; 2614 } 2615 2616 switch (wkey) { 2617 case VK_SHIFT: 2618 return AwtComponent::GetShiftKeyLocation(wkey, flags); 2619 case VK_CONTROL: // fall through 2620 case VK_MENU: 2621 if (extended) { 2622 return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; 2623 } else { 2624 return java_awt_event_KeyEvent_KEY_LOCATION_LEFT; 2625 } 2626 case VK_LWIN: 2627 return java_awt_event_KeyEvent_KEY_LOCATION_LEFT; 2628 case VK_RWIN: 2629 return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; 2630 default: 2631 break; 2632 } 2633 2634 // REMIND: if we add keycodes for the windows keys, we'll have to 2635 // include left/right discrimination code for them. 2636 2637 return java_awt_event_KeyEvent_KEY_LOCATION_STANDARD; 2638 } 2639 2640 jint AwtComponent::GetShiftKeyLocation(UINT vkey, UINT flags) 2641 { 2642 // init scancodes to safe values 2643 UINT leftShiftScancode = 0; 2644 UINT rightShiftScancode = 0; 2645 2646 // First 8 bits of flags is the scancode 2647 UINT keyScanCode = flags & 0xFF; 2648 2649 DTRACE_PRINTLN3( 2650 "AwtComponent::GetShiftKeyLocation vkey = %d = 0x%x scan = %d", 2651 vkey, vkey, keyScanCode); 2652 2653 leftShiftScancode = ::MapVirtualKey(VK_LSHIFT, 0); 2654 rightShiftScancode = ::MapVirtualKey(VK_RSHIFT, 0); 2655 2656 if (keyScanCode == leftShiftScancode) { 2657 return java_awt_event_KeyEvent_KEY_LOCATION_LEFT; 2658 } 2659 if (keyScanCode == rightShiftScancode) { 2660 return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; 2661 } 2662 2663 DASSERT(false); 2664 // Note: the above should not fail on NT (or 2000) 2665 2666 // default value 2667 return java_awt_event_KeyEvent_KEY_LOCATION_LEFT; 2668 } 2669 2670 /* Returns Java ActionEvent modifieres. 2671 * When creating ActionEvent, modifiers provided by ActionEvent 2672 * class should be set. 2673 */ 2674 jint 2675 AwtComponent::GetActionModifiers() 2676 { 2677 jint modifiers = GetJavaModifiers(); 2678 2679 if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) { 2680 modifiers |= java_awt_event_ActionEvent_CTRL_MASK; 2681 } 2682 if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) { 2683 modifiers |= java_awt_event_ActionEvent_SHIFT_MASK; 2684 } 2685 if (modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) { 2686 modifiers |= java_awt_event_ActionEvent_ALT_MASK; 2687 } 2688 return modifiers; 2689 } 2690 2691 /* Returns Java extended InputEvent modifieres. 2692 * Since ::GetKeyState returns current state and Java modifiers represent 2693 * state before event, modifier on changed key are inverted. 2694 */ 2695 jint 2696 AwtComponent::GetJavaModifiers() 2697 { 2698 jint modifiers = 0; 2699 2700 if (HIBYTE(::GetKeyState(VK_CONTROL)) != 0) { 2701 modifiers |= java_awt_event_InputEvent_CTRL_DOWN_MASK; 2702 } 2703 if (HIBYTE(::GetKeyState(VK_SHIFT)) != 0) { 2704 modifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK; 2705 } 2706 if (HIBYTE(::GetKeyState(VK_MENU)) != 0) { 2707 modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK; 2708 } 2709 if (HIBYTE(::GetKeyState(VK_RMENU)) != 0) { 2710 modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK; 2711 } 2712 if (HIBYTE(::GetKeyState(VK_MBUTTON)) != 0) { 2713 modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK; 2714 } 2715 if (HIBYTE(::GetKeyState(VK_RBUTTON)) != 0) { 2716 modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK; 2717 } 2718 if (HIBYTE(::GetKeyState(VK_LBUTTON)) != 0) { 2719 modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK; 2720 } 2721 2722 if (HIBYTE(::GetKeyState(VK_XBUTTON1)) != 0) { 2723 modifiers |= masks[3]; 2724 } 2725 if (HIBYTE(::GetKeyState(VK_XBUTTON2)) != 0) { 2726 modifiers |= masks[4]; 2727 } 2728 return modifiers; 2729 } 2730 2731 jint 2732 AwtComponent::GetButton(int mouseButton) 2733 { 2734 /* Mouse buttons are already set correctly for left/right handedness */ 2735 switch(mouseButton) { 2736 case LEFT_BUTTON: 2737 return java_awt_event_MouseEvent_BUTTON1; 2738 case MIDDLE_BUTTON: 2739 return java_awt_event_MouseEvent_BUTTON2; 2740 case RIGHT_BUTTON: 2741 return java_awt_event_MouseEvent_BUTTON3; 2742 case X1_BUTTON: //16 : 2743 //just assign 4 and 5 numbers because MouseEvent class doesn't contain const identifier for them now 2744 return 4; 2745 case X2_BUTTON: //32 2746 return 5; 2747 } 2748 return java_awt_event_MouseEvent_NOBUTTON; 2749 } 2750 2751 UINT 2752 AwtComponent::GetButtonMK(int mouseButton) 2753 { 2754 switch(mouseButton) { 2755 case LEFT_BUTTON: 2756 return MK_LBUTTON; 2757 case MIDDLE_BUTTON: 2758 return MK_MBUTTON; 2759 case RIGHT_BUTTON: 2760 return MK_RBUTTON; 2761 case X1_BUTTON: 2762 return MK_XBUTTON1; 2763 case X2_BUTTON: 2764 return MK_XBUTTON2; 2765 } 2766 return 0; 2767 } 2768 2769 // FIXME: Keyboard related stuff has grown so big and hairy that we 2770 // really need to move it into a class of its own. And, since 2771 // keyboard is a shared resource, AwtComponent is a bad place for it. 2772 2773 // These constants are defined in the Japanese version of VC++5.0, 2774 // but not the US version 2775 #ifndef VK_CONVERT 2776 #define VK_KANA 0x15 2777 #define VK_KANJI 0x19 2778 #define VK_CONVERT 0x1C 2779 #define VK_NONCONVERT 0x1D 2780 #endif 2781 2782 #ifndef VK_XBUTTON1 2783 #define VK_XBUTTON1 0x05 2784 #endif 2785 2786 #ifndef VK_XBUTTON2 2787 #define VK_XBUTTON2 0x06 2788 #endif 2789 2790 typedef struct { 2791 UINT javaKey; 2792 UINT windowsKey; 2793 } KeyMapEntry; 2794 2795 // Static table, arranged more or less spatially. 2796 KeyMapEntry keyMapTable[] = { 2797 // Modifier keys 2798 {java_awt_event_KeyEvent_VK_CAPS_LOCK, VK_CAPITAL}, 2799 {java_awt_event_KeyEvent_VK_SHIFT, VK_SHIFT}, 2800 {java_awt_event_KeyEvent_VK_CONTROL, VK_CONTROL}, 2801 {java_awt_event_KeyEvent_VK_ALT, VK_MENU}, 2802 {java_awt_event_KeyEvent_VK_ALT_GRAPH, VK_RMENU}, 2803 {java_awt_event_KeyEvent_VK_NUM_LOCK, VK_NUMLOCK}, 2804 2805 // Miscellaneous Windows keys 2806 {java_awt_event_KeyEvent_VK_WINDOWS, VK_LWIN}, 2807 {java_awt_event_KeyEvent_VK_WINDOWS, VK_RWIN}, 2808 {java_awt_event_KeyEvent_VK_CONTEXT_MENU, VK_APPS}, 2809 2810 // Alphabet 2811 {java_awt_event_KeyEvent_VK_A, 'A'}, 2812 {java_awt_event_KeyEvent_VK_B, 'B'}, 2813 {java_awt_event_KeyEvent_VK_C, 'C'}, 2814 {java_awt_event_KeyEvent_VK_D, 'D'}, 2815 {java_awt_event_KeyEvent_VK_E, 'E'}, 2816 {java_awt_event_KeyEvent_VK_F, 'F'}, 2817 {java_awt_event_KeyEvent_VK_G, 'G'}, 2818 {java_awt_event_KeyEvent_VK_H, 'H'}, 2819 {java_awt_event_KeyEvent_VK_I, 'I'}, 2820 {java_awt_event_KeyEvent_VK_J, 'J'}, 2821 {java_awt_event_KeyEvent_VK_K, 'K'}, 2822 {java_awt_event_KeyEvent_VK_L, 'L'}, 2823 {java_awt_event_KeyEvent_VK_M, 'M'}, 2824 {java_awt_event_KeyEvent_VK_N, 'N'}, 2825 {java_awt_event_KeyEvent_VK_O, 'O'}, 2826 {java_awt_event_KeyEvent_VK_P, 'P'}, 2827 {java_awt_event_KeyEvent_VK_Q, 'Q'}, 2828 {java_awt_event_KeyEvent_VK_R, 'R'}, 2829 {java_awt_event_KeyEvent_VK_S, 'S'}, 2830 {java_awt_event_KeyEvent_VK_T, 'T'}, 2831 {java_awt_event_KeyEvent_VK_U, 'U'}, 2832 {java_awt_event_KeyEvent_VK_V, 'V'}, 2833 {java_awt_event_KeyEvent_VK_W, 'W'}, 2834 {java_awt_event_KeyEvent_VK_X, 'X'}, 2835 {java_awt_event_KeyEvent_VK_Y, 'Y'}, 2836 {java_awt_event_KeyEvent_VK_Z, 'Z'}, 2837 2838 // Standard numeric row 2839 {java_awt_event_KeyEvent_VK_0, '0'}, 2840 {java_awt_event_KeyEvent_VK_1, '1'}, 2841 {java_awt_event_KeyEvent_VK_2, '2'}, 2842 {java_awt_event_KeyEvent_VK_3, '3'}, 2843 {java_awt_event_KeyEvent_VK_4, '4'}, 2844 {java_awt_event_KeyEvent_VK_5, '5'}, 2845 {java_awt_event_KeyEvent_VK_6, '6'}, 2846 {java_awt_event_KeyEvent_VK_7, '7'}, 2847 {java_awt_event_KeyEvent_VK_8, '8'}, 2848 {java_awt_event_KeyEvent_VK_9, '9'}, 2849 2850 // Misc key from main block 2851 {java_awt_event_KeyEvent_VK_ENTER, VK_RETURN}, 2852 {java_awt_event_KeyEvent_VK_SPACE, VK_SPACE}, 2853 {java_awt_event_KeyEvent_VK_BACK_SPACE, VK_BACK}, 2854 {java_awt_event_KeyEvent_VK_TAB, VK_TAB}, 2855 {java_awt_event_KeyEvent_VK_ESCAPE, VK_ESCAPE}, 2856 2857 // NumPad with NumLock off & extended block (rectangular) 2858 {java_awt_event_KeyEvent_VK_INSERT, VK_INSERT}, 2859 {java_awt_event_KeyEvent_VK_DELETE, VK_DELETE}, 2860 {java_awt_event_KeyEvent_VK_HOME, VK_HOME}, 2861 {java_awt_event_KeyEvent_VK_END, VK_END}, 2862 {java_awt_event_KeyEvent_VK_PAGE_UP, VK_PRIOR}, 2863 {java_awt_event_KeyEvent_VK_PAGE_DOWN, VK_NEXT}, 2864 {java_awt_event_KeyEvent_VK_CLEAR, VK_CLEAR}, // NumPad 5 2865 2866 // NumPad with NumLock off & extended arrows block (triangular) 2867 {java_awt_event_KeyEvent_VK_LEFT, VK_LEFT}, 2868 {java_awt_event_KeyEvent_VK_RIGHT, VK_RIGHT}, 2869 {java_awt_event_KeyEvent_VK_UP, VK_UP}, 2870 {java_awt_event_KeyEvent_VK_DOWN, VK_DOWN}, 2871 2872 // NumPad with NumLock on: numbers 2873 {java_awt_event_KeyEvent_VK_NUMPAD0, VK_NUMPAD0}, 2874 {java_awt_event_KeyEvent_VK_NUMPAD1, VK_NUMPAD1}, 2875 {java_awt_event_KeyEvent_VK_NUMPAD2, VK_NUMPAD2}, 2876 {java_awt_event_KeyEvent_VK_NUMPAD3, VK_NUMPAD3}, 2877 {java_awt_event_KeyEvent_VK_NUMPAD4, VK_NUMPAD4}, 2878 {java_awt_event_KeyEvent_VK_NUMPAD5, VK_NUMPAD5}, 2879 {java_awt_event_KeyEvent_VK_NUMPAD6, VK_NUMPAD6}, 2880 {java_awt_event_KeyEvent_VK_NUMPAD7, VK_NUMPAD7}, 2881 {java_awt_event_KeyEvent_VK_NUMPAD8, VK_NUMPAD8}, 2882 {java_awt_event_KeyEvent_VK_NUMPAD9, VK_NUMPAD9}, 2883 2884 // NumPad with NumLock on 2885 {java_awt_event_KeyEvent_VK_MULTIPLY, VK_MULTIPLY}, 2886 {java_awt_event_KeyEvent_VK_ADD, VK_ADD}, 2887 {java_awt_event_KeyEvent_VK_SEPARATOR, VK_SEPARATOR}, 2888 {java_awt_event_KeyEvent_VK_SUBTRACT, VK_SUBTRACT}, 2889 {java_awt_event_KeyEvent_VK_DECIMAL, VK_DECIMAL}, 2890 {java_awt_event_KeyEvent_VK_DIVIDE, VK_DIVIDE}, 2891 2892 // Functional keys 2893 {java_awt_event_KeyEvent_VK_F1, VK_F1}, 2894 {java_awt_event_KeyEvent_VK_F2, VK_F2}, 2895 {java_awt_event_KeyEvent_VK_F3, VK_F3}, 2896 {java_awt_event_KeyEvent_VK_F4, VK_F4}, 2897 {java_awt_event_KeyEvent_VK_F5, VK_F5}, 2898 {java_awt_event_KeyEvent_VK_F6, VK_F6}, 2899 {java_awt_event_KeyEvent_VK_F7, VK_F7}, 2900 {java_awt_event_KeyEvent_VK_F8, VK_F8}, 2901 {java_awt_event_KeyEvent_VK_F9, VK_F9}, 2902 {java_awt_event_KeyEvent_VK_F10, VK_F10}, 2903 {java_awt_event_KeyEvent_VK_F11, VK_F11}, 2904 {java_awt_event_KeyEvent_VK_F12, VK_F12}, 2905 {java_awt_event_KeyEvent_VK_F13, VK_F13}, 2906 {java_awt_event_KeyEvent_VK_F14, VK_F14}, 2907 {java_awt_event_KeyEvent_VK_F15, VK_F15}, 2908 {java_awt_event_KeyEvent_VK_F16, VK_F16}, 2909 {java_awt_event_KeyEvent_VK_F17, VK_F17}, 2910 {java_awt_event_KeyEvent_VK_F18, VK_F18}, 2911 {java_awt_event_KeyEvent_VK_F19, VK_F19}, 2912 {java_awt_event_KeyEvent_VK_F20, VK_F20}, 2913 {java_awt_event_KeyEvent_VK_F21, VK_F21}, 2914 {java_awt_event_KeyEvent_VK_F22, VK_F22}, 2915 {java_awt_event_KeyEvent_VK_F23, VK_F23}, 2916 {java_awt_event_KeyEvent_VK_F24, VK_F24}, 2917 2918 {java_awt_event_KeyEvent_VK_PRINTSCREEN, VK_SNAPSHOT}, 2919 {java_awt_event_KeyEvent_VK_SCROLL_LOCK, VK_SCROLL}, 2920 {java_awt_event_KeyEvent_VK_PAUSE, VK_PAUSE}, 2921 {java_awt_event_KeyEvent_VK_CANCEL, VK_CANCEL}, 2922 {java_awt_event_KeyEvent_VK_HELP, VK_HELP}, 2923 2924 // Japanese 2925 {java_awt_event_KeyEvent_VK_CONVERT, VK_CONVERT}, 2926 {java_awt_event_KeyEvent_VK_NONCONVERT, VK_NONCONVERT}, 2927 {java_awt_event_KeyEvent_VK_INPUT_METHOD_ON_OFF, VK_KANJI}, 2928 {java_awt_event_KeyEvent_VK_ALPHANUMERIC, VK_DBE_ALPHANUMERIC}, 2929 {java_awt_event_KeyEvent_VK_KATAKANA, VK_DBE_KATAKANA}, 2930 {java_awt_event_KeyEvent_VK_HIRAGANA, VK_DBE_HIRAGANA}, 2931 {java_awt_event_KeyEvent_VK_FULL_WIDTH, VK_DBE_DBCSCHAR}, 2932 {java_awt_event_KeyEvent_VK_HALF_WIDTH, VK_DBE_SBCSCHAR}, 2933 {java_awt_event_KeyEvent_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN}, 2934 2935 {java_awt_event_KeyEvent_VK_UNDEFINED, 0} 2936 }; 2937 2938 2939 // Dynamic mapping table for OEM VK codes. This table is refilled 2940 // by BuildDynamicKeyMapTable when keyboard layout is switched. 2941 // (see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values). 2942 struct DynamicKeyMapEntry { 2943 UINT windowsKey; // OEM VK codes known in advance 2944 UINT javaKey; // depends on input langauge (kbd layout) 2945 }; 2946 2947 static DynamicKeyMapEntry dynamicKeyMapTable[] = { 2948 {0x00BA, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_1 2949 {0x00BB, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PLUS 2950 {0x00BC, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_COMMA 2951 {0x00BD, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_MINUS 2952 {0x00BE, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PERIOD 2953 {0x00BF, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_2 2954 {0x00C0, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_3 2955 {0x00DB, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_4 2956 {0x00DC, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_5 2957 {0x00DD, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_6 2958 {0x00DE, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_7 2959 {0x00DF, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_8 2960 {0x00E2, java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_102 2961 {0, 0} 2962 }; 2963 2964 2965 2966 // Auxiliary tables used to fill the above dynamic table. We first 2967 // find the character for the OEM VK code using ::MapVirtualKey and 2968 // then go through these auxiliary tables to map it to Java VK code. 2969 2970 struct CharToVKEntry { 2971 WCHAR c; 2972 UINT javaKey; 2973 }; 2974 2975 static const CharToVKEntry charToVKTable[] = { 2976 {L'!', java_awt_event_KeyEvent_VK_EXCLAMATION_MARK}, 2977 {L'"', java_awt_event_KeyEvent_VK_QUOTEDBL}, 2978 {L'#', java_awt_event_KeyEvent_VK_NUMBER_SIGN}, 2979 {L'$', java_awt_event_KeyEvent_VK_DOLLAR}, 2980 {L'&', java_awt_event_KeyEvent_VK_AMPERSAND}, 2981 {L'\'', java_awt_event_KeyEvent_VK_QUOTE}, 2982 {L'(', java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS}, 2983 {L')', java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS}, 2984 {L'*', java_awt_event_KeyEvent_VK_ASTERISK}, 2985 {L'+', java_awt_event_KeyEvent_VK_PLUS}, 2986 {L',', java_awt_event_KeyEvent_VK_COMMA}, 2987 {L'-', java_awt_event_KeyEvent_VK_MINUS}, 2988 {L'.', java_awt_event_KeyEvent_VK_PERIOD}, 2989 {L'/', java_awt_event_KeyEvent_VK_SLASH}, 2990 {L':', java_awt_event_KeyEvent_VK_COLON}, 2991 {L';', java_awt_event_KeyEvent_VK_SEMICOLON}, 2992 {L'<', java_awt_event_KeyEvent_VK_LESS}, 2993 {L'=', java_awt_event_KeyEvent_VK_EQUALS}, 2994 {L'>', java_awt_event_KeyEvent_VK_GREATER}, 2995 {L'@', java_awt_event_KeyEvent_VK_AT}, 2996 {L'[', java_awt_event_KeyEvent_VK_OPEN_BRACKET}, 2997 {L'\\', java_awt_event_KeyEvent_VK_BACK_SLASH}, 2998 {L']', java_awt_event_KeyEvent_VK_CLOSE_BRACKET}, 2999 {L'^', java_awt_event_KeyEvent_VK_CIRCUMFLEX}, 3000 {L'_', java_awt_event_KeyEvent_VK_UNDERSCORE}, 3001 {L'`', java_awt_event_KeyEvent_VK_BACK_QUOTE}, 3002 {L'{', java_awt_event_KeyEvent_VK_BRACELEFT}, 3003 {L'}', java_awt_event_KeyEvent_VK_BRACERIGHT}, 3004 {0x00A1, java_awt_event_KeyEvent_VK_INVERTED_EXCLAMATION_MARK}, 3005 {0x20A0, java_awt_event_KeyEvent_VK_EURO_SIGN}, // ???? 3006 {0,0} 3007 }; 3008 3009 // For dead accents some layouts return ASCII punctuation, while some 3010 // return spacing accent chars, so both should be listed. NB: MS docs 3011 // say that conversion routings return spacing accent character, not 3012 // combining. 3013 static const CharToVKEntry charToDeadVKTable[] = { 3014 {L'`', java_awt_event_KeyEvent_VK_DEAD_GRAVE}, 3015 {L'\'', java_awt_event_KeyEvent_VK_DEAD_ACUTE}, 3016 {0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE}, 3017 {L'^', java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX}, 3018 {L'~', java_awt_event_KeyEvent_VK_DEAD_TILDE}, 3019 {0x02DC, java_awt_event_KeyEvent_VK_DEAD_TILDE}, 3020 {0x00AF, java_awt_event_KeyEvent_VK_DEAD_MACRON}, 3021 {0x02D8, java_awt_event_KeyEvent_VK_DEAD_BREVE}, 3022 {0x02D9, java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT}, 3023 {L'"', java_awt_event_KeyEvent_VK_DEAD_DIAERESIS}, 3024 {0x00A8, java_awt_event_KeyEvent_VK_DEAD_DIAERESIS}, 3025 {0x02DA, java_awt_event_KeyEvent_VK_DEAD_ABOVERING}, 3026 {0x02DD, java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE}, 3027 {0x02C7, java_awt_event_KeyEvent_VK_DEAD_CARON}, // aka hacek 3028 {L',', java_awt_event_KeyEvent_VK_DEAD_CEDILLA}, 3029 {0x00B8, java_awt_event_KeyEvent_VK_DEAD_CEDILLA}, 3030 {0x02DB, java_awt_event_KeyEvent_VK_DEAD_OGONEK}, 3031 {0x037A, java_awt_event_KeyEvent_VK_DEAD_IOTA}, // ASCII ??? 3032 {0x309B, java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND}, 3033 {0x309C, java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND}, 3034 {0x0004, java_awt_event_KeyEvent_VK_COMPOSE}, 3035 {0,0} 3036 }; 3037 3038 // The full map of the current keyboard state including 3039 // windows virtual key, scancode, java virtual key, and unicode 3040 // for this key sans modifiers. 3041 // All but first element may be 0. 3042 // XXX in the update releases this is an addition to the unchanged existing code 3043 struct DynPrimaryKeymapEntry { 3044 UINT wkey; 3045 UINT scancode; 3046 UINT jkey; 3047 WCHAR unicode; 3048 }; 3049 3050 static DynPrimaryKeymapEntry dynPrimaryKeymap[256]; 3051 3052 void 3053 AwtComponent::InitDynamicKeyMapTable() 3054 { 3055 static BOOL kbdinited = FALSE; 3056 3057 if (!kbdinited) { 3058 AwtComponent::BuildDynamicKeyMapTable(); 3059 // We cannot build it here since JNI is not available yet: 3060 //AwtComponent::BuildPrimaryDynamicTable(); 3061 kbdinited = TRUE; 3062 } 3063 } 3064 3065 void 3066 AwtComponent::BuildDynamicKeyMapTable() 3067 { 3068 HKL hkl = GetKeyboardLayout(); 3069 3070 DTRACE_PRINTLN2("Building dynamic VK mapping tables: HKL = %08X (CP%d)", 3071 hkl, AwtComponent::GetCodePage()); 3072 3073 // Will need this to reset layout after dead keys. 3074 UINT spaceScanCode = ::MapVirtualKeyEx(VK_SPACE, 0, hkl); 3075 3076 // Entries in dynamic table that maps between Java VK and Windows 3077 // VK are built in three steps: 3078 // 1. Map windows VK to ANSI character (cannot map to unicode 3079 // directly, since ::ToUnicode is not implemented on win9x) 3080 // 2. Convert ANSI char to Unicode char 3081 // 3. Map Unicode char to Java VK via two auxilary tables. 3082 3083 for (DynamicKeyMapEntry *dynamic = dynamicKeyMapTable; 3084 dynamic->windowsKey != 0; 3085 ++dynamic) 3086 { 3087 // Defaults to VK_UNDEFINED 3088 dynamic->javaKey = java_awt_event_KeyEvent_VK_UNDEFINED; 3089 3090 BYTE kbdState[AwtToolkit::KB_STATE_SIZE]; 3091 AwtToolkit::GetKeyboardState(kbdState); 3092 3093 kbdState[dynamic->windowsKey] |= 0x80; // Press the key. 3094 3095 // Unpress modifiers, since they are most likely pressed as 3096 // part of the keyboard switching shortcut. 3097 kbdState[VK_CONTROL] &= ~0x80; 3098 kbdState[VK_SHIFT] &= ~0x80; 3099 kbdState[VK_MENU] &= ~0x80; 3100 3101 char cbuf[2] = { '\0', '\0'}; 3102 UINT scancode = ::MapVirtualKeyEx(dynamic->windowsKey, 0, hkl); 3103 int nchars = ::ToAsciiEx(dynamic->windowsKey, scancode, kbdState, 3104 (WORD*)cbuf, 0, hkl); 3105 3106 // Auxiliary table used to map Unicode character to Java VK. 3107 // Will assign a different table for dead keys (below). 3108 const CharToVKEntry *charMap = charToVKTable; 3109 3110 if (nchars < 0) { // Dead key 3111 // Use a different table for dead chars since different layouts 3112 // return different characters for the same dead key. 3113 charMap = charToDeadVKTable; 3114 3115 // We also need to reset layout so that next translation 3116 // is unaffected by the dead status. We do this by 3117 // translating <SPACE> key. 3118 kbdState[dynamic->windowsKey] &= ~0x80; 3119 kbdState[VK_SPACE] |= 0x80; 3120 3121 char junkbuf[2] = { '\0', '\0'}; 3122 ::ToAsciiEx(VK_SPACE, spaceScanCode, kbdState, 3123 (WORD*)junkbuf, 0, hkl); 3124 } 3125 3126 #ifdef DEBUG 3127 if (nchars == 0) { 3128 DTRACE_PRINTLN1("VK 0x%02X -> cannot convert to ANSI char", 3129 dynamic->windowsKey); 3130 continue; 3131 } 3132 else if (nchars > 1) { // can't happen, see reset code below 3133 DTRACE_PRINTLN3("VK 0x%02X -> converted to <0x%02X,0x%02X>", 3134 dynamic->windowsKey, 3135 (UCHAR)cbuf[0], (UCHAR)cbuf[1]); 3136 continue; 3137 } 3138 #endif 3139 3140 WCHAR ucbuf[2] = { L'\0', L'\0' }; 3141 int nconverted = ::MultiByteToWideChar(AwtComponent::GetCodePage(), 0, 3142 cbuf, 1, ucbuf, 2); 3143 #ifdef DEBUG 3144 if (nconverted < 0) { 3145 DTRACE_PRINTLN3("VK 0x%02X -> ANSI 0x%02X -> MultiByteToWideChar failed (0x%X)", 3146 dynamic->windowsKey, (UCHAR)cbuf[0], 3147 ::GetLastError()); 3148 continue; 3149 } 3150 #endif 3151 3152 WCHAR uc = ucbuf[0]; 3153 for (const CharToVKEntry *map = charMap; map->c != 0; ++map) { 3154 if (uc == map->c) { 3155 dynamic->javaKey = map->javaKey; 3156 break; 3157 } 3158 } 3159 3160 DTRACE_PRINTLN4("VK 0x%02X -> ANSI 0x%02X -> U+%04X -> Java VK 0x%X", 3161 dynamic->windowsKey, (UCHAR)cbuf[0], (UINT)ucbuf[0], 3162 dynamic->javaKey); 3163 } // for each VK_OEM_* 3164 } 3165 3166 3167 static BOOL isKanaLockAvailable() 3168 { 3169 // This method is to determine whether the Kana Lock feature is 3170 // available on the attached keyboard. Kana Lock feature does not 3171 // necessarily require that the real KANA keytop is available on 3172 // keyboard, so using MapVirtualKey(VK_KANA) is not sufficient for testing. 3173 // Instead of that we regard it as Japanese keyboard (w/ Kana Lock) if :- 3174 // 3175 // - the keyboard layout is Japanese (VK_KANA has the same value as VK_HANGUL) 3176 // - the keyboard is Japanese keyboard (keyboard type == 7). 3177 return (LOWORD(GetKeyboardLayout(0)) == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)) 3178 && (GetKeyboardType(0) == 7); 3179 } 3180 3181 void AwtComponent::JavaKeyToWindowsKey(UINT javaKey, 3182 UINT *windowsKey, UINT *modifiers, UINT originalWindowsKey) 3183 { 3184 // Handle the few cases where a Java VK code corresponds to a Windows 3185 // key/modifier combination or applies only to specific keyboard layouts 3186 switch (javaKey) { 3187 case java_awt_event_KeyEvent_VK_ALL_CANDIDATES: 3188 *windowsKey = VK_CONVERT; 3189 *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK; 3190 return; 3191 case java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE: 3192 *windowsKey = VK_CONVERT; 3193 *modifiers = java_awt_event_InputEvent_SHIFT_DOWN_MASK; 3194 return; 3195 case java_awt_event_KeyEvent_VK_CODE_INPUT: 3196 *windowsKey = VK_DBE_ALPHANUMERIC; 3197 *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK; 3198 return; 3199 case java_awt_event_KeyEvent_VK_KANA_LOCK: 3200 if (isKanaLockAvailable()) { 3201 *windowsKey = VK_KANA; 3202 *modifiers = java_awt_event_InputEvent_CTRL_DOWN_MASK; 3203 return; 3204 } 3205 } 3206 3207 // for the general case, use a bi-directional table 3208 for (int i = 0; keyMapTable[i].windowsKey != 0; i++) { 3209 if (keyMapTable[i].javaKey == javaKey) { 3210 *windowsKey = keyMapTable[i].windowsKey; 3211 *modifiers = 0; 3212 return; 3213 } 3214 } 3215 3216 // Bug 4766655 3217 // Two Windows keys could map to the same Java key, so 3218 // give preference to the originalWindowsKey if it is 3219 // specified (not IGNORE_KEY). 3220 if (originalWindowsKey == IGNORE_KEY) { 3221 for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) { 3222 if (dynamicKeyMapTable[j].javaKey == javaKey) { 3223 *windowsKey = dynamicKeyMapTable[j].windowsKey; 3224 *modifiers = 0; 3225 return; 3226 } 3227 } 3228 } else { 3229 BOOL found = false; 3230 for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) { 3231 if (dynamicKeyMapTable[j].javaKey == javaKey) { 3232 *windowsKey = dynamicKeyMapTable[j].windowsKey; 3233 *modifiers = 0; 3234 found = true; 3235 if (*windowsKey == originalWindowsKey) { 3236 return; /* if ideal case found return, else keep looking */ 3237 } 3238 } 3239 } 3240 if (found) { 3241 return; 3242 } 3243 } 3244 3245 *windowsKey = 0; 3246 *modifiers = 0; 3247 return; 3248 } 3249 3250 UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey) 3251 3252 { 3253 // Handle the few cases where we need to take the modifier into 3254 // consideration for the Java VK code or where we have to take the keyboard 3255 // layout into consideration so that function keys can get 3256 // recognized in a platform-independent way. 3257 switch (windowsKey) { 3258 case VK_CONVERT: 3259 if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) { 3260 return java_awt_event_KeyEvent_VK_ALL_CANDIDATES; 3261 } 3262 if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0) { 3263 return java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE; 3264 } 3265 break; 3266 case VK_DBE_ALPHANUMERIC: 3267 if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) { 3268 return java_awt_event_KeyEvent_VK_CODE_INPUT; 3269 } 3270 break; 3271 case VK_KANA: 3272 if (isKanaLockAvailable()) { 3273 return java_awt_event_KeyEvent_VK_KANA_LOCK; 3274 } 3275 break; 3276 }; 3277 3278 // check dead key 3279 if (isDeadKey) { 3280 for (int i = 0; charToDeadVKTable[i].c != 0; i++) { 3281 if (charToDeadVKTable[i].c == character) { 3282 return charToDeadVKTable[i].javaKey; 3283 } 3284 } 3285 } 3286 3287 // for the general case, use a bi-directional table 3288 for (int i = 0; keyMapTable[i].windowsKey != 0; i++) { 3289 if (keyMapTable[i].windowsKey == windowsKey) { 3290 return keyMapTable[i].javaKey; 3291 } 3292 } 3293 3294 for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) { 3295 if (dynamicKeyMapTable[j].windowsKey == windowsKey) { 3296 if (dynamicKeyMapTable[j].javaKey != java_awt_event_KeyEvent_VK_UNDEFINED) { 3297 return dynamicKeyMapTable[j].javaKey; 3298 }else{ 3299 break; 3300 } 3301 } 3302 } 3303 3304 return java_awt_event_KeyEvent_VK_UNDEFINED; 3305 } 3306 3307 BOOL AwtComponent::IsNavigationKey(UINT wkey) { 3308 switch (wkey) { 3309 case VK_END: 3310 case VK_PRIOR: // PageUp 3311 case VK_NEXT: // PageDown 3312 case VK_HOME: 3313 case VK_LEFT: 3314 case VK_UP: 3315 case VK_RIGHT: 3316 case VK_DOWN: 3317 return TRUE; 3318 } 3319 return FALSE; 3320 } 3321 3322 // determine if a key is a numpad key (distinguishes the numpad 3323 // arrow keys from the non-numpad arrow keys, for example). 3324 BOOL AwtComponent::IsNumPadKey(UINT vkey, BOOL extended) 3325 { 3326 // Note: scancodes are the same for the numpad arrow keys and 3327 // the non-numpad arrow keys (also for PageUp, etc.). 3328 // The scancodes for the numpad divide and the non-numpad slash 3329 // are the same, but the wparams are different 3330 3331 DTRACE_PRINTLN3("AwtComponent::IsNumPadKey vkey = %d = 0x%x extended = %d", 3332 vkey, vkey, extended); 3333 3334 switch (vkey) { 3335 case VK_CLEAR: // numpad 5 with numlock off 3336 case VK_NUMPAD0: 3337 case VK_NUMPAD1: 3338 case VK_NUMPAD2: 3339 case VK_NUMPAD3: 3340 case VK_NUMPAD4: 3341 case VK_NUMPAD5: 3342 case VK_NUMPAD6: 3343 case VK_NUMPAD7: 3344 case VK_NUMPAD8: 3345 case VK_NUMPAD9: 3346 case VK_MULTIPLY: 3347 case VK_ADD: 3348 case VK_SEPARATOR: // numpad , not on US kbds 3349 case VK_SUBTRACT: 3350 case VK_DECIMAL: 3351 case VK_DIVIDE: 3352 case VK_NUMLOCK: 3353 return TRUE; 3354 break; 3355 case VK_END: 3356 case VK_PRIOR: // PageUp 3357 case VK_NEXT: // PageDown 3358 case VK_HOME: 3359 case VK_LEFT: 3360 case VK_UP: 3361 case VK_RIGHT: 3362 case VK_DOWN: 3363 case VK_INSERT: 3364 case VK_DELETE: 3365 // extended if non-numpad 3366 return (!extended); 3367 break; 3368 case VK_RETURN: // extended if on numpad 3369 return (extended); 3370 break; 3371 default: 3372 break; 3373 } 3374 3375 return FALSE; 3376 } 3377 static void 3378 resetKbdState( BYTE kstate[256]) { 3379 BYTE tmpState[256]; 3380 WCHAR wc[2]; 3381 memmove(tmpState, kstate, sizeof(kstate)); 3382 tmpState[VK_SHIFT] = 0; 3383 tmpState[VK_CONTROL] = 0; 3384 tmpState[VK_MENU] = 0; 3385 3386 ::ToUnicodeEx(VK_SPACE,::MapVirtualKey(VK_SPACE, 0), tmpState, wc, 2, 0, GetKeyboardLayout(0)); 3387 } 3388 3389 // XXX in the update releases this is an addition to the unchanged existing code 3390 // After the call, a table will have a unicode associated with a windows virtual keycode 3391 // sans modifiers. With some further simplification, one can 3392 // derive java keycode from it, and anyway we will pass this unicode value 3393 // all the way up in a comment to a KeyEvent. 3394 void 3395 AwtComponent::BuildPrimaryDynamicTable() { 3396 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 3397 // XXX: how about that? 3398 //CriticalSection::Lock l(GetLock()); 3399 //if (GetPeer(env) == NULL) { 3400 // /* event received during termination. */ 3401 // return; 3402 //} 3403 3404 HKL hkl = GetKeyboardLayout(); 3405 UINT sc = 0; 3406 BYTE kbdState[AwtToolkit::KB_STATE_SIZE]; 3407 memset(kbdState, 0, sizeof (kbdState)); 3408 3409 // Use JNI call to obtain java key code. We should keep a list 3410 // of currently available keycodes in a single place. 3411 static jclass extKeyCodesCls; 3412 if( extKeyCodesCls == NULL) { 3413 jclass extKeyCodesClsLocal = env->FindClass("sun/awt/ExtendedKeyCodes"); 3414 DASSERT(extKeyCodesClsLocal); 3415 CHECK_NULL(extKeyCodesClsLocal); 3416 extKeyCodesCls = (jclass)env->NewGlobalRef(extKeyCodesClsLocal); 3417 env->DeleteLocalRef(extKeyCodesClsLocal); 3418 } 3419 static jmethodID getExtendedKeyCodeForChar; 3420 if (getExtendedKeyCodeForChar == NULL) { 3421 getExtendedKeyCodeForChar = 3422 env->GetStaticMethodID(extKeyCodesCls, "getExtendedKeyCodeForChar", "(I)I"); 3423 DASSERT(getExtendedKeyCodeForChar); 3424 CHECK_NULL(getExtendedKeyCodeForChar); 3425 } 3426 jint extJKC; //extended Java key code 3427 3428 for (UINT i = 0; i < 256; i++) { 3429 dynPrimaryKeymap[i].wkey = i; 3430 dynPrimaryKeymap[i].jkey = java_awt_event_KeyEvent_VK_UNDEFINED; 3431 dynPrimaryKeymap[i].unicode = 0; 3432 3433 if ((sc = MapVirtualKey (i, 0)) == 0) { 3434 dynPrimaryKeymap[i].scancode = 0; 3435 continue; 3436 } 3437 dynPrimaryKeymap[i].scancode = sc; 3438 3439 // XXX process cases like VK_SHIFT etc. 3440 kbdState[i] = 0x80; // "key pressed". 3441 WCHAR wc[16]; 3442 int k = ::ToUnicodeEx(i, sc, kbdState, wc, 16, 0, hkl); 3443 if (k == 1) { 3444 // unicode 3445 dynPrimaryKeymap[i].unicode = wc[0]; 3446 if (dynPrimaryKeymap[i].jkey == java_awt_event_KeyEvent_VK_UNDEFINED) { 3447 // Convert unicode to java keycode. 3448 //dynPrimaryKeymap[i].jkey = ((UINT)(wc[0]) + 0x01000000); 3449 // 3450 //XXX If this key in on the keypad, we should force a special value equal to 3451 //XXX an old java keycode: but how to say if it is a keypad key? 3452 //XXX We'll do it in WmKeyUp/Down. 3453 extJKC = env->CallStaticIntMethod(extKeyCodesCls, 3454 getExtendedKeyCodeForChar, (jint)(wc[0])); 3455 dynPrimaryKeymap[i].jkey = extJKC; 3456 } 3457 }else if (k == -1) { 3458 // dead key: use charToDeadVKTable 3459 dynPrimaryKeymap[i].unicode = wc[0]; 3460 resetKbdState( kbdState ); 3461 for (const CharToVKEntry *map = charToDeadVKTable; map->c != 0; ++map) { 3462 if (wc[0] == map->c) { 3463 dynPrimaryKeymap[i].jkey = map->javaKey; 3464 break; 3465 } 3466 } 3467 } else if (k == 0) { 3468 // reset 3469 resetKbdState( kbdState ); 3470 }else { 3471 // k > 1: this key does generate multiple characters. Ignore it. 3472 // An example: Arabic Lam and Alef ligature. 3473 // There will be no extended keycode and thus shortcuts for this key. 3474 // XXX shouldn't we reset the kbd state? 3475 #ifdef DEBUG 3476 DTRACE_PRINTLN2("wkey 0x%02X (%d)", i,i); 3477 #endif 3478 } 3479 kbdState[i] = 0; // "key unpressed" 3480 } 3481 } 3482 void 3483 AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers) 3484 { 3485 if( wkey && wkey < 256 ) { 3486 if(keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD) { 3487 // At the creation time, 3488 // dynPrimaryKeymap cannot distinguish between e.g. "/" and "NumPad /" 3489 dynPrimaryKeymap[wkey].jkey = jkeyLegacy; 3490 } 3491 if(dynPrimaryKeymap[wkey].jkey == java_awt_event_KeyEvent_VK_UNDEFINED) { 3492 // E.g. it is non-unicode key 3493 dynPrimaryKeymap[wkey].jkey = jkeyLegacy; 3494 } 3495 } 3496 } 3497 3498 UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, BOOL &isDeadKey) 3499 { 3500 static Hashtable transTable("VKEY translations"); 3501 static Hashtable deadKeyFlagTable("Dead Key Flags"); 3502 isDeadKey = FALSE; 3503 3504 // Try to translate using last saved translation 3505 if (ops == LOAD) { 3506 void* deadKeyFlag = deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey))); 3507 void* value = transTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey))); 3508 if (value != NULL) { 3509 isDeadKey = static_cast<BOOL>(reinterpret_cast<INT_PTR>(deadKeyFlag)); 3510 return static_cast<UINT>(reinterpret_cast<INT_PTR>(value)); 3511 } 3512 } 3513 3514 // If the windows key is a return, wkey will equal 13 ('\r') 3515 // In this case, we want to return 10 ('\n') 3516 // Since ToAscii would convert VK_RETURN to '\r', we need 3517 // to have a special case here. 3518 if (wkey == VK_RETURN) 3519 return '\n'; 3520 3521 // high order bit in keyboardState indicates whether the key is down 3522 static const BYTE KEY_STATE_DOWN = 0x80; 3523 BYTE keyboardState[AwtToolkit::KB_STATE_SIZE]; 3524 AwtToolkit::GetKeyboardState(keyboardState); 3525 3526 // apply modifiers to keyboard state if necessary 3527 BOOL shiftIsDown = FALSE; 3528 if (modifiers) { 3529 shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK; 3530 BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK; 3531 BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK; 3532 3533 // Windows treats AltGr as Ctrl+Alt 3534 if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) { 3535 altIsDown = TRUE; 3536 ctrlIsDown = TRUE; 3537 } 3538 3539 if (shiftIsDown) { 3540 keyboardState[VK_SHIFT] |= KEY_STATE_DOWN; 3541 } 3542 3543 // fix for 4623376,4737679,4501485,4740906,4708221 (4173679/4122715) 3544 // Here we try to resolve a conflict with ::ToAsciiEx's translating 3545 // ALT+number key combinations. kdm@sarc.spb.su 3546 // yan: Do it for navigation keys only, otherwise some AltGr deadkeys fail. 3547 if( IsNavigationKey(wkey) ) { 3548 keyboardState[VK_MENU] &= ~KEY_STATE_DOWN; 3549 } 3550 3551 if (ctrlIsDown) 3552 { 3553 if (altIsDown) { 3554 // bugid 4215009: don't mess with AltGr == Ctrl + Alt 3555 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN; 3556 } 3557 else { 3558 // bugid 4098210: old event model doesn't have KEY_TYPED 3559 // events, so try to provide a meaningful character for 3560 // Ctrl+<key>. Take Ctrl into account only when we know 3561 // that Ctrl+<key> will be an ASCII control. Ignore by 3562 // default. 3563 keyboardState[VK_CONTROL] &= ~KEY_STATE_DOWN; 3564 3565 // Letters have Ctrl+<letter> counterparts. According to 3566 // <winuser.h> VK_A through VK_Z are the same as ASCII 3567 // 'A' through 'Z'. 3568 if (wkey >= 'A' && wkey <= 'Z') { 3569 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN; 3570 } 3571 else { 3572 // Non-letter controls 033 to 037 are: 3573 // ^[ (ESC), ^\ (FS), ^] (GS), ^^ (RS), and ^_ (US) 3574 3575 // Shift state bits returned by ::VkKeyScan in HIBYTE 3576 static const UINT _VKS_SHIFT_MASK = 0x01; 3577 static const UINT _VKS_CTRL_MASK = 0x02; 3578 static const UINT _VKS_ALT_MASK = 0x04; 3579 3580 // Check to see whether there is a meaningful translation 3581 TCHAR ch; 3582 short vk; 3583 for (ch = _T('\033'); ch < _T('\040'); ch++) { 3584 vk = ::VkKeyScan(ch); 3585 if (wkey == LOBYTE(vk)) { 3586 UINT shiftState = HIBYTE(vk); 3587 if ((shiftState & _VKS_CTRL_MASK) || 3588 (!(shiftState & _VKS_SHIFT_MASK) 3589 == !shiftIsDown)) 3590 { 3591 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN; 3592 } 3593 break; 3594 } 3595 } 3596 } 3597 } // ctrlIsDown && altIsDown 3598 } // ctrlIsDown 3599 } // modifiers 3600 3601 WORD wChar[2]; 3602 int converted = 1; 3603 UINT ch = ::MapVirtualKeyEx(wkey, 2, GetKeyboardLayout()); 3604 if (ch & 0x80000000) { 3605 // Dead key which is handled as a normal key 3606 isDeadKey = deadKeyActive = TRUE; 3607 } else if (deadKeyActive) { 3608 // We cannot use ::ToUnicodeEx if dead key is active because this will 3609 // break dead key function 3610 wChar[0] = shiftIsDown ? ch : tolower(ch); 3611 } else { 3612 UINT scancode = ::MapVirtualKey(wkey, 0); 3613 converted = ::ToUnicodeEx(wkey, scancode, keyboardState, 3614 wChar, 2, 0, GetKeyboardLayout()); 3615 } 3616 3617 UINT translation; 3618 BOOL deadKeyFlag = (converted == 2); 3619 3620 // Dead Key 3621 if (converted < 0 || isDeadKey) { 3622 translation = java_awt_event_KeyEvent_CHAR_UNDEFINED; 3623 } else 3624 // No translation available -- try known conversions or else punt. 3625 if (converted == 0) { 3626 if (wkey == VK_DELETE) { 3627 translation = '\177'; 3628 } else 3629 if (wkey >= VK_NUMPAD0 && wkey <= VK_NUMPAD9) { 3630 translation = '0' + wkey - VK_NUMPAD0; 3631 } else { 3632 translation = java_awt_event_KeyEvent_CHAR_UNDEFINED; 3633 } 3634 } else 3635 // the caller expects a Unicode character. 3636 if (converted > 0) { 3637 translation = wChar[0]; 3638 } 3639 if (ops == SAVE) { 3640 transTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)), 3641 reinterpret_cast<void*>(static_cast<INT_PTR>(translation))); 3642 if (deadKeyFlag) { 3643 deadKeyFlagTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)), 3644 reinterpret_cast<void*>(static_cast<INT_PTR>(deadKeyFlag))); 3645 } else { 3646 deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey))); 3647 } 3648 } 3649 3650 isDeadKey = deadKeyFlag; 3651 return translation; 3652 } 3653 3654 MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt, 3655 UINT flags, BOOL system) 3656 { 3657 // VK_PROCESSKEY is a special value which means 3658 // "Current IME wants to consume this KeyEvent" 3659 // Real key code is saved by IMM32.DLL and can be retrieved by 3660 // calling ImmGetVirtualKey(); 3661 if (wkey == VK_PROCESSKEY) { 3662 return mrDoDefault; 3663 } 3664 MSG msg; 3665 InitMessage(&msg, (system ? WM_SYSKEYDOWN : WM_KEYDOWN), 3666 wkey, MAKELPARAM(repCnt, flags)); 3667 3668 UINT modifiers = GetJavaModifiers(); 3669 jint keyLocation = GetKeyLocation(wkey, flags); 3670 BOOL isDeadKey = FALSE; 3671 UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE, isDeadKey); 3672 UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey); 3673 UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers); 3674 3675 3676 SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED, 3677 ::JVM_CurrentTimeMillis(NULL, 0), jkey, character, 3678 modifiers, keyLocation, (jlong)wkey, &msg); 3679 3680 // bugid 4724007: Windows does not create a WM_CHAR for the Del key 3681 // for some reason, so we need to create the KEY_TYPED event on the 3682 // WM_KEYDOWN. Use null msg so the character doesn't get sent back 3683 // to the native window for processing (this event is synthesized 3684 // for Java - we don't want Windows trying to process it). 3685 if (jkey == java_awt_event_KeyEvent_VK_DELETE) { 3686 SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED, 3687 ::JVM_CurrentTimeMillis(NULL, 0), 3688 java_awt_event_KeyEvent_VK_UNDEFINED, 3689 character, modifiers, 3690 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0); 3691 } 3692 3693 return mrConsume; 3694 } 3695 3696 MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt, 3697 UINT flags, BOOL system) 3698 { 3699 3700 // VK_PROCESSKEY is a special value which means 3701 // "Current IME wants to consume this KeyEvent" 3702 // Real key code is saved by IMM32.DLL and can be retrieved by 3703 // calling ImmGetVirtualKey(); 3704 if (wkey == VK_PROCESSKEY) { 3705 return mrDoDefault; 3706 } 3707 MSG msg; 3708 InitMessage(&msg, (system ? WM_SYSKEYUP : WM_KEYUP), 3709 wkey, MAKELPARAM(repCnt, flags)); 3710 3711 UINT modifiers = GetJavaModifiers(); 3712 jint keyLocation = GetKeyLocation(wkey, flags); 3713 BOOL isDeadKey = FALSE; 3714 UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD, isDeadKey); 3715 UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey); 3716 UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers); 3717 3718 SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED, 3719 ::JVM_CurrentTimeMillis(NULL, 0), jkey, character, 3720 modifiers, keyLocation, (jlong)wkey, &msg); 3721 return mrConsume; 3722 } 3723 3724 MsgRouting AwtComponent::WmInputLangChange(UINT charset, HKL hKeyboardLayout) 3725 { 3726 // Normally we would be able to use charset and TranslateCharSetInfo 3727 // to get a code page that should be associated with this keyboard 3728 // layout change. However, there seems to be an NT 4.0 bug associated 3729 // with the WM_INPUTLANGCHANGE message, which makes the charset parameter 3730 // unreliable, especially on Asian systems. Our workaround uses the 3731 // keyboard layout handle instead. 3732 m_hkl = hKeyboardLayout; 3733 m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID 3734 m_CodePage = LangToCodePage(m_idLang); 3735 BuildDynamicKeyMapTable(); // compute new mappings for VK_OEM 3736 BuildPrimaryDynamicTable(); 3737 return mrConsume; // do not propagate to children 3738 } 3739 3740 // Convert Language ID to CodePage 3741 UINT AwtComponent::LangToCodePage(LANGID idLang) 3742 { 3743 TCHAR strCodePage[MAX_ACP_STR_LEN]; 3744 // use the LANGID to create a LCID 3745 LCID idLocale = MAKELCID(idLang, SORT_DEFAULT); 3746 // get the ANSI code page associated with this locale 3747 if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE, strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 ) 3748 return _ttoi(strCodePage); 3749 else 3750 return GetACP(); 3751 } 3752 3753 3754 MsgRouting AwtComponent::WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL system) 3755 { 3756 // We will simply create Java events here. 3757 WCHAR unicodeChar = character; 3758 MSG msg; 3759 InitMessage(&msg, WM_IME_CHAR, character, 3760 MAKELPARAM(repCnt, flags)); 3761 3762 jint modifiers = GetJavaModifiers(); 3763 SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED, 3764 ::JVM_CurrentTimeMillis(NULL, 0), 3765 java_awt_event_KeyEvent_VK_UNDEFINED, 3766 unicodeChar, modifiers, 3767 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0, 3768 &msg); 3769 return mrConsume; 3770 } 3771 3772 MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags, 3773 BOOL system) 3774 { 3775 deadKeyActive = FALSE; 3776 3777 // Will only get WmChar messages with DBCS if we create them for 3778 // an Edit class in the WmForwardChar method. These synthesized 3779 // DBCS chars are ok to pass on directly to the default window 3780 // procedure. They've already been filtered through the Java key 3781 // event queue. We will never get the trail byte since the edit 3782 // class will PeekMessage(&msg, hwnd, WM_CHAR, WM_CHAR, 3783 // PM_REMOVE). I would like to be able to pass this character off 3784 // via WM_AWT_FORWARD_BYTE, but the Edit classes don't seem to 3785 // like that. 3786 3787 // We will simply create Java events here. 3788 UINT message = system ? WM_SYSCHAR : WM_CHAR; 3789 3790 // The Alt modifier is reported in the 29th bit of the lParam, 3791 // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)). 3792 bool alt_is_down = (flags & (1<<13)) != 0; 3793 3794 // Fix for bug 4141621, corrected by fix for bug 6223726: Alt+space doesn't invoke system menu 3795 // We should not pass this particular combination to Java. 3796 3797 if (system && alt_is_down) { 3798 if (character == VK_SPACE) { 3799 return mrDoDefault; 3800 } 3801 } 3802 3803 // If this is a WM_CHAR (non-system) message, then the Alt flag 3804 // indicates that the character was typed using an AltGr key 3805 // (which Windows treats as Ctrl+Alt), so in this case we do NOT 3806 // pass the Ctrl and Alt modifiers to Java, but instead we 3807 // replace them with Java's AltGraph modifier. Note: the AltGraph 3808 // modifier does not exist in 1.1.x releases. 3809 jint modifiers = GetJavaModifiers(); 3810 if (!system && alt_is_down) { 3811 // character typed with AltGraph 3812 modifiers &= ~(java_awt_event_InputEvent_ALT_DOWN_MASK 3813 | java_awt_event_InputEvent_CTRL_DOWN_MASK); 3814 modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK; 3815 } 3816 3817 WCHAR unicodeChar = character; 3818 3819 // Kludge: Combine pending single byte with this char for some Chinese IMEs 3820 if (m_PendingLeadByte != 0) { 3821 character = (m_PendingLeadByte & 0x00ff) | (character << 8); 3822 m_PendingLeadByte = 0; 3823 ::MultiByteToWideChar(GetCodePage(), 0, (CHAR*)&character, 2, 3824 &unicodeChar, 1); 3825 } 3826 3827 if (unicodeChar == VK_RETURN) { 3828 // Enter key generates \r in windows, but \n is required in java 3829 unicodeChar = java_awt_event_KeyEvent_VK_ENTER; 3830 } 3831 MSG msg; 3832 InitMessage(&msg, message, character, 3833 MAKELPARAM(repCnt, flags)); 3834 SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED, 3835 ::JVM_CurrentTimeMillis(NULL, 0), 3836 java_awt_event_KeyEvent_VK_UNDEFINED, 3837 unicodeChar, modifiers, 3838 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0, 3839 &msg); 3840 return mrConsume; 3841 } 3842 3843 MsgRouting AwtComponent::WmForwardChar(WCHAR character, LPARAM lParam, 3844 BOOL synthetic) 3845 { 3846 // just post WM_CHAR with unicode key value 3847 DefWindowProc(WM_CHAR, (WPARAM)character, lParam); 3848 return mrConsume; 3849 } 3850 3851 MsgRouting AwtComponent::WmPaste() 3852 { 3853 return mrDoDefault; 3854 } 3855 3856 // support IME Composition messages 3857 void AwtComponent::SetCompositionWindow(RECT& r) 3858 { 3859 HWND hwnd = ImmGetHWnd(); 3860 HIMC hIMC = ImmGetContext(hwnd); 3861 if (hIMC == NULL) { 3862 return; 3863 } 3864 COMPOSITIONFORM cf = {CFS_DEFAULT, {0, 0}, {0, 0, 0, 0}}; 3865 ImmSetCompositionWindow(hIMC, &cf); 3866 ImmReleaseContext(hwnd, hIMC); 3867 } 3868 3869 void AwtComponent::OpenCandidateWindow(int x, int y) 3870 { 3871 UINT bits = 1; 3872 POINT p = {0, 0}; // upper left corner of the client area 3873 HWND hWnd = GetHWnd(); 3874 if (!::IsWindowVisible(hWnd)) { 3875 return; 3876 } 3877 HWND hTop = GetTopLevelParentForWindow(hWnd); 3878 ::ClientToScreen(hTop, &p); 3879 if (!m_bitsCandType) { 3880 SetCandidateWindow(m_bitsCandType, x - p.x, y - p.y); 3881 return; 3882 } 3883 for (int iCandType=0; iCandType<32; iCandType++, bits<<=1) { 3884 if ( m_bitsCandType & bits ) 3885 SetCandidateWindow(iCandType, x - p.x, y - p.y); 3886 } 3887 if (m_bitsCandType != 0) { 3888 // REMIND: is there any chance GetProxyFocusOwner() returns NULL here? 3889 ::DefWindowProc(ImmGetHWnd(), 3890 WM_IME_NOTIFY, IMN_OPENCANDIDATE, m_bitsCandType); 3891 } 3892 } 3893 3894 void AwtComponent::SetCandidateWindow(int iCandType, int x, int y) 3895 { 3896 HWND hwnd = ImmGetHWnd(); 3897 HIMC hIMC = ImmGetContext(hwnd); 3898 CANDIDATEFORM cf; 3899 cf.dwIndex = iCandType; 3900 cf.dwStyle = CFS_POINT; 3901 cf.ptCurrentPos.x = x; 3902 cf.ptCurrentPos.y = y; 3903 3904 ImmSetCandidateWindow(hIMC, &cf); 3905 ImmReleaseContext(hwnd, hIMC); 3906 } 3907 3908 MsgRouting AwtComponent::WmImeSetContext(BOOL fSet, LPARAM *lplParam) 3909 { 3910 // If the Windows input context is disabled, do not let Windows 3911 // display any UIs. 3912 HWND hwnd = ImmGetHWnd(); 3913 HIMC hIMC = ImmGetContext(hwnd); 3914 if (hIMC == NULL) { 3915 *lplParam = 0; 3916 return mrDoDefault; 3917 } 3918 ImmReleaseContext(hwnd, hIMC); 3919 3920 if (fSet) { 3921 LPARAM lParam = *lplParam; 3922 if (!m_useNativeCompWindow) { 3923 // stop to draw native composing window. 3924 *lplParam &= ~ISC_SHOWUICOMPOSITIONWINDOW; 3925 } 3926 } 3927 return mrDoDefault; 3928 } 3929 3930 MsgRouting AwtComponent::WmImeNotify(WPARAM subMsg, LPARAM bitsCandType) 3931 { 3932 if (!m_useNativeCompWindow) { 3933 if (subMsg == IMN_OPENCANDIDATE) { 3934 m_bitsCandType = bitsCandType; 3935 InquireCandidatePosition(); 3936 } else if (subMsg == IMN_OPENSTATUSWINDOW || 3937 subMsg == WM_IME_STARTCOMPOSITION) { 3938 m_bitsCandType = 0; 3939 InquireCandidatePosition(); 3940 } else if (subMsg == IMN_SETCANDIDATEPOS) { 3941 InquireCandidatePosition(); 3942 } 3943 return mrConsume; 3944 } 3945 return mrDoDefault; 3946 } 3947 3948 MsgRouting AwtComponent::WmImeStartComposition() 3949 { 3950 if (m_useNativeCompWindow) { 3951 RECT rc; 3952 ::GetClientRect(GetHWnd(), &rc); 3953 SetCompositionWindow(rc); 3954 return mrDoDefault; 3955 } else 3956 return mrConsume; 3957 } 3958 3959 MsgRouting AwtComponent::WmImeEndComposition() 3960 { 3961 if (m_useNativeCompWindow) return mrDoDefault; 3962 3963 SendInputMethodEvent( 3964 java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED, 3965 NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0 ); 3966 return mrConsume; 3967 } 3968 3969 MsgRouting AwtComponent::WmImeComposition(WORD wChar, LPARAM flags) 3970 { 3971 if (m_useNativeCompWindow) return mrDoDefault; 3972 3973 int* bndClauseW = NULL; 3974 jstring* readingClauseW = NULL; 3975 int* bndAttrW = NULL; 3976 BYTE* valAttrW = NULL; 3977 int cClauseW = 0; 3978 AwtInputTextInfor* textInfor = NULL; 3979 3980 try { 3981 HWND hwnd = ImmGetHWnd(); 3982 HIMC hIMC = ImmGetContext(hwnd); 3983 DASSERT(hIMC!=0); 3984 3985 textInfor = new AwtInputTextInfor; 3986 textInfor->GetContextData(hIMC, flags); 3987 ImmReleaseContext(hwnd, hIMC); 3988 3989 jstring jtextString = textInfor->GetText(); 3990 /* The conditions to send the input method event to AWT EDT are: 3991 1. Whenever there is a composition message sent regarding whether 3992 the composition text is NULL or not. See details at bug 6222692. 3993 2. When there is a committed message sent, in which case, we have to 3994 check whether the committed string is NULL or not. If the committed string 3995 is NULL, there is no need to send any input method event. 3996 (Minor note: 'jtextString' returned is the merged string in the case of 3997 partial commit.) 3998 */ 3999 if ((flags & GCS_RESULTSTR && jtextString != NULL) || 4000 (flags & GCS_COMPSTR)) { 4001 int cursorPosW = textInfor->GetCursorPosition(); 4002 // In order not to delete the readingClauseW in the catch clause, 4003 // calling GetAttributeInfor before GetClauseInfor. 4004 int cAttrW = textInfor->GetAttributeInfor(bndAttrW, valAttrW); 4005 cClauseW = textInfor->GetClauseInfor(bndClauseW, readingClauseW); 4006 4007 /* Send INPUT_METHOD_TEXT_CHANGED event to the WInputMethod which in turn sends 4008 the event to AWT EDT. 4009 4010 The last two paremeters are set to equal since we don't have recommendations for 4011 the visible position within the current composed text. See details at 4012 java.awt.event.InputMethodEvent. 4013 */ 4014 SendInputMethodEvent(java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED, 4015 jtextString, 4016 cClauseW, bndClauseW, readingClauseW, 4017 cAttrW, bndAttrW, valAttrW, 4018 textInfor->GetCommittedTextLength(), 4019 cursorPosW, cursorPosW); 4020 } 4021 } catch (...) { 4022 // since GetClauseInfor and GetAttributeInfor could throw exception, we have to release 4023 // the pointer here. 4024 delete [] bndClauseW; 4025 delete [] readingClauseW; 4026 delete [] bndAttrW; 4027 delete [] valAttrW; 4028 throw; 4029 } 4030 4031 /* Free the storage allocated. Since jtextString won't be passed from threads 4032 * to threads, we just use the local ref and it will be deleted within the destructor 4033 * of AwtInputTextInfor object. 4034 */ 4035 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4036 if (cClauseW && readingClauseW) { 4037 for (int i = 0; i < cClauseW; i ++) { 4038 if (readingClauseW[i]) { 4039 env->DeleteLocalRef(readingClauseW[i]); 4040 } 4041 } 4042 } 4043 delete [] bndClauseW; 4044 delete [] readingClauseW; 4045 delete [] bndAttrW; 4046 delete [] valAttrW; 4047 delete textInfor; 4048 4049 return mrConsume; 4050 } 4051 4052 // 4053 // generate and post InputMethodEvent 4054 // 4055 void AwtComponent::SendInputMethodEvent(jint id, jstring text, 4056 int cClause, int* rgClauseBoundary, jstring* rgClauseReading, 4057 int cAttrBlock, int* rgAttrBoundary, BYTE *rgAttrValue, 4058 int commitedTextLength, int caretPos, int visiblePos) 4059 { 4060 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4061 4062 // assumption for array type casting 4063 DASSERT(sizeof(int)==sizeof(jint)); 4064 DASSERT(sizeof(BYTE)==sizeof(jbyte)); 4065 4066 // caluse information 4067 jintArray clauseBoundary = NULL; 4068 jobjectArray clauseReading = NULL; 4069 if (cClause && rgClauseBoundary && rgClauseReading) { 4070 // convert clause boundary offset array to java array 4071 clauseBoundary = env->NewIntArray(cClause+1); 4072 DASSERT(clauseBoundary); 4073 CHECK_NULL(clauseBoundary); 4074 env->SetIntArrayRegion(clauseBoundary, 0, cClause+1, (jint *)rgClauseBoundary); 4075 DASSERT(!safe_ExceptionOccurred(env)); 4076 4077 // convert clause reading string array to java array 4078 jclass stringCls = JNU_ClassString(env); 4079 DASSERT(stringCls); 4080 CHECK_NULL(stringCls); 4081 clauseReading = env->NewObjectArray(cClause, stringCls, NULL); 4082 DASSERT(clauseReading); 4083 CHECK_NULL(clauseReading); 4084 for (int i=0; i<cClause; i++) env->SetObjectArrayElement(clauseReading, i, rgClauseReading[i]); 4085 DASSERT(!safe_ExceptionOccurred(env)); 4086 } 4087 4088 4089 // attrubute value definition in WInputMethod.java must be equal to that in IMM.H 4090 DASSERT(ATTR_INPUT==sun_awt_windows_WInputMethod_ATTR_INPUT); 4091 DASSERT(ATTR_TARGET_CONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_CONVERTED); 4092 DASSERT(ATTR_CONVERTED==sun_awt_windows_WInputMethod_ATTR_CONVERTED); 4093 DASSERT(ATTR_TARGET_NOTCONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_NOTCONVERTED); 4094 DASSERT(ATTR_INPUT_ERROR==sun_awt_windows_WInputMethod_ATTR_INPUT_ERROR); 4095 4096 // attribute information 4097 jintArray attrBoundary = NULL; 4098 jbyteArray attrValue = NULL; 4099 if (cAttrBlock && rgAttrBoundary && rgAttrValue) { 4100 // convert attribute boundary offset array to java array 4101 attrBoundary = env->NewIntArray(cAttrBlock+1); 4102 DASSERT(attrBoundary); 4103 CHECK_NULL(attrBoundary); 4104 env->SetIntArrayRegion(attrBoundary, 0, cAttrBlock+1, (jint *)rgAttrBoundary); 4105 DASSERT(!safe_ExceptionOccurred(env)); 4106 4107 // convert attribute value byte array to java array 4108 attrValue = env->NewByteArray(cAttrBlock); 4109 DASSERT(attrValue); 4110 CHECK_NULL(attrValue); 4111 env->SetByteArrayRegion(attrValue, 0, cAttrBlock, (jbyte *)rgAttrValue); 4112 DASSERT(!safe_ExceptionOccurred(env)); 4113 } 4114 4115 4116 // get global reference of WInputMethod class (run only once) 4117 static jclass wInputMethodCls = NULL; 4118 if (wInputMethodCls == NULL) { 4119 jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod"); 4120 DASSERT(wInputMethodClsLocal); 4121 CHECK_NULL(wInputMethodClsLocal); 4122 wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal); 4123 env->DeleteLocalRef(wInputMethodClsLocal); 4124 } 4125 4126 // get method ID of sendInputMethodEvent() (run only once) 4127 static jmethodID sendIMEventMid = 0; 4128 if (sendIMEventMid == 0) { 4129 sendIMEventMid = env->GetMethodID(wInputMethodCls, "sendInputMethodEvent", 4130 "(IJLjava/lang/String;[I[Ljava/lang/String;[I[BIII)V"); 4131 DASSERT(sendIMEventMid); 4132 CHECK_NULL(sendIMEventMid); 4133 } 4134 4135 // call m_InputMethod.sendInputMethod() 4136 env->CallVoidMethod(m_InputMethod, sendIMEventMid, id, ::JVM_CurrentTimeMillis(NULL, 0), 4137 text, clauseBoundary, clauseReading, attrBoundary, 4138 attrValue, commitedTextLength, caretPos, visiblePos); 4139 if (safe_ExceptionOccurred(env)) env->ExceptionDescribe(); 4140 DASSERT(!safe_ExceptionOccurred(env)); 4141 4142 } 4143 4144 4145 4146 // 4147 // Inquires candidate position according to the composed text 4148 // 4149 void AwtComponent::InquireCandidatePosition() 4150 { 4151 if (!::IsWindowVisible(GetHWnd())) { 4152 return; 4153 } 4154 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4155 4156 // get global reference of WInputMethod class (run only once) 4157 static jclass wInputMethodCls = NULL; 4158 if (wInputMethodCls == NULL) { 4159 jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod"); 4160 DASSERT(wInputMethodClsLocal); 4161 CHECK_NULL(wInputMethodClsLocal); 4162 wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal); 4163 env->DeleteLocalRef(wInputMethodClsLocal); 4164 } 4165 4166 // get method ID of sendInputMethodEvent() (run only once) 4167 static jmethodID inqCandPosMid = 0; 4168 if (inqCandPosMid == 0) { 4169 inqCandPosMid = env->GetMethodID(wInputMethodCls, "inquireCandidatePosition", "()V"); 4170 DASSERT(!safe_ExceptionOccurred(env)); 4171 DASSERT(inqCandPosMid); 4172 CHECK_NULL(inqCandPosMid); 4173 } 4174 4175 // call m_InputMethod.sendInputMethod() 4176 jobject candPos = env->CallObjectMethod(m_InputMethod, inqCandPosMid); 4177 DASSERT(!safe_ExceptionOccurred(env)); 4178 } 4179 4180 HWND AwtComponent::ImmGetHWnd() 4181 { 4182 HWND proxy = GetProxyFocusOwner(); 4183 return (proxy != NULL) ? proxy : GetHWnd(); 4184 } 4185 4186 HIMC AwtComponent::ImmAssociateContext(HIMC himc) 4187 { 4188 return ::ImmAssociateContext(ImmGetHWnd(), himc); 4189 } 4190 4191 HWND AwtComponent::GetProxyFocusOwner() 4192 { 4193 AwtWindow *window = GetContainer(); 4194 if (window != 0) { 4195 AwtFrame *owner = window->GetOwningFrameOrDialog(); 4196 if (owner != 0) { 4197 return owner->GetProxyFocusOwner(); 4198 } else if (!window->IsSimpleWindow()) { // isn't an owned simple window 4199 return ((AwtFrame*)window)->GetProxyFocusOwner(); 4200 } 4201 } 4202 return (HWND)NULL; 4203 } 4204 4205 /* Redirects message to the focus proxy, if any */ 4206 void AwtComponent::CallProxyDefWindowProc(UINT message, WPARAM wParam, 4207 LPARAM lParam, LRESULT &retVal, MsgRouting &mr) 4208 { 4209 if (mr != mrConsume) { 4210 HWND proxy = GetProxyFocusOwner(); 4211 if (proxy != NULL && ::IsWindowEnabled(proxy)) { 4212 retVal = ::DefWindowProc(proxy, message, wParam, lParam); 4213 mr = mrConsume; 4214 } 4215 } 4216 } 4217 4218 MsgRouting AwtComponent::WmCommand(UINT id, HWND hWndChild, UINT notifyCode) 4219 { 4220 /* Menu/Accelerator */ 4221 if (hWndChild == 0) { 4222 AwtObject* obj = AwtToolkit::GetInstance().LookupCmdID(id); 4223 if (obj == NULL) { 4224 return mrConsume; 4225 } 4226 DASSERT(((AwtMenuItem*)obj)->GetID() == id); 4227 obj->DoCommand(); 4228 return mrConsume; 4229 } 4230 /* Child id notification */ 4231 else { 4232 AwtComponent* child = AwtComponent::GetComponent(hWndChild); 4233 if (child) { 4234 child->WmNotify(notifyCode); 4235 } 4236 } 4237 return mrDoDefault; 4238 } 4239 4240 MsgRouting AwtComponent::WmNotify(UINT notifyCode) 4241 { 4242 return mrDoDefault; 4243 } 4244 4245 MsgRouting AwtComponent::WmCompareItem(UINT ctrlId, 4246 COMPAREITEMSTRUCT &compareInfo, 4247 LRESULT &result) 4248 { 4249 AwtComponent* child = AwtComponent::GetComponent(compareInfo.hwndItem); 4250 if (child == this) { 4251 /* DoCallback("handleItemDelete", */ 4252 } 4253 else if (child) { 4254 return child->WmCompareItem(ctrlId, compareInfo, result); 4255 } 4256 return mrConsume; 4257 } 4258 4259 MsgRouting AwtComponent::WmDeleteItem(UINT ctrlId, 4260 DELETEITEMSTRUCT &deleteInfo) 4261 { 4262 /* 4263 * Workaround for NT 4.0 bug -- if SetWindowPos is called on a AwtList 4264 * window, a WM_DELETEITEM message is sent to its parent with a window 4265 * handle of one of the list's child windows. The property lookup 4266 * succeeds, but the HWNDs don't match. 4267 */ 4268 if (deleteInfo.hwndItem == NULL) { 4269 return mrConsume; 4270 } 4271 AwtComponent* child = (AwtComponent *)AwtComponent::GetComponent(deleteInfo.hwndItem); 4272 4273 if (child && child->GetHWnd() != deleteInfo.hwndItem) { 4274 return mrConsume; 4275 } 4276 4277 if (child == this) { 4278 /*DoCallback("handleItemDelete", */ 4279 } 4280 else if (child) { 4281 return child->WmDeleteItem(ctrlId, deleteInfo); 4282 } 4283 return mrConsume; 4284 } 4285 4286 MsgRouting AwtComponent::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT &drawInfo) 4287 { 4288 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4289 4290 if (drawInfo.CtlType == ODT_MENU) { 4291 if (IsMenu((HMENU)drawInfo.hwndItem) && drawInfo.itemData != 0) { 4292 AwtMenu* menu = (AwtMenu*)(drawInfo.itemData); 4293 menu->DrawItem(drawInfo); 4294 } 4295 } else { 4296 return OwnerDrawItem(ctrlId, drawInfo); 4297 } 4298 return mrConsume; 4299 } 4300 4301 MsgRouting AwtComponent::WmMeasureItem(UINT ctrlId, 4302 MEASUREITEMSTRUCT &measureInfo) 4303 { 4304 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4305 4306 if (measureInfo.CtlType == ODT_MENU) { 4307 if (measureInfo.itemData != 0) { 4308 AwtMenu* menu = (AwtMenu*)(measureInfo.itemData); 4309 HDC hDC = ::GetDC(GetHWnd()); 4310 /* menu->MeasureItem(env, hDC, measureInfo); */ 4311 menu->MeasureItem(hDC, measureInfo); 4312 ::ReleaseDC(GetHWnd(), hDC); 4313 } 4314 } else { 4315 return OwnerMeasureItem(ctrlId, measureInfo); 4316 } 4317 return mrConsume; 4318 } 4319 4320 MsgRouting AwtComponent::OwnerDrawItem(UINT ctrlId, 4321 DRAWITEMSTRUCT &drawInfo) 4322 { 4323 AwtComponent* child = AwtComponent::GetComponent(drawInfo.hwndItem); 4324 if (child == this) { 4325 /* DoCallback("handleItemDelete", */ 4326 } else if (child != NULL) { 4327 return child->WmDrawItem(ctrlId, drawInfo); 4328 } 4329 return mrConsume; 4330 } 4331 4332 MsgRouting AwtComponent::OwnerMeasureItem(UINT ctrlId, 4333 MEASUREITEMSTRUCT &measureInfo) 4334 { 4335 HWND hChild = ::GetDlgItem(GetHWnd(), measureInfo.CtlID); 4336 AwtComponent* child = AwtComponent::GetComponent(hChild); 4337 /* 4338 * If the parent cannot find the child's instance from its handle, 4339 * maybe the child is in its creation. So the child must be searched 4340 * from the list linked before the child's creation. 4341 */ 4342 if (child == NULL) { 4343 child = SearchChild((UINT)ctrlId); 4344 } 4345 4346 if (child == this) { 4347 /* DoCallback("handleItemDelete", */ 4348 } 4349 else if (child) { 4350 return child->WmMeasureItem(ctrlId, measureInfo); 4351 } 4352 return mrConsume; 4353 } 4354 4355 /* for WmDrawItem method of Label, Button and Checkbox */ 4356 void AwtComponent::DrawWindowText(HDC hDC, jobject font, jstring text, 4357 int x, int y) 4358 { 4359 int nOldBkMode = ::SetBkMode(hDC,TRANSPARENT); 4360 DASSERT(nOldBkMode != 0); 4361 AwtFont::drawMFString(hDC, font, text, x, y, GetCodePage()); 4362 VERIFY(::SetBkMode(hDC,nOldBkMode)); 4363 } 4364 4365 /* 4366 * Draw text in gray (the color being set to COLOR_GRAYTEXT) when the 4367 * component is disabled. Used only for label, checkbox and button in 4368 * OWNER_DRAW. It draws the text in emboss. 4369 */ 4370 void AwtComponent::DrawGrayText(HDC hDC, jobject font, jstring text, 4371 int x, int y) 4372 { 4373 ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHILIGHT)); 4374 AwtComponent::DrawWindowText(hDC, font, text, x+1, y+1); 4375 ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW)); 4376 AwtComponent::DrawWindowText(hDC, font, text, x, y); 4377 } 4378 4379 /* for WmMeasureItem method of List and Choice */ 4380 jstring AwtComponent::GetItemString(JNIEnv *env, jobject target, jint index) 4381 { 4382 jstring str = (jstring)JNU_CallMethodByName(env, NULL, target, "getItemImpl", 4383 "(I)Ljava/lang/String;", 4384 index).l; 4385 DASSERT(!safe_ExceptionOccurred(env)); 4386 return str; 4387 } 4388 4389 /* for WmMeasureItem method of List and Choice */ 4390 void AwtComponent::MeasureListItem(JNIEnv *env, 4391 MEASUREITEMSTRUCT &measureInfo) 4392 { 4393 if (env->EnsureLocalCapacity(1) < 0) { 4394 return; 4395 } 4396 jobject dimension = PreferredItemSize(env); 4397 DASSERT(dimension); 4398 measureInfo.itemWidth = 4399 env->GetIntField(dimension, AwtDimension::widthID); 4400 measureInfo.itemHeight = 4401 env->GetIntField(dimension, AwtDimension::heightID); 4402 env->DeleteLocalRef(dimension); 4403 } 4404 4405 /* for WmDrawItem method of List and Choice */ 4406 void AwtComponent::DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo) 4407 { 4408 if (env->EnsureLocalCapacity(3) < 0) { 4409 return; 4410 } 4411 jobject peer = GetPeer(env); 4412 jobject target = env->GetObjectField(peer, AwtObject::targetID); 4413 4414 HDC hDC = drawInfo.hDC; 4415 RECT rect = drawInfo.rcItem; 4416 4417 BOOL bEnabled = isEnabled(); 4418 BOOL unfocusableChoice = (drawInfo.itemState & ODS_COMBOBOXEDIT) && !IsFocusable(); 4419 DWORD crBack, crText; 4420 if (drawInfo.itemState & ODS_SELECTED){ 4421 /* Set background and text colors for selected item */ 4422 crBack = ::GetSysColor (COLOR_HIGHLIGHT); 4423 crText = ::GetSysColor (COLOR_HIGHLIGHTTEXT); 4424 } else { 4425 /* Set background and text colors for unselected item */ 4426 crBack = GetBackgroundColor(); 4427 crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT); 4428 } 4429 if (unfocusableChoice) { 4430 //6190728. Shouldn't draw selection field (edit control) of an owner-drawn combo box. 4431 crBack = GetBackgroundColor(); 4432 crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT); 4433 } 4434 4435 /* Fill item rectangle with background color */ 4436 HBRUSH hbrBack = ::CreateSolidBrush (crBack); 4437 DASSERT(hbrBack); 4438 /* 6190728. Shouldn't draw any kind of rectangle around selection field 4439 * (edit control) of an owner-drawn combo box while unfocusable 4440 */ 4441 if (!unfocusableChoice){ 4442 VERIFY(::FillRect (hDC, &rect, hbrBack)); 4443 } 4444 VERIFY(::DeleteObject (hbrBack)); 4445 4446 /* Set current background and text colors */ 4447 ::SetBkColor (hDC, crBack); 4448 ::SetTextColor (hDC, crText); 4449 4450 /*draw string (with left margin of 1 point) */ 4451 if ((int) (drawInfo.itemID) >= 0) { 4452 jobject font = GET_FONT(target, peer); 4453 jstring text = GetItemString(env, target, drawInfo.itemID); 4454 if (env->ExceptionCheck()) { 4455 env->DeleteLocalRef(font); 4456 env->DeleteLocalRef(target); 4457 return; 4458 } 4459 SIZE size = AwtFont::getMFStringSize(hDC, font, text); 4460 AwtFont::drawMFString(hDC, font, text, 4461 (GetRTL()) ? rect.right - size.cx - 1 4462 : rect.left + 1, 4463 (rect.top + rect.bottom - size.cy) / 2, 4464 GetCodePage()); 4465 env->DeleteLocalRef(font); 4466 env->DeleteLocalRef(text); 4467 } 4468 if ((drawInfo.itemState & ODS_FOCUS) && 4469 (drawInfo.itemAction & (ODA_FOCUS | ODA_DRAWENTIRE))) { 4470 if (!unfocusableChoice){ 4471 if(::DrawFocusRect(hDC, &rect) == 0) 4472 VERIFY(::GetLastError() == 0); 4473 } 4474 } 4475 env->DeleteLocalRef(target); 4476 } 4477 4478 /* for MeasureListItem method and WmDrawItem method of Checkbox */ 4479 jint AwtComponent::GetFontHeight(JNIEnv *env) 4480 { 4481 if (env->EnsureLocalCapacity(4) < 0) { 4482 return NULL; 4483 } 4484 jobject self = GetPeer(env); 4485 jobject target = env->GetObjectField(self, AwtObject::targetID); 4486 4487 jobject font = GET_FONT(target, self); 4488 jobject toolkit = env->CallObjectMethod(target, 4489 AwtComponent::getToolkitMID); 4490 4491 DASSERT(!safe_ExceptionOccurred(env)); 4492 4493 jobject fontMetrics = 4494 env->CallObjectMethod(toolkit, AwtToolkit::getFontMetricsMID, font); 4495 4496 DASSERT(!safe_ExceptionOccurred(env)); 4497 4498 jint height = env->CallIntMethod(fontMetrics, AwtFont::getHeightMID); 4499 DASSERT(!safe_ExceptionOccurred(env)); 4500 4501 env->DeleteLocalRef(target); 4502 env->DeleteLocalRef(font); 4503 env->DeleteLocalRef(toolkit); 4504 env->DeleteLocalRef(fontMetrics); 4505 4506 return height; 4507 } 4508 4509 // If you override WmPrint, make sure to save a copy of the DC on the GDI 4510 // stack to be restored in WmPrintClient. Windows mangles the DC in 4511 // ::DefWindowProc. 4512 MsgRouting AwtComponent::WmPrint(HDC hDC, LPARAM flags) 4513 { 4514 /* 4515 * DefWindowProc for WM_PRINT changes DC parameters, so we have 4516 * to restore it ourselves. Otherwise it will cause problems 4517 * when several components are printed to the same DC. 4518 */ 4519 int nOriginalDC = ::SaveDC(hDC); 4520 DASSERT(nOriginalDC != 0); 4521 4522 if (flags & PRF_NONCLIENT) { 4523 4524 VERIFY(::SaveDC(hDC)); 4525 4526 DefWindowProc(WM_PRINT, (WPARAM)hDC, 4527 (flags & (PRF_NONCLIENT 4528 | PRF_CHECKVISIBLE | PRF_ERASEBKGND))); 4529 4530 VERIFY(::RestoreDC(hDC, -1)); 4531 4532 // Special case for components with a sunken border. Windows does not 4533 // print the border correctly on PCL printers, so we have to do it ourselves. 4534 if (GetStyleEx() & WS_EX_CLIENTEDGE) { 4535 RECT r; 4536 VERIFY(::GetWindowRect(GetHWnd(), &r)); 4537 VERIFY(::OffsetRect(&r, -r.left, -r.top)); 4538 VERIFY(::DrawEdge(hDC, &r, EDGE_SUNKEN, BF_RECT)); 4539 } 4540 } 4541 4542 if (flags & PRF_CLIENT) { 4543 4544 /* 4545 * Special case for components with a sunken border. 4546 * Windows prints a client area without offset to a border width. 4547 * We will first print the non-client area with the original offset, 4548 * then the client area with a corrected offset. 4549 */ 4550 if (GetStyleEx() & WS_EX_CLIENTEDGE) { 4551 4552 int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE); 4553 int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE); 4554 4555 VERIFY(::OffsetWindowOrgEx(hDC, -nEdgeWidth, -nEdgeHeight, NULL)); 4556 4557 // Save a copy of the DC for WmPrintClient 4558 VERIFY(::SaveDC(hDC)); 4559 4560 DefWindowProc(WM_PRINT, (WPARAM) hDC, 4561 (flags & (PRF_CLIENT 4562 | PRF_CHECKVISIBLE | PRF_ERASEBKGND))); 4563 4564 VERIFY(::OffsetWindowOrgEx(hDC, nEdgeWidth, nEdgeHeight, NULL)); 4565 4566 } else { 4567 4568 // Save a copy of the DC for WmPrintClient 4569 VERIFY(::SaveDC(hDC)); 4570 DefWindowProc(WM_PRINT, (WPARAM) hDC, 4571 (flags & (PRF_CLIENT 4572 | PRF_CHECKVISIBLE | PRF_ERASEBKGND))); 4573 } 4574 } 4575 4576 if (flags & (PRF_CHILDREN | PRF_OWNED)) { 4577 DefWindowProc(WM_PRINT, (WPARAM) hDC, 4578 (flags & ~PRF_CLIENT & ~PRF_NONCLIENT)); 4579 } 4580 4581 VERIFY(::RestoreDC(hDC, nOriginalDC)); 4582 4583 return mrConsume; 4584 } 4585 4586 // If you override WmPrintClient, make sure to obtain a valid copy of 4587 // the DC from the GDI stack. The copy of the DC should have been placed 4588 // there by WmPrint. Windows mangles the DC in ::DefWindowProc. 4589 MsgRouting AwtComponent::WmPrintClient(HDC hDC, LPARAM) 4590 { 4591 // obtain valid DC from GDI stack 4592 ::RestoreDC(hDC, -1); 4593 4594 return mrDoDefault; 4595 } 4596 4597 MsgRouting AwtComponent::WmNcCalcSize(BOOL fCalcValidRects, 4598 LPNCCALCSIZE_PARAMS lpncsp, 4599 LRESULT &retVal) 4600 { 4601 return mrDoDefault; 4602 } 4603 4604 MsgRouting AwtComponent::WmNcPaint(HRGN hrgn) 4605 { 4606 return mrDoDefault; 4607 } 4608 4609 MsgRouting AwtComponent::WmNcHitTest(UINT x, UINT y, LRESULT &retVal) 4610 { 4611 return mrDoDefault; 4612 } 4613 4614 /** 4615 * WmQueryNewPalette is called whenever our component is coming to 4616 * the foreground; this gives us an opportunity to install our 4617 * custom palette. If this install actually changes entries in 4618 * the system palette, then we get a further call to WmPaletteChanged 4619 * (but note that we only need to realize our palette once). 4620 */ 4621 MsgRouting AwtComponent::WmQueryNewPalette(LRESULT &retVal) 4622 { 4623 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); 4624 m_QueryNewPaletteCalled = TRUE; 4625 HDC hDC = ::GetDC(GetHWnd()); 4626 DASSERT(hDC); 4627 AwtWin32GraphicsDevice::SelectPalette(hDC, screen); 4628 AwtWin32GraphicsDevice::RealizePalette(hDC, screen); 4629 ::ReleaseDC(GetHWnd(), hDC); 4630 // We must realize the palettes of all of our DC's 4631 // There is sometimes a problem where the realization of 4632 // our temporary hDC here does not actually do what 4633 // we want. Not clear why, but presumably fallout from 4634 // our use of several simultaneous hDC's. 4635 activeDCList.RealizePalettes(screen); 4636 // Do not invalidate here; if the palette 4637 // has not changed we will get an extra repaint 4638 retVal = TRUE; 4639 4640 return mrDoDefault; 4641 } 4642 4643 /** 4644 * We should not need to track this event since we handle our 4645 * palette management effectively in the WmQueryNewPalette and 4646 * WmPaletteChanged methods. However, there seems to be a bug 4647 * on some win32 systems (e.g., NT4) whereby the palette 4648 * immediately after a displayChange is not yet updated to its 4649 * final post-display-change values (hence we adjust our palette 4650 * using the wrong system palette entries), then the palette is 4651 * updated, but a WM_PALETTECHANGED message is never sent. 4652 * By tracking the ISCHANGING message as well (and by tracking 4653 * displayChange events in the AwtToolkit object), we can account 4654 * for this error by forcing our WmPaletteChanged method to be 4655 * called and thereby realizing our logical palette and updating 4656 * our dynamic colorModel object. 4657 */ 4658 MsgRouting AwtComponent::WmPaletteIsChanging(HWND hwndPalChg) 4659 { 4660 if (AwtToolkit::GetInstance().HasDisplayChanged()) { 4661 WmPaletteChanged(hwndPalChg); 4662 AwtToolkit::GetInstance().ResetDisplayChanged(); 4663 } 4664 return mrDoDefault; 4665 } 4666 4667 MsgRouting AwtComponent::WmPaletteChanged(HWND hwndPalChg) 4668 { 4669 // We need to re-realize our palette here (unless we're the one 4670 // that was realizing it in the first place). That will let us match the 4671 // remaining colors in the system palette as best we can. We always 4672 // invalidate because the palette will have changed when we receive this 4673 // message. 4674 4675 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); 4676 if (hwndPalChg != GetHWnd()) { 4677 HDC hDC = ::GetDC(GetHWnd()); 4678 DASSERT(hDC); 4679 AwtWin32GraphicsDevice::SelectPalette(hDC, screen); 4680 AwtWin32GraphicsDevice::RealizePalette(hDC, screen); 4681 ::ReleaseDC(GetHWnd(), hDC); 4682 // We must realize the palettes of all of our DC's 4683 activeDCList.RealizePalettes(screen); 4684 } 4685 if (AwtWin32GraphicsDevice::UpdateSystemPalette(screen)) { 4686 AwtWin32GraphicsDevice::UpdateDynamicColorModel(screen); 4687 } 4688 Invalidate(NULL); 4689 return mrDoDefault; 4690 } 4691 4692 MsgRouting AwtComponent::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss) 4693 { 4694 DASSERT(!IsBadReadPtr(lpss, sizeof(STYLESTRUCT))); 4695 return mrDoDefault; 4696 } 4697 4698 MsgRouting AwtComponent::WmSettingChange(UINT wFlag, LPCTSTR pszSection) 4699 { 4700 DASSERT(!IsBadStringPtr(pszSection, 20)); 4701 DTRACE_PRINTLN2("WM_SETTINGCHANGE: wFlag=%d pszSection=%s", (int)wFlag, pszSection); 4702 return mrDoDefault; 4703 } 4704 4705 HDC AwtComponent::GetDCFromComponent() 4706 { 4707 GetDCReturnStruct *hdcStruct = 4708 (GetDCReturnStruct*)SendMessage(WM_AWT_GETDC); 4709 HDC hdc; 4710 if (hdcStruct) { 4711 if (hdcStruct->gdiLimitReached) { 4712 if (jvm != NULL) { 4713 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4714 if (env != NULL && !safe_ExceptionOccurred(env)) { 4715 JNU_ThrowByName(env, "java/awt/AWTError", 4716 "HDC creation failure - " \ 4717 "exceeded maximum GDI resources"); 4718 } 4719 } 4720 } 4721 hdc = hdcStruct->hDC; 4722 delete hdcStruct; 4723 } else { 4724 hdc = NULL; 4725 } 4726 return hdc; 4727 } 4728 4729 void AwtComponent::FillBackground(HDC hMemoryDC, SIZE &size) 4730 { 4731 RECT eraseR = { 0, 0, size.cx, size.cy }; 4732 VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush())); 4733 } 4734 4735 void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha) 4736 { 4737 if (!bitmapBits) { 4738 return; 4739 } 4740 4741 DWORD* dest = (DWORD*)bitmapBits; 4742 //XXX: might be optimized to use one loop (cy*cx -> 0) 4743 for (int i = 0; i < size.cy; i++ ) { 4744 for (int j = 0; j < size.cx; j++ ) { 4745 ((BYTE*)(dest++))[3] = alpha; 4746 } 4747 } 4748 } 4749 4750 int AwtComponent::ScaleUpX(int x) { 4751 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); 4752 Devices::InstanceAccess devices; 4753 AwtWin32GraphicsDevice* device = devices->GetDevice(screen); 4754 return device == NULL ? x : device->ScaleUpX(x); 4755 } 4756 4757 int AwtComponent::ScaleUpY(int y) { 4758 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); 4759 Devices::InstanceAccess devices; 4760 AwtWin32GraphicsDevice* device = devices->GetDevice(screen); 4761 return device == NULL ? y : device->ScaleUpY(y); 4762 } 4763 4764 int AwtComponent::ScaleDownX(int x) { 4765 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); 4766 Devices::InstanceAccess devices; 4767 AwtWin32GraphicsDevice* device = devices->GetDevice(screen); 4768 return device == NULL ? x : device->ScaleDownX(x); 4769 } 4770 4771 int AwtComponent::ScaleDownY(int y) { 4772 int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); 4773 Devices::InstanceAccess devices; 4774 AwtWin32GraphicsDevice* device = devices->GetDevice(screen); 4775 return device == NULL ? y : device->ScaleDownY(y); 4776 } 4777 4778 jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) { 4779 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4780 4781 if (!::IsWindowVisible(GetHWnd())) { 4782 return NULL; 4783 } 4784 4785 HDC hdc = GetDCFromComponent(); 4786 if (!hdc) { 4787 return NULL; 4788 } 4789 HDC hMemoryDC = ::CreateCompatibleDC(hdc); 4790 void *bitmapBits = NULL; 4791 HBITMAP hBitmap = BitmapUtil::CreateARGBBitmap(size.cx, size.cy, &bitmapBits); 4792 HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemoryDC, hBitmap); 4793 SendMessage(WM_AWT_RELEASEDC, (WPARAM)hdc); 4794 4795 FillBackground(hMemoryDC, size); 4796 4797 VERIFY(::SetWindowOrgEx(hMemoryDC, loc.cx, loc.cy, NULL)); 4798 4799 // Don't bother with PRF_CHECKVISIBLE because we called IsWindowVisible 4800 // above. 4801 SendMessage(WM_PRINT, (WPARAM)hMemoryDC, PRF_CLIENT | PRF_NONCLIENT); 4802 4803 // First make sure the system completed any drawing to the bitmap. 4804 ::GdiFlush(); 4805 4806 // WM_PRINT does not fill the alpha-channel of the ARGB bitmap 4807 // leaving it equal to zero. Hence we need to fill it manually. Otherwise 4808 // the pixels will be considered transparent when interpreting the data. 4809 FillAlpha(bitmapBits, size, alpha); 4810 4811 ::SelectObject(hMemoryDC, hOldBitmap); 4812 4813 BITMAPINFO bmi; 4814 memset(&bmi, 0, sizeof(BITMAPINFO)); 4815 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 4816 bmi.bmiHeader.biWidth = size.cx; 4817 bmi.bmiHeader.biHeight = -size.cy; 4818 bmi.bmiHeader.biPlanes = 1; 4819 bmi.bmiHeader.biBitCount = 32; 4820 bmi.bmiHeader.biCompression = BI_RGB; 4821 4822 jobject localPixelArray = env->NewIntArray(size.cx * size.cy); 4823 jintArray pixelArray = NULL; 4824 if (localPixelArray != NULL) { 4825 pixelArray = (jintArray)env->NewGlobalRef(localPixelArray); 4826 env->DeleteLocalRef(localPixelArray); localPixelArray = NULL; 4827 4828 jboolean isCopy; 4829 jint *pixels = env->GetIntArrayElements(pixelArray, &isCopy); 4830 4831 ::GetDIBits(hMemoryDC, hBitmap, 0, size.cy, (LPVOID)pixels, &bmi, 4832 DIB_RGB_COLORS); 4833 4834 env->ReleaseIntArrayElements(pixelArray, pixels, 0); 4835 } 4836 4837 VERIFY(::DeleteObject(hBitmap)); 4838 VERIFY(::DeleteDC(hMemoryDC)); 4839 4840 return pixelArray; 4841 } 4842 4843 void* AwtComponent::SetNativeFocusOwner(void *self) { 4844 if (self == NULL) { 4845 // It means that the KFM wants to set focus to null 4846 sm_focusOwner = NULL; 4847 return NULL; 4848 } 4849 4850 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4851 4852 AwtComponent *c = NULL; 4853 jobject peer = (jobject)self; 4854 4855 PDATA pData; 4856 JNI_CHECK_NULL_GOTO(peer, "peer", ret); 4857 pData = JNI_GET_PDATA(peer); 4858 if (pData == NULL) { 4859 goto ret; 4860 } 4861 c = (AwtComponent *)pData; 4862 4863 ret: 4864 if (c && ::IsWindow(c->GetHWnd())) { 4865 sm_focusOwner = c->GetHWnd(); 4866 } else { 4867 sm_focusOwner = NULL; 4868 } 4869 env->DeleteGlobalRef(peer); 4870 return NULL; 4871 } 4872 4873 void* AwtComponent::GetNativeFocusedWindow() { 4874 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4875 AwtComponent *comp = 4876 AwtComponent::GetComponent(AwtComponent::GetFocusedWindow()); 4877 return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL; 4878 } 4879 4880 void* AwtComponent::GetNativeFocusOwner() { 4881 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4882 AwtComponent *comp = 4883 AwtComponent::GetComponent(AwtComponent::sm_focusOwner); 4884 return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL; 4885 } 4886 4887 AwtComponent* AwtComponent::SearchChild(UINT id) { 4888 ChildListItem* child; 4889 for (child = m_childList; child != NULL;child = child->m_next) { 4890 if (child->m_ID == id) 4891 return child->m_Component; 4892 } 4893 /* 4894 * DASSERT(FALSE); 4895 * This should not be happend if all children are recorded 4896 */ 4897 return NULL; /* make compiler happy */ 4898 } 4899 4900 void AwtComponent::RemoveChild(UINT id) { 4901 ChildListItem* child = m_childList; 4902 ChildListItem* lastChild = NULL; 4903 while (child != NULL) { 4904 if (child->m_ID == id) { 4905 if (lastChild == NULL) { 4906 m_childList = child->m_next; 4907 } else { 4908 lastChild->m_next = child->m_next; 4909 } 4910 child->m_next = NULL; 4911 DASSERT(child != NULL); 4912 delete child; 4913 return; 4914 } 4915 lastChild = child; 4916 child = child->m_next; 4917 } 4918 } 4919 4920 void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked, 4921 jint modifiers, jint keyLocation, jlong nativeCode, MSG *pMsg) 4922 { 4923 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 4924 CriticalSection::Lock l(GetLock()); 4925 if (GetPeer(env) == NULL) { 4926 /* event received during termination. */ 4927 return; 4928 } 4929 4930 static jclass keyEventCls; 4931 if (keyEventCls == NULL) { 4932 jclass keyEventClsLocal = env->FindClass("java/awt/event/KeyEvent"); 4933 DASSERT(keyEventClsLocal); 4934 if (keyEventClsLocal == NULL) { 4935 /* exception already thrown */ 4936 return; 4937 } 4938 keyEventCls = (jclass)env->NewGlobalRef(keyEventClsLocal); 4939 env->DeleteLocalRef(keyEventClsLocal); 4940 } 4941 4942 static jmethodID keyEventConst; 4943 if (keyEventConst == NULL) { 4944 keyEventConst = env->GetMethodID(keyEventCls, "<init>", 4945 "(Ljava/awt/Component;IJIICI)V"); 4946 DASSERT(keyEventConst); 4947 CHECK_NULL(keyEventConst); 4948 } 4949 if (env->EnsureLocalCapacity(2) < 0) { 4950 return; 4951 } 4952 jobject target = GetTarget(env); 4953 jobject keyEvent = env->NewObject(keyEventCls, keyEventConst, target, 4954 id, when, modifiers, raw, cooked, 4955 keyLocation); 4956 if (safe_ExceptionOccurred(env)) env->ExceptionDescribe(); 4957 DASSERT(!safe_ExceptionOccurred(env)); 4958 DASSERT(keyEvent != NULL); 4959 if (keyEvent == NULL) { 4960 env->DeleteLocalRef(target); 4961 return; 4962 } 4963 env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode); 4964 if( nativeCode && nativeCode < 256 ) { 4965 env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode)); 4966 env->SetLongField(keyEvent, AwtKeyEvent::extendedKeyCodeID, (jlong)(dynPrimaryKeymap[nativeCode].jkey)); 4967 if( nativeCode < 255 ) { 4968 env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(dynPrimaryKeymap[nativeCode].scancode)); 4969 }else if( pMsg != NULL ) { 4970 // unknown key with virtual keycode 0xFF. 4971 // Its scancode is not in the table, pickup it from the message. 4972 env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(HIWORD(pMsg->lParam) & 0xFF)); 4973 } 4974 } 4975 if (pMsg != NULL) { 4976 AwtAWTEvent::saveMSG(env, pMsg, keyEvent); 4977 } 4978 SendEvent(keyEvent); 4979 4980 env->DeleteLocalRef(keyEvent); 4981 env->DeleteLocalRef(target); 4982 } 4983 4984 void 4985 AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when, 4986 jint raw, jint cooked, 4987 jint modifiers, jint keyLocation, 4988 jlong nativeCode, 4989 MSG *msg) 4990 { 4991 /* 4992 * if focus owner is null, but focused window isn't 4993 * we will send key event to focused window 4994 */ 4995 HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : AwtComponent::GetFocusedWindow()); 4996 4997 if (hwndTarget == GetHWnd()) { 4998 SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, nativeCode, msg); 4999 } else { 5000 AwtComponent *target = NULL; 5001 if (hwndTarget != NULL) { 5002 target = AwtComponent::GetComponent(hwndTarget); 5003 if (target == NULL) { 5004 target = this; 5005 } 5006 } 5007 if (target != NULL) { 5008 target->SendKeyEvent(id, when, raw, cooked, modifiers, 5009 keyLocation, nativeCode, msg); 5010 } 5011 } 5012 } 5013 5014 void AwtComponent::SetDragCapture(UINT flags) 5015 { 5016 // don't want to interfere with other controls 5017 if (::GetCapture() == NULL) { 5018 ::SetCapture(GetHWnd()); 5019 } 5020 } 5021 5022 void AwtComponent::ReleaseDragCapture(UINT flags) 5023 { 5024 if ((::GetCapture() == GetHWnd()) && ((flags & ALL_MK_BUTTONS) == 0)) { 5025 // user has released all buttons, so release the capture 5026 ::ReleaseCapture(); 5027 } 5028 } 5029 5030 void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y, 5031 jint modifiers, jint clickCount, 5032 jboolean popupTrigger, jint button, 5033 MSG *pMsg, BOOL causedByTouchEvent) 5034 { 5035 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5036 CriticalSection::Lock l(GetLock()); 5037 if (GetPeer(env) == NULL) { 5038 /* event received during termination. */ 5039 return; 5040 } 5041 5042 static jclass mouseEventCls; 5043 if (mouseEventCls == NULL) { 5044 jclass mouseEventClsLocal = 5045 env->FindClass("java/awt/event/MouseEvent"); 5046 CHECK_NULL(mouseEventClsLocal); 5047 mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal); 5048 env->DeleteLocalRef(mouseEventClsLocal); 5049 } 5050 RECT insets; 5051 GetInsets(&insets); 5052 5053 static jmethodID mouseEventConst; 5054 if (mouseEventConst == NULL) { 5055 mouseEventConst = 5056 env->GetMethodID(mouseEventCls, "<init>", 5057 "(Ljava/awt/Component;IJIIIIIIZI)V"); 5058 DASSERT(mouseEventConst); 5059 CHECK_NULL(mouseEventConst); 5060 } 5061 if (env->EnsureLocalCapacity(2) < 0) { 5062 return; 5063 } 5064 jobject target = GetTarget(env); 5065 DWORD curMousePos = ::GetMessagePos(); 5066 int xAbs = GET_X_LPARAM(curMousePos); 5067 int yAbs = GET_Y_LPARAM(curMousePos); 5068 jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst, 5069 target, 5070 id, when, modifiers, 5071 ScaleDownX(x + insets.left), 5072 ScaleDownY(y + insets.top), 5073 ScaleDownX(xAbs), ScaleDownY(yAbs), 5074 clickCount, popupTrigger, button); 5075 5076 if (safe_ExceptionOccurred(env)) { 5077 env->ExceptionDescribe(); 5078 env->ExceptionClear(); 5079 } 5080 5081 DASSERT(mouseEvent != NULL); 5082 CHECK_NULL(mouseEvent); 5083 if (causedByTouchEvent) { 5084 env->SetBooleanField(mouseEvent, AwtMouseEvent::causedByTouchEventID, 5085 JNI_TRUE); 5086 } 5087 if (pMsg != 0) { 5088 AwtAWTEvent::saveMSG(env, pMsg, mouseEvent); 5089 } 5090 SendEvent(mouseEvent); 5091 5092 env->DeleteLocalRef(mouseEvent); 5093 env->DeleteLocalRef(target); 5094 } 5095 5096 void 5097 AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y, 5098 jint modifiers, jint clickCount, 5099 jboolean popupTrigger, jint scrollType, 5100 jint scrollAmount, jint roundedWheelRotation, 5101 jdouble preciseWheelRotation, MSG *pMsg) 5102 { 5103 /* Code based not so loosely on AwtComponent::SendMouseEvent */ 5104 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5105 CriticalSection::Lock l(GetLock()); 5106 if (GetPeer(env) == NULL) { 5107 /* event received during termination. */ 5108 return; 5109 } 5110 5111 static jclass mouseWheelEventCls; 5112 if (mouseWheelEventCls == NULL) { 5113 jclass mouseWheelEventClsLocal = 5114 env->FindClass("java/awt/event/MouseWheelEvent"); 5115 CHECK_NULL(mouseWheelEventClsLocal); 5116 mouseWheelEventCls = (jclass)env->NewGlobalRef(mouseWheelEventClsLocal); 5117 env->DeleteLocalRef(mouseWheelEventClsLocal); 5118 } 5119 RECT insets; 5120 GetInsets(&insets); 5121 5122 static jmethodID mouseWheelEventConst; 5123 if (mouseWheelEventConst == NULL) { 5124 mouseWheelEventConst = 5125 env->GetMethodID(mouseWheelEventCls, "<init>", 5126 "(Ljava/awt/Component;IJIIIIIIZIIID)V"); 5127 DASSERT(mouseWheelEventConst); 5128 CHECK_NULL(mouseWheelEventConst); 5129 } 5130 if (env->EnsureLocalCapacity(2) < 0) { 5131 return; 5132 } 5133 jobject target = GetTarget(env); 5134 DWORD curMousePos = ::GetMessagePos(); 5135 int xAbs = GET_X_LPARAM(curMousePos); 5136 int yAbs = GET_Y_LPARAM(curMousePos); 5137 5138 DTRACE_PRINTLN("creating MWE in JNI"); 5139 5140 jobject mouseWheelEvent = env->NewObject(mouseWheelEventCls, 5141 mouseWheelEventConst, 5142 target, 5143 id, when, modifiers, 5144 ScaleDownX(x + insets.left), 5145 ScaleDownY(y + insets.top), 5146 ScaleDownX(xAbs), 5147 ScaleDownY(yAbs), 5148 clickCount, popupTrigger, 5149 scrollType, scrollAmount, 5150 roundedWheelRotation, preciseWheelRotation); 5151 5152 DASSERT(mouseWheelEvent != NULL); 5153 if (mouseWheelEvent == NULL || safe_ExceptionOccurred(env)) { 5154 env->ExceptionDescribe(); 5155 env->ExceptionClear(); 5156 env->DeleteLocalRef(target); 5157 return; 5158 } 5159 if (pMsg != NULL) { 5160 AwtAWTEvent::saveMSG(env, pMsg, mouseWheelEvent); 5161 } 5162 SendEvent(mouseWheelEvent); 5163 5164 env->DeleteLocalRef(mouseWheelEvent); 5165 env->DeleteLocalRef(target); 5166 } 5167 5168 void AwtComponent::SendFocusEvent(jint id, HWND opposite) 5169 { 5170 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5171 5172 CriticalSection::Lock l(GetLock()); 5173 if (GetPeer(env) == NULL) { 5174 /* event received during termination. */ 5175 return; 5176 } 5177 5178 static jclass focusEventCls; 5179 if (focusEventCls == NULL) { 5180 jclass focusEventClsLocal 5181 = env->FindClass("java/awt/event/FocusEvent"); 5182 DASSERT(focusEventClsLocal); 5183 CHECK_NULL(focusEventClsLocal); 5184 focusEventCls = (jclass)env->NewGlobalRef(focusEventClsLocal); 5185 env->DeleteLocalRef(focusEventClsLocal); 5186 } 5187 5188 static jmethodID focusEventConst; 5189 if (focusEventConst == NULL) { 5190 focusEventConst = 5191 env->GetMethodID(focusEventCls, "<init>", 5192 "(Ljava/awt/Component;IZLjava/awt/Component;)V"); 5193 DASSERT(focusEventConst); 5194 CHECK_NULL(focusEventConst); 5195 } 5196 5197 static jclass sequencedEventCls; 5198 if (sequencedEventCls == NULL) { 5199 jclass sequencedEventClsLocal = 5200 env->FindClass("java/awt/SequencedEvent"); 5201 DASSERT(sequencedEventClsLocal); 5202 CHECK_NULL(sequencedEventClsLocal); 5203 sequencedEventCls = 5204 (jclass)env->NewGlobalRef(sequencedEventClsLocal); 5205 env->DeleteLocalRef(sequencedEventClsLocal); 5206 } 5207 5208 static jmethodID sequencedEventConst; 5209 if (sequencedEventConst == NULL) { 5210 sequencedEventConst = 5211 env->GetMethodID(sequencedEventCls, "<init>", 5212 "(Ljava/awt/AWTEvent;)V"); 5213 DASSERT(sequencedEventConst); 5214 CHECK_NULL(sequencedEventConst); 5215 } 5216 5217 if (env->EnsureLocalCapacity(3) < 0) { 5218 return; 5219 } 5220 5221 jobject target = GetTarget(env); 5222 jobject jOpposite = NULL; 5223 if (opposite != NULL) { 5224 AwtComponent *awtOpposite = AwtComponent::GetComponent(opposite); 5225 if (awtOpposite != NULL) { 5226 jOpposite = awtOpposite->GetTarget(env); 5227 } 5228 } 5229 jobject focusEvent = env->NewObject(focusEventCls, focusEventConst, 5230 target, id, JNI_FALSE, jOpposite); 5231 DASSERT(!safe_ExceptionOccurred(env)); 5232 DASSERT(focusEvent != NULL); 5233 if (jOpposite != NULL) { 5234 env->DeleteLocalRef(jOpposite); jOpposite = NULL; 5235 } 5236 env->DeleteLocalRef(target); target = NULL; 5237 CHECK_NULL(focusEvent); 5238 5239 jobject sequencedEvent = env->NewObject(sequencedEventCls, 5240 sequencedEventConst, 5241 focusEvent); 5242 DASSERT(!safe_ExceptionOccurred(env)); 5243 DASSERT(sequencedEvent != NULL); 5244 env->DeleteLocalRef(focusEvent); focusEvent = NULL; 5245 CHECK_NULL(sequencedEvent); 5246 SendEvent(sequencedEvent); 5247 5248 env->DeleteLocalRef(sequencedEvent); 5249 } 5250 5251 /* 5252 * Forward a filtered event directly to the subclassed window. 5253 * This method is needed so that DefWindowProc is invoked on the 5254 * component's owning thread. 5255 */ 5256 MsgRouting AwtComponent::HandleEvent(MSG *msg, BOOL) 5257 { 5258 DefWindowProc(msg->message, msg->wParam, msg->lParam); 5259 delete msg; 5260 return mrConsume; 5261 } 5262 5263 /* Post a WM_AWT_HANDLE_EVENT message which invokes HandleEvent 5264 on the toolkit thread. This method may pre-filter the messages. */ 5265 BOOL AwtComponent::PostHandleEventMessage(MSG *msg, BOOL synthetic) 5266 { 5267 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5268 // We should cut off keyboard events to disabled components 5269 // to avoid the components responding visually to keystrokes when disabled. 5270 // we shouldn't cut off WM_SYS* messages as they aren't used for normal activity 5271 // but to activate menus, close windows, etc 5272 switch(msg->message) { 5273 case WM_KEYDOWN: 5274 case WM_KEYUP: 5275 case WM_CHAR: 5276 case WM_DEADCHAR: 5277 { 5278 if (!isRecursivelyEnabled()) { 5279 goto quit; 5280 } 5281 break; 5282 } 5283 } 5284 if (PostMessage(GetHWnd(), WM_AWT_HANDLE_EVENT, 5285 (WPARAM) synthetic, (LPARAM) msg)) { 5286 return TRUE; 5287 } else { 5288 JNU_ThrowInternalError(env, "Message not posted, native event queue may be full."); 5289 } 5290 quit: 5291 delete msg; 5292 return FALSE; 5293 } 5294 5295 void AwtComponent::SynthesizeKeyMessage(JNIEnv *env, jobject keyEvent) 5296 { 5297 jint id = (env)->GetIntField(keyEvent, AwtAWTEvent::idID); 5298 UINT message; 5299 switch (id) { 5300 case java_awt_event_KeyEvent_KEY_PRESSED: 5301 message = WM_KEYDOWN; 5302 break; 5303 case java_awt_event_KeyEvent_KEY_RELEASED: 5304 message = WM_KEYUP; 5305 break; 5306 case java_awt_event_KeyEvent_KEY_TYPED: 5307 message = WM_CHAR; 5308 break; 5309 default: 5310 return; 5311 } 5312 5313 /* 5314 * KeyEvent.modifiers aren't supported -- the Java apppwd must send separate 5315 * KEY_PRESSED and KEY_RELEASED events for the modifier virtual keys. 5316 */ 5317 if (id == java_awt_event_KeyEvent_KEY_TYPED) { 5318 // WM_CHAR message must be posted using WM_AWT_FORWARD_CHAR 5319 // (for Edit control) 5320 jchar keyChar = (jchar) 5321 (env)->GetCharField(keyEvent, AwtKeyEvent::keyCharID); 5322 5323 // Bugid 4724007. If it is a Delete character, don't send the fake 5324 // KEY_TYPED we created back to the native window: Windows doesn't 5325 // expect a WM_CHAR for Delete in TextFields, so it tries to enter a 5326 // character after deleting. 5327 if (keyChar == '\177') { // the Delete character 5328 return; 5329 } 5330 5331 // Disable forwarding WM_CHAR messages to disabled components 5332 if (isRecursivelyEnabled()) { 5333 if (!::PostMessage(GetHWnd(), WM_AWT_FORWARD_CHAR, 5334 MAKEWPARAM(keyChar, TRUE), 0)) { 5335 JNU_ThrowInternalError(env, "Message not posted, native event queue may be full."); 5336 } 5337 } 5338 } else { 5339 jint keyCode = 5340 (env)->GetIntField(keyEvent, AwtKeyEvent::keyCodeID); 5341 UINT key, modifiers; 5342 AwtComponent::JavaKeyToWindowsKey(keyCode, &key, &modifiers); 5343 MSG* msg = CreateMessage(message, key, 0); 5344 PostHandleEventMessage(msg, TRUE); 5345 } 5346 } 5347 5348 void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent) 5349 { 5350 /* DebugBreak(); */ 5351 jint button = (env)->GetIntField(mouseEvent, AwtMouseEvent::buttonID); 5352 jint modifiers = (env)->GetIntField(mouseEvent, AwtInputEvent::modifiersID); 5353 5354 WPARAM wParam = 0; 5355 WORD wLow = 0; 5356 jint wheelAmt = 0; 5357 jint id = (env)->GetIntField(mouseEvent, AwtAWTEvent::idID); 5358 UINT message; 5359 switch (id) { 5360 case java_awt_event_MouseEvent_MOUSE_PRESSED: { 5361 switch (button) { 5362 case java_awt_event_MouseEvent_BUTTON1: 5363 message = WM_LBUTTONDOWN; break; 5364 case java_awt_event_MouseEvent_BUTTON3: 5365 message = WM_MBUTTONDOWN; break; 5366 case java_awt_event_MouseEvent_BUTTON2: 5367 message = WM_RBUTTONDOWN; break; 5368 default: 5369 return; 5370 } 5371 break; 5372 } 5373 case java_awt_event_MouseEvent_MOUSE_RELEASED: { 5374 switch (button) { 5375 case java_awt_event_MouseEvent_BUTTON1: 5376 message = WM_LBUTTONUP; break; 5377 case java_awt_event_MouseEvent_BUTTON3: 5378 message = WM_MBUTTONUP; break; 5379 case java_awt_event_MouseEvent_BUTTON2: 5380 message = WM_RBUTTONUP; break; 5381 default: 5382 return; 5383 } 5384 break; 5385 } 5386 case java_awt_event_MouseEvent_MOUSE_MOVED: 5387 /* MOUSE_DRAGGED events must first have sent a MOUSE_PRESSED event. */ 5388 case java_awt_event_MouseEvent_MOUSE_DRAGGED: 5389 message = WM_MOUSEMOVE; 5390 break; 5391 case java_awt_event_MouseEvent_MOUSE_WHEEL: 5392 if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) { 5393 wLow |= MK_CONTROL; 5394 } 5395 if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) { 5396 wLow |= MK_SHIFT; 5397 } 5398 if (modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) { 5399 wLow |= MK_LBUTTON; 5400 } 5401 if (modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) { 5402 wLow |= MK_RBUTTON; 5403 } 5404 if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) { 5405 wLow |= MK_MBUTTON; 5406 } 5407 if (modifiers & X1_BUTTON) { 5408 wLow |= GetButtonMK(X1_BUTTON); 5409 } 5410 if (modifiers & X2_BUTTON) { 5411 wLow |= GetButtonMK(X2_BUTTON); 5412 } 5413 5414 wheelAmt = (jint)JNU_CallMethodByName(env, 5415 NULL, 5416 mouseEvent, 5417 "getWheelRotation", 5418 "()I").i; 5419 DASSERT(!safe_ExceptionOccurred(env)); 5420 JNU_CHECK_EXCEPTION(env); 5421 DTRACE_PRINTLN1("wheelAmt = %i\n", wheelAmt); 5422 5423 // convert Java wheel amount value to Win32 5424 wheelAmt *= -1 * WHEEL_DELTA; 5425 5426 message = WM_MOUSEWHEEL; 5427 wParam = MAKEWPARAM(wLow, wheelAmt); 5428 5429 break; 5430 default: 5431 return; 5432 } 5433 jint x = (env)->GetIntField(mouseEvent, AwtMouseEvent::xID); 5434 jint y = (env)->GetIntField(mouseEvent, AwtMouseEvent::yID); 5435 MSG* msg = CreateMessage(message, wParam, MAKELPARAM(x, y), x, y); 5436 PostHandleEventMessage(msg, TRUE); 5437 } 5438 5439 BOOL AwtComponent::InheritsNativeMouseWheelBehavior() {return false;} 5440 5441 void AwtComponent::Invalidate(RECT* r) 5442 { 5443 ::InvalidateRect(GetHWnd(), r, FALSE); 5444 } 5445 5446 void AwtComponent::BeginValidate() 5447 { 5448 DASSERT(m_validationNestCount >= 0 && 5449 m_validationNestCount < 1000); // sanity check 5450 5451 if (m_validationNestCount == 0) { 5452 // begin deferred window positioning if we're not inside 5453 // another Begin/EndValidate pair 5454 DASSERT(m_hdwp == NULL); 5455 m_hdwp = ::BeginDeferWindowPos(32); 5456 } 5457 5458 m_validationNestCount++; 5459 } 5460 5461 void AwtComponent::EndValidate() 5462 { 5463 DASSERT(m_validationNestCount > 0 && 5464 m_validationNestCount < 1000); // sanity check 5465 DASSERT(m_hdwp != NULL); 5466 5467 m_validationNestCount--; 5468 if (m_validationNestCount == 0) { 5469 // if this call to EndValidate is not nested inside another 5470 // Begin/EndValidate pair, end deferred window positioning 5471 ::EndDeferWindowPos(m_hdwp); 5472 m_hdwp = NULL; 5473 } 5474 } 5475 5476 /** 5477 * HWND, AwtComponent and Java Peer interaction 5478 */ 5479 5480 /* 5481 *Link the C++, Java peer, and HWNDs together. 5482 */ 5483 void AwtComponent::LinkObjects(JNIEnv *env, jobject peer) 5484 { 5485 /* 5486 * Bind all three objects together thru this C++ object, two-way to each: 5487 * JavaPeer <-> C++ <-> HWND 5488 * 5489 * C++ -> JavaPeer 5490 */ 5491 if (m_peerObject == NULL) { 5492 // This may have already been set up by CreateHWnd 5493 // And we don't want to create two references so we 5494 // will leave the prior one alone 5495 m_peerObject = env->NewGlobalRef(peer); 5496 } 5497 /* JavaPeer -> HWND */ 5498 env->SetLongField(peer, AwtComponent::hwndID, reinterpret_cast<jlong>(m_hwnd)); 5499 5500 /* JavaPeer -> C++ */ 5501 JNI_SET_PDATA(peer, this); 5502 5503 /* HWND -> C++ */ 5504 SetComponentInHWND(); 5505 } 5506 5507 /* Cleanup above linking */ 5508 void AwtComponent::UnlinkObjects() 5509 { 5510 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5511 if (m_peerObject) { 5512 env->SetLongField(m_peerObject, AwtComponent::hwndID, 0); 5513 JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL)); 5514 JNI_SET_DESTROYED(m_peerObject); 5515 env->DeleteGlobalRef(m_peerObject); 5516 m_peerObject = NULL; 5517 } 5518 } 5519 5520 void AwtComponent::Enable(BOOL bEnable) 5521 { 5522 if (bEnable && IsTopLevel()) { 5523 // we should not enable blocked toplevels 5524 bEnable = !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd())); 5525 } 5526 // Shouldn't trigger native focus change 5527 // (only the proxy may be the native focus owner). 5528 ::EnableWindow(GetHWnd(), bEnable); 5529 5530 CriticalSection::Lock l(GetLock()); 5531 VerifyState(); 5532 } 5533 5534 /* 5535 * associate an AwtDropTarget with this AwtComponent 5536 */ 5537 5538 AwtDropTarget* AwtComponent::CreateDropTarget(JNIEnv* env) { 5539 m_dropTarget = new AwtDropTarget(env, this); 5540 m_dropTarget->RegisterTarget(TRUE); 5541 return m_dropTarget; 5542 } 5543 5544 /* 5545 * disassociate an AwtDropTarget with this AwtComponent 5546 */ 5547 5548 void AwtComponent::DestroyDropTarget() { 5549 if (m_dropTarget != NULL) { 5550 m_dropTarget->RegisterTarget(FALSE); 5551 m_dropTarget->Release(); 5552 m_dropTarget = NULL; 5553 } 5554 } 5555 5556 BOOL AwtComponent::IsFocusingMouseMessage(MSG *pMsg) { 5557 return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK; 5558 } 5559 5560 BOOL AwtComponent::IsFocusingKeyMessage(MSG *pMsg) { 5561 return pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_SPACE; 5562 } 5563 5564 void AwtComponent::_Show(void *param) 5565 { 5566 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5567 5568 jobject self = (jobject)param; 5569 5570 AwtComponent *p; 5571 5572 PDATA pData; 5573 JNI_CHECK_PEER_GOTO(self, ret); 5574 p = (AwtComponent *)pData; 5575 if (::IsWindow(p->GetHWnd())) 5576 { 5577 p->SendMessage(WM_AWT_COMPONENT_SHOW); 5578 } 5579 ret: 5580 env->DeleteGlobalRef(self); 5581 } 5582 5583 void AwtComponent::_Hide(void *param) 5584 { 5585 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5586 5587 jobject self = (jobject)param; 5588 5589 AwtComponent *p; 5590 5591 PDATA pData; 5592 JNI_CHECK_PEER_GOTO(self, ret); 5593 p = (AwtComponent *)pData; 5594 if (::IsWindow(p->GetHWnd())) 5595 { 5596 p->SendMessage(WM_AWT_COMPONENT_HIDE); 5597 } 5598 ret: 5599 env->DeleteGlobalRef(self); 5600 } 5601 5602 void AwtComponent::_Enable(void *param) 5603 { 5604 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5605 5606 jobject self = (jobject)param; 5607 5608 AwtComponent *p; 5609 5610 PDATA pData; 5611 JNI_CHECK_PEER_GOTO(self, ret); 5612 p = (AwtComponent *)pData; 5613 if (::IsWindow(p->GetHWnd())) 5614 { 5615 p->Enable(TRUE); 5616 } 5617 ret: 5618 env->DeleteGlobalRef(self); 5619 } 5620 5621 void AwtComponent::_Disable(void *param) 5622 { 5623 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5624 5625 jobject self = (jobject)param; 5626 5627 AwtComponent *p; 5628 5629 PDATA pData; 5630 JNI_CHECK_PEER_GOTO(self, ret); 5631 p = (AwtComponent *)pData; 5632 if (::IsWindow(p->GetHWnd())) 5633 { 5634 p->Enable(FALSE); 5635 } 5636 ret: 5637 env->DeleteGlobalRef(self); 5638 } 5639 5640 jobject AwtComponent::_GetLocationOnScreen(void *param) 5641 { 5642 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5643 5644 jobject self = (jobject)param; 5645 5646 jobject result = NULL; 5647 AwtComponent *p; 5648 5649 PDATA pData; 5650 JNI_CHECK_PEER_GOTO(self, ret); 5651 p = (AwtComponent *)pData; 5652 if (::IsWindow(p->GetHWnd())) 5653 { 5654 RECT rect; 5655 VERIFY(::GetWindowRect(p->GetHWnd(),&rect)); 5656 result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V", 5657 p->ScaleDownX(rect.left), 5658 p->ScaleDownY(rect.top)); 5659 } 5660 ret: 5661 env->DeleteGlobalRef(self); 5662 5663 if (result != NULL) 5664 { 5665 jobject resultGlobalRef = env->NewGlobalRef(result); 5666 env->DeleteLocalRef(result); 5667 return resultGlobalRef; 5668 } 5669 else 5670 { 5671 return NULL; 5672 } 5673 } 5674 5675 void AwtComponent::_Reshape(void *param) 5676 { 5677 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5678 5679 ReshapeStruct *rs = (ReshapeStruct*)param; 5680 jobject self = rs->component; 5681 jint x = rs->x; 5682 jint y = rs->y; 5683 jint w = rs->w; 5684 jint h = rs->h; 5685 5686 AwtComponent *p; 5687 5688 PDATA pData; 5689 JNI_CHECK_PEER_GOTO(self, ret); 5690 p = (AwtComponent *)pData; 5691 if (::IsWindow(p->GetHWnd())) 5692 { 5693 RECT* r = new RECT; 5694 ::SetRect(r, x, y, x + w, y + h); 5695 p->SendMessage(WM_AWT_RESHAPE_COMPONENT, CHECK_EMBEDDED, (LPARAM)r); 5696 } 5697 ret: 5698 env->DeleteGlobalRef(self); 5699 5700 delete rs; 5701 } 5702 5703 void AwtComponent::_ReshapeNoCheck(void *param) 5704 { 5705 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5706 5707 ReshapeStruct *rs = (ReshapeStruct*)param; 5708 jobject self = rs->component; 5709 jint x = rs->x; 5710 jint y = rs->y; 5711 jint w = rs->w; 5712 jint h = rs->h; 5713 5714 AwtComponent *p; 5715 5716 PDATA pData; 5717 JNI_CHECK_PEER_GOTO(self, ret); 5718 p = (AwtComponent *)pData; 5719 if (::IsWindow(p->GetHWnd())) 5720 { 5721 RECT* r = new RECT; 5722 ::SetRect(r, x, y, x + w, y + h); 5723 p->SendMessage(WM_AWT_RESHAPE_COMPONENT, DONT_CHECK_EMBEDDED, (LPARAM)r); 5724 } 5725 ret: 5726 env->DeleteGlobalRef(self); 5727 5728 delete rs; 5729 } 5730 5731 void AwtComponent::_NativeHandleEvent(void *param) 5732 { 5733 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5734 5735 NativeHandleEventStruct *nhes = (NativeHandleEventStruct *)param; 5736 jobject self = nhes->component; 5737 jobject event = nhes->event; 5738 5739 AwtComponent *p; 5740 5741 PDATA pData; 5742 JNI_CHECK_NULL_GOTO(self, "peer", ret); 5743 pData = JNI_GET_PDATA(self); 5744 if (pData == NULL) { 5745 env->DeleteGlobalRef(self); 5746 if (event != NULL) { 5747 env->DeleteGlobalRef(event); 5748 } 5749 delete nhes; 5750 return; 5751 } 5752 JNI_CHECK_NULL_GOTO(event, "null AWTEvent", ret); 5753 5754 p = (AwtComponent *)pData; 5755 if (::IsWindow(p->GetHWnd())) 5756 { 5757 if (env->EnsureLocalCapacity(1) < 0) { 5758 env->DeleteGlobalRef(self); 5759 env->DeleteGlobalRef(event); 5760 delete nhes; 5761 return; 5762 } 5763 jbyteArray bdata = (jbyteArray)(env)->GetObjectField(event, AwtAWTEvent::bdataID); 5764 int id = (env)->GetIntField(event, AwtAWTEvent::idID); 5765 DASSERT(!safe_ExceptionOccurred(env)); 5766 if (bdata != 0) { 5767 MSG msg; 5768 (env)->GetByteArrayRegion(bdata, 0, sizeof(MSG), (jbyte *)&msg); 5769 (env)->DeleteLocalRef(bdata); 5770 static BOOL keyDownConsumed = FALSE; 5771 static BOOL bCharChanged = FALSE; 5772 static WCHAR modifiedChar; 5773 WCHAR unicodeChar; 5774 5775 /* Remember if a KEY_PRESSED event is consumed, as an old model 5776 * program won't consume a subsequent KEY_TYPED event. 5777 */ 5778 jboolean consumed = 5779 (env)->GetBooleanField(event, AwtAWTEvent::consumedID); 5780 DASSERT(!safe_ExceptionOccurred(env)); 5781 5782 if (consumed) { 5783 keyDownConsumed = (id == java_awt_event_KeyEvent_KEY_PRESSED); 5784 env->DeleteGlobalRef(self); 5785 env->DeleteGlobalRef(event); 5786 delete nhes; 5787 return; 5788 5789 } else if (id == java_awt_event_KeyEvent_KEY_PRESSED) { 5790 // Fix for 6637607: reset consuming 5791 keyDownConsumed = FALSE; 5792 } 5793 5794 /* Consume a KEY_TYPED event if a KEY_PRESSED had been, to support 5795 * the old model. 5796 */ 5797 if ((id == java_awt_event_KeyEvent_KEY_TYPED) && keyDownConsumed) { 5798 keyDownConsumed = FALSE; 5799 env->DeleteGlobalRef(self); 5800 env->DeleteGlobalRef(event); 5801 delete nhes; 5802 return; 5803 } 5804 5805 /* Modify any event parameters, if necessary. */ 5806 if (self && pData && 5807 id >= java_awt_event_KeyEvent_KEY_FIRST && 5808 id <= java_awt_event_KeyEvent_KEY_LAST) { 5809 5810 AwtComponent* p = (AwtComponent*)pData; 5811 5812 jint keyCode = 5813 (env)->GetIntField(event, AwtKeyEvent::keyCodeID); 5814 jchar keyChar = 5815 (env)->GetCharField(event, AwtKeyEvent::keyCharID); 5816 jint modifiers = 5817 (env)->GetIntField(event, AwtInputEvent::modifiersID); 5818 5819 DASSERT(!safe_ExceptionOccurred(env)); 5820 5821 /* Check to see whether the keyCode or modifiers were changed 5822 on the keyPressed event, and tweak the following keyTyped 5823 event (if any) accodingly. */ 5824 switch (id) { 5825 case java_awt_event_KeyEvent_KEY_PRESSED: 5826 { 5827 UINT winKey = (UINT)msg.wParam; 5828 bCharChanged = FALSE; 5829 5830 if (winKey == VK_PROCESSKEY) { 5831 // Leave it up to IME 5832 break; 5833 } 5834 5835 if (keyCode != java_awt_event_KeyEvent_VK_UNDEFINED) { 5836 UINT newWinKey, ignored; 5837 p->JavaKeyToWindowsKey(keyCode, &newWinKey, &ignored, winKey); 5838 if (newWinKey != 0) { 5839 winKey = newWinKey; 5840 } 5841 } 5842 5843 BOOL isDeadKey = FALSE; 5844 modifiedChar = p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE, isDeadKey); 5845 bCharChanged = (keyChar != modifiedChar); 5846 } 5847 break; 5848 5849 case java_awt_event_KeyEvent_KEY_RELEASED: 5850 { 5851 keyDownConsumed = FALSE; 5852 bCharChanged = FALSE; 5853 } 5854 break; 5855 5856 case java_awt_event_KeyEvent_KEY_TYPED: 5857 { 5858 if (bCharChanged) 5859 { 5860 unicodeChar = modifiedChar; 5861 } 5862 else 5863 { 5864 unicodeChar = keyChar; 5865 } 5866 bCharChanged = FALSE; 5867 5868 // Disable forwarding KEY_TYPED messages to peers of 5869 // disabled components 5870 if (p->isRecursivelyEnabled()) { 5871 // send the character back to the native window for 5872 // processing. The WM_AWT_FORWARD_CHAR handler will send 5873 // this character to DefWindowProc 5874 if (!::PostMessage(p->GetHWnd(), WM_AWT_FORWARD_CHAR, 5875 MAKEWPARAM(unicodeChar, FALSE), msg.lParam)) { 5876 JNU_ThrowInternalError(env, "Message not posted, native event queue may be full."); 5877 } 5878 } 5879 env->DeleteGlobalRef(self); 5880 env->DeleteGlobalRef(event); 5881 delete nhes; 5882 return; 5883 } 5884 break; 5885 5886 default: 5887 break; 5888 } 5889 } 5890 5891 // ignore all InputMethodEvents 5892 if (self && (pData = JNI_GET_PDATA(self)) && 5893 id >= java_awt_event_InputMethodEvent_INPUT_METHOD_FIRST && 5894 id <= java_awt_event_InputMethodEvent_INPUT_METHOD_LAST) { 5895 env->DeleteGlobalRef(self); 5896 env->DeleteGlobalRef(event); 5897 delete nhes; 5898 return; 5899 } 5900 5901 // Create copy for local msg 5902 MSG* pCopiedMsg = new MSG; 5903 memmove(pCopiedMsg, &msg, sizeof(MSG)); 5904 // Event handler deletes msg 5905 p->PostHandleEventMessage(pCopiedMsg, FALSE); 5906 5907 env->DeleteGlobalRef(self); 5908 env->DeleteGlobalRef(event); 5909 delete nhes; 5910 return; 5911 } 5912 5913 /* Forward any valid synthesized events. Currently only mouse and 5914 * key events are supported. 5915 */ 5916 if (self == NULL || (pData = JNI_GET_PDATA(self)) == NULL) { 5917 env->DeleteGlobalRef(self); 5918 env->DeleteGlobalRef(event); 5919 delete nhes; 5920 return; 5921 } 5922 5923 AwtComponent* p = (AwtComponent*)pData; 5924 if (id >= java_awt_event_KeyEvent_KEY_FIRST && 5925 id <= java_awt_event_KeyEvent_KEY_LAST) { 5926 p->SynthesizeKeyMessage(env, event); 5927 } else if (id >= java_awt_event_MouseEvent_MOUSE_FIRST && 5928 id <= java_awt_event_MouseEvent_MOUSE_LAST) { 5929 p->SynthesizeMouseMessage(env, event); 5930 } 5931 } 5932 5933 ret: 5934 if (self != NULL) { 5935 env->DeleteGlobalRef(self); 5936 } 5937 if (event != NULL) { 5938 env->DeleteGlobalRef(event); 5939 } 5940 5941 delete nhes; 5942 } 5943 5944 void AwtComponent::_SetForeground(void *param) 5945 { 5946 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5947 5948 SetColorStruct *scs = (SetColorStruct *)param; 5949 jobject self = scs->component; 5950 jint rgb = scs->rgb; 5951 5952 AwtComponent *c = NULL; 5953 5954 PDATA pData; 5955 JNI_CHECK_PEER_GOTO(self, ret); 5956 c = (AwtComponent *)pData; 5957 if (::IsWindow(c->GetHWnd())) 5958 { 5959 c->SetColor(PALETTERGB((rgb>>16)&0xff, 5960 (rgb>>8)&0xff, 5961 (rgb)&0xff)); 5962 c->VerifyState(); 5963 } 5964 ret: 5965 env->DeleteGlobalRef(self); 5966 5967 delete scs; 5968 } 5969 5970 void AwtComponent::_SetBackground(void *param) 5971 { 5972 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5973 5974 SetColorStruct *scs = (SetColorStruct *)param; 5975 jobject self = scs->component; 5976 jint rgb = scs->rgb; 5977 5978 AwtComponent *c = NULL; 5979 5980 PDATA pData; 5981 JNI_CHECK_PEER_GOTO(self, ret); 5982 c = (AwtComponent *)pData; 5983 if (::IsWindow(c->GetHWnd())) 5984 { 5985 c->SetBackgroundColor(PALETTERGB((rgb>>16)&0xff, 5986 (rgb>>8)&0xff, 5987 (rgb)&0xff)); 5988 c->VerifyState(); 5989 } 5990 ret: 5991 env->DeleteGlobalRef(self); 5992 5993 delete scs; 5994 } 5995 5996 void AwtComponent::_SetFont(void *param) 5997 { 5998 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 5999 6000 SetFontStruct *sfs = (SetFontStruct *)param; 6001 jobject self = sfs->component; 6002 jobject font = sfs->font; 6003 6004 AwtComponent *c = NULL; 6005 6006 PDATA pData; 6007 JNI_CHECK_PEER_GOTO(self, ret); 6008 JNI_CHECK_NULL_GOTO(font, "null font", ret); 6009 c = (AwtComponent *)pData; 6010 if (::IsWindow(c->GetHWnd())) 6011 { 6012 AwtFont *awtFont = (AwtFont *)env->GetLongField(font, AwtFont::pDataID); 6013 if (awtFont == NULL) { 6014 /*arguments of AwtFont::Create are changed for multifont component */ 6015 awtFont = AwtFont::Create(env, font); 6016 } 6017 env->SetLongField(font, AwtFont::pDataID, (jlong)awtFont); 6018 6019 c->SetFont(awtFont); 6020 } 6021 ret: 6022 env->DeleteGlobalRef(self); 6023 env->DeleteGlobalRef(font); 6024 6025 delete sfs; 6026 } 6027 6028 // Sets or kills focus for a component. 6029 void AwtComponent::_SetFocus(void *param) 6030 { 6031 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6032 6033 SetFocusStruct *sfs = (SetFocusStruct *)param; 6034 jobject self = sfs->component; 6035 jboolean doSetFocus = sfs->doSetFocus; 6036 6037 AwtComponent *c = NULL; 6038 6039 PDATA pData; 6040 JNI_CHECK_NULL_GOTO(self, "peer", ret); 6041 pData = JNI_GET_PDATA(self); 6042 if (pData == NULL) { 6043 // do nothing just return false 6044 goto ret; 6045 } 6046 6047 c = (AwtComponent *)pData; 6048 if (::IsWindow(c->GetHWnd())) { 6049 c->SendMessage(WM_AWT_COMPONENT_SETFOCUS, (WPARAM)doSetFocus, 0); 6050 } 6051 ret: 6052 env->DeleteGlobalRef(self); 6053 6054 delete sfs; 6055 } 6056 6057 void AwtComponent::_Start(void *param) 6058 { 6059 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6060 6061 jobject self = (jobject)param; 6062 6063 AwtComponent *c = NULL; 6064 6065 PDATA pData; 6066 JNI_CHECK_PEER_GOTO(self, ret); 6067 c = (AwtComponent *)pData; 6068 if (::IsWindow(c->GetHWnd())) 6069 { 6070 jobject target = c->GetTarget(env); 6071 6072 /* Disable window if specified -- windows are enabled by default. */ 6073 jboolean enabled = (jboolean)env->GetBooleanField(target, 6074 AwtComponent::enabledID); 6075 if (!enabled) { 6076 ::EnableWindow(c->GetHWnd(), FALSE); 6077 } 6078 6079 /* The peer is now ready for callbacks, since this is the last 6080 * initialization call 6081 */ 6082 c->EnableCallbacks(TRUE); 6083 6084 // Fix 4745222: we need to invalidate region since we validated it before initialization. 6085 ::InvalidateRgn(c->GetHWnd(), NULL, FALSE); 6086 6087 // Fix 4530093: WM_PAINT after EnableCallbacks 6088 ::UpdateWindow(c->GetHWnd()); 6089 6090 env->DeleteLocalRef(target); 6091 } 6092 ret: 6093 env->DeleteGlobalRef(self); 6094 } 6095 6096 void AwtComponent::_BeginValidate(void *param) 6097 { 6098 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6099 if (AwtToolkit::IsMainThread()) { 6100 jobject self = (jobject)param; 6101 if (self != NULL) { 6102 PDATA pData = JNI_GET_PDATA(self); 6103 if (pData) { 6104 AwtComponent *c = (AwtComponent *)pData; 6105 if (::IsWindow(c->GetHWnd())) { 6106 c->SendMessage(WM_AWT_BEGIN_VALIDATE); 6107 } 6108 } 6109 env->DeleteGlobalRef(self); 6110 } 6111 } else { 6112 AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_BeginValidate, param); 6113 } 6114 } 6115 6116 void AwtComponent::_EndValidate(void *param) 6117 { 6118 if (AwtToolkit::IsMainThread()) { 6119 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6120 jobject self = (jobject)param; 6121 if (self != NULL) { 6122 PDATA pData = JNI_GET_PDATA(self); 6123 if (pData) { 6124 AwtComponent *c = (AwtComponent *)pData; 6125 if (::IsWindow(c->GetHWnd())) { 6126 c->SendMessage(WM_AWT_END_VALIDATE); 6127 } 6128 } 6129 env->DeleteGlobalRef(self); 6130 } 6131 } else { 6132 AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_EndValidate, param); 6133 } 6134 } 6135 6136 void AwtComponent::_UpdateWindow(void *param) 6137 { 6138 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6139 if (AwtToolkit::IsMainThread()) { 6140 jobject self = (jobject)param; 6141 AwtComponent *c = NULL; 6142 PDATA pData; 6143 JNI_CHECK_PEER_GOTO(self, ret); 6144 c = (AwtComponent *)pData; 6145 if (::IsWindow(c->GetHWnd())) { 6146 ::UpdateWindow(c->GetHWnd()); 6147 } 6148 ret: 6149 env->DeleteGlobalRef(self); 6150 } else { 6151 AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_UpdateWindow, param); 6152 } 6153 } 6154 6155 jlong AwtComponent::_AddNativeDropTarget(void *param) 6156 { 6157 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6158 6159 jobject self = (jobject)param; 6160 6161 jlong result = 0; 6162 AwtComponent *c = NULL; 6163 6164 PDATA pData; 6165 JNI_CHECK_PEER_GOTO(self, ret); 6166 c = (AwtComponent *)pData; 6167 if (::IsWindow(c->GetHWnd())) 6168 { 6169 result = (jlong)(c->CreateDropTarget(env)); 6170 } 6171 ret: 6172 env->DeleteGlobalRef(self); 6173 6174 return result; 6175 } 6176 6177 void AwtComponent::_RemoveNativeDropTarget(void *param) 6178 { 6179 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6180 6181 jobject self = (jobject)param; 6182 6183 AwtComponent *c = NULL; 6184 6185 PDATA pData; 6186 JNI_CHECK_PEER_GOTO(self, ret); 6187 c = (AwtComponent *)pData; 6188 if (::IsWindow(c->GetHWnd())) 6189 { 6190 c->DestroyDropTarget(); 6191 } 6192 ret: 6193 env->DeleteGlobalRef(self); 6194 } 6195 6196 jintArray AwtComponent::_CreatePrintedPixels(void *param) 6197 { 6198 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6199 6200 CreatePrintedPixelsStruct *cpps = (CreatePrintedPixelsStruct *)param; 6201 jobject self = cpps->component; 6202 6203 jintArray result = NULL; 6204 AwtComponent *c = NULL; 6205 6206 PDATA pData; 6207 JNI_CHECK_PEER_GOTO(self, ret); 6208 c = (AwtComponent *)pData; 6209 if (::IsWindow(c->GetHWnd())) 6210 { 6211 result = (jintArray)c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)cpps, 0); 6212 } 6213 ret: 6214 env->DeleteGlobalRef(self); 6215 6216 delete cpps; 6217 return result; // this reference is global 6218 } 6219 6220 jboolean AwtComponent::_IsObscured(void *param) 6221 { 6222 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6223 6224 jobject self = (jobject)param; 6225 6226 jboolean result = JNI_FALSE; 6227 AwtComponent *c = NULL; 6228 6229 PDATA pData; 6230 JNI_CHECK_PEER_GOTO(self, ret); 6231 6232 c = (AwtComponent *)pData; 6233 6234 if (::IsWindow(c->GetHWnd())) 6235 { 6236 HWND hWnd = c->GetHWnd(); 6237 HDC hDC = ::GetDC(hWnd); 6238 RECT clipbox; 6239 int callresult = ::GetClipBox(hDC, &clipbox); 6240 switch(callresult) { 6241 case NULLREGION : 6242 result = JNI_FALSE; 6243 break; 6244 case SIMPLEREGION : { 6245 RECT windowRect; 6246 if (!::GetClientRect(hWnd, &windowRect)) { 6247 result = JNI_TRUE; 6248 } else { 6249 result = (jboolean)((clipbox.bottom != windowRect.bottom) 6250 || (clipbox.left != windowRect.left) 6251 || (clipbox.right != windowRect.right) 6252 || (clipbox.top != windowRect.top)); 6253 } 6254 break; 6255 } 6256 case COMPLEXREGION : 6257 default : 6258 result = JNI_TRUE; 6259 break; 6260 } 6261 ::ReleaseDC(hWnd, hDC); 6262 } 6263 ret: 6264 env->DeleteGlobalRef(self); 6265 6266 return result; 6267 } 6268 6269 jboolean AwtComponent::_NativeHandlesWheelScrolling(void *param) 6270 { 6271 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6272 6273 jobject self = (jobject)param; 6274 6275 jboolean result = JNI_FALSE; 6276 AwtComponent *c = NULL; 6277 6278 PDATA pData; 6279 JNI_CHECK_PEER_GOTO(self, ret); 6280 c = (AwtComponent *)pData; 6281 if (::IsWindow(c->GetHWnd())) 6282 { 6283 result = JNI_IS_TRUE(c->InheritsNativeMouseWheelBehavior()); 6284 } 6285 ret: 6286 env->DeleteGlobalRef(self); 6287 6288 return result; 6289 } 6290 6291 void AwtComponent::SetParent(void * param) { 6292 if (AwtToolkit::IsMainThread()) { 6293 AwtComponent** comps = (AwtComponent**)param; 6294 if ((comps[0] != NULL) && (comps[1] != NULL)) { 6295 HWND selfWnd = comps[0]->GetHWnd(); 6296 HWND parentWnd = comps[1]->GetHWnd(); 6297 if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) { 6298 // Shouldn't trigger native focus change 6299 // (only the proxy may be the native focus owner). 6300 ::SetParent(selfWnd, parentWnd); 6301 } 6302 } 6303 delete[] comps; 6304 } else { 6305 AwtToolkit::GetInstance().InvokeFunction(AwtComponent::SetParent, param); 6306 } 6307 } 6308 6309 void AwtComponent::_SetRectangularShape(void *param) 6310 { 6311 if (!AwtToolkit::IsMainThread()) { 6312 AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetRectangularShape, param); 6313 } else { 6314 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6315 6316 SetRectangularShapeStruct *data = (SetRectangularShapeStruct *)param; 6317 jobject self = data->component; 6318 jint x1 = data->x1; 6319 jint x2 = data->x2; 6320 jint y1 = data->y1; 6321 jint y2 = data->y2; 6322 jobject region = data->region; 6323 6324 AwtComponent *c = NULL; 6325 6326 PDATA pData; 6327 JNI_CHECK_PEER_GOTO(self, ret); 6328 6329 c = (AwtComponent *)pData; 6330 if (::IsWindow(c->GetHWnd())) { 6331 HRGN hRgn = NULL; 6332 6333 // If all the params are zeros, the shape must be simply reset. 6334 // Otherwise, convert it into a region. 6335 if (region || x1 || x2 || y1 || y2) { 6336 RECT_T rects[256]; 6337 RECT_T *pRect = rects; 6338 6339 const int numrects = RegionToYXBandedRectangles(env, x1, y1, x2, y2, 6340 region, &pRect, sizeof(rects)/sizeof(rects[0])); 6341 if (!pRect) { 6342 // RegionToYXBandedRectangles doesn't use safe_Malloc(), 6343 // so throw the exception explicitly 6344 throw std::bad_alloc(); 6345 } 6346 6347 RGNDATA *pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc, 6348 sizeof(RGNDATAHEADER), sizeof(RECT_T), numrects); 6349 memcpy((BYTE*)pRgnData + sizeof(RGNDATAHEADER), pRect, sizeof(RECT_T) * numrects); 6350 if (pRect != rects) { 6351 free(pRect); 6352 } 6353 pRect = NULL; 6354 6355 RGNDATAHEADER *pRgnHdr = (RGNDATAHEADER *) pRgnData; 6356 pRgnHdr->dwSize = sizeof(RGNDATAHEADER); 6357 pRgnHdr->iType = RDH_RECTANGLES; 6358 pRgnHdr->nRgnSize = 0; 6359 pRgnHdr->rcBound.top = 0; 6360 pRgnHdr->rcBound.left = 0; 6361 pRgnHdr->rcBound.bottom = LONG(y2 - y1); 6362 pRgnHdr->rcBound.right = LONG(x2 - x1); 6363 pRgnHdr->nCount = numrects; 6364 6365 hRgn = ::ExtCreateRegion(NULL, 6366 sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, pRgnData); 6367 6368 free(pRgnData); 6369 } 6370 6371 ::SetWindowRgn(c->GetHWnd(), hRgn, TRUE); 6372 } 6373 6374 ret: 6375 env->DeleteGlobalRef(self); 6376 if (region) { 6377 env->DeleteGlobalRef(region); 6378 } 6379 6380 delete data; 6381 } 6382 } 6383 6384 void AwtComponent::_SetZOrder(void *param) { 6385 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6386 6387 SetZOrderStruct *data = (SetZOrderStruct *)param; 6388 jobject self = data->component; 6389 HWND above = HWND_TOP; 6390 if (data->above != 0) { 6391 above = reinterpret_cast<HWND>(data->above); 6392 } 6393 6394 AwtComponent *c = NULL; 6395 6396 PDATA pData; 6397 JNI_CHECK_PEER_GOTO(self, ret); 6398 6399 c = (AwtComponent *)pData; 6400 if (::IsWindow(c->GetHWnd())) { 6401 ::SetWindowPos(c->GetHWnd(), above, 0, 0, 0, 0, 6402 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS); 6403 } 6404 6405 ret: 6406 env->DeleteGlobalRef(self); 6407 6408 delete data; 6409 } 6410 6411 void AwtComponent::PostUngrabEvent() { 6412 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6413 jobject target = GetTarget(env); 6414 jobject event = JNU_NewObjectByName(env, "sun/awt/UngrabEvent", "(Ljava/awt/Component;)V", 6415 target); 6416 if (safe_ExceptionOccurred(env)) { 6417 env->ExceptionDescribe(); 6418 env->ExceptionClear(); 6419 } 6420 env->DeleteLocalRef(target); 6421 if (event != NULL) { 6422 SendEvent(event); 6423 env->DeleteLocalRef(event); 6424 } 6425 } 6426 6427 void AwtComponent::SetFocusedWindow(HWND window) 6428 { 6429 HWND old = sm_focusedWindow; 6430 sm_focusedWindow = window; 6431 6432 AwtWindow::FocusedWindowChanged(old, window); 6433 } 6434 6435 /************************************************************************ 6436 * Component native methods 6437 */ 6438 6439 extern "C" { 6440 6441 /** 6442 * This method is called from the WGL pipeline when it needs to retrieve 6443 * the HWND associated with a ComponentPeer's C++ level object. 6444 */ 6445 HWND 6446 AwtComponent_GetHWnd(JNIEnv *env, jlong pData) 6447 { 6448 AwtComponent *p = (AwtComponent *)jlong_to_ptr(pData); 6449 if (p == NULL) { 6450 return (HWND)0; 6451 } 6452 return p->GetHWnd(); 6453 } 6454 6455 static void _GetInsets(void* param) 6456 { 6457 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 6458 6459 GetInsetsStruct *gis = (GetInsetsStruct *)param; 6460 jobject self = gis->window; 6461 6462 gis->insets->left = gis->insets->top = 6463 gis->insets->right = gis->insets->bottom = 0; 6464 6465 PDATA pData; 6466 JNI_CHECK_PEER_GOTO(self, ret); 6467 AwtComponent *component = (AwtComponent *)pData; 6468 6469 component->GetInsets(gis->insets); 6470 6471 ret: 6472 env->DeleteGlobalRef(self); 6473 delete gis; 6474 } 6475 6476 /** 6477 * This method is called from the WGL pipeline when it needs to retrieve 6478 * the insets associated with a ComponentPeer's C++ level object. 6479 */ 6480 void AwtComponent_GetInsets(JNIEnv *env, jobject peer, RECT *insets) 6481 { 6482 TRY; 6483 6484 GetInsetsStruct *gis = new GetInsetsStruct; 6485 gis->window = env->NewGlobalRef(peer); 6486 gis->insets = insets; 6487 6488 AwtToolkit::GetInstance().InvokeFunction(_GetInsets, gis); 6489 // global refs and mds are deleted in _UpdateWindow 6490 6491 CATCH_BAD_ALLOC; 6492 6493 } 6494 6495 JNIEXPORT void JNICALL 6496 Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls) 6497 { 6498 TRY; 6499 jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent"); 6500 CHECK_NULL(inputEventClazz); 6501 jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I"); 6502 CHECK_NULL(getButtonDownMasksID); 6503 jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID); 6504 jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE); 6505 CHECK_NULL(tmp); 6506 jsize len = env->GetArrayLength(obj); 6507 AwtComponent::masks = SAFE_SIZE_NEW_ARRAY(jint, len); 6508 for (int i = 0; i < len; i++) { 6509 AwtComponent::masks[i] = tmp[i]; 6510 } 6511 env->ReleaseIntArrayElements(obj, tmp, 0); 6512 env->DeleteLocalRef(obj); 6513 6514 /* class ids */ 6515 jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer"); 6516 6517 DASSERT(peerCls); 6518 CHECK_NULL(peerCls); 6519 6520 /* field ids */ 6521 AwtComponent::peerID = 6522 env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;"); 6523 DASSERT(AwtComponent::peerID); 6524 CHECK_NULL(AwtComponent::peerID); 6525 6526 AwtComponent::xID = env->GetFieldID(cls, "x", "I"); 6527 DASSERT(AwtComponent::xID); 6528 CHECK_NULL(AwtComponent::xID); 6529 6530 AwtComponent::yID = env->GetFieldID(cls, "y", "I"); 6531 DASSERT(AwtComponent::yID); 6532 CHECK_NULL(AwtComponent::yID); 6533 6534 AwtComponent::heightID = env->GetFieldID(cls, "height", "I"); 6535 DASSERT(AwtComponent::heightID); 6536 CHECK_NULL(AwtComponent::heightID); 6537 6538 AwtComponent::widthID = env->GetFieldID(cls, "width", "I"); 6539 DASSERT(AwtComponent::widthID); 6540 CHECK_NULL(AwtComponent::widthID); 6541 6542 AwtComponent::visibleID = env->GetFieldID(cls, "visible", "Z"); 6543 DASSERT(AwtComponent::visibleID); 6544 CHECK_NULL(AwtComponent::visibleID); 6545 6546 AwtComponent::backgroundID = 6547 env->GetFieldID(cls, "background", "Ljava/awt/Color;"); 6548 DASSERT(AwtComponent::backgroundID); 6549 CHECK_NULL(AwtComponent::backgroundID); 6550 6551 AwtComponent::foregroundID = 6552 env->GetFieldID(cls, "foreground", "Ljava/awt/Color;"); 6553 DASSERT(AwtComponent::foregroundID); 6554 CHECK_NULL(AwtComponent::foregroundID); 6555 6556 AwtComponent::enabledID = env->GetFieldID(cls, "enabled", "Z"); 6557 DASSERT(AwtComponent::enabledID); 6558 CHECK_NULL(AwtComponent::enabledID); 6559 6560 AwtComponent::parentID = env->GetFieldID(cls, "parent", "Ljava/awt/Container;"); 6561 DASSERT(AwtComponent::parentID); 6562 CHECK_NULL(AwtComponent::parentID); 6563 6564 AwtComponent::graphicsConfigID = 6565 env->GetFieldID(cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;"); 6566 DASSERT(AwtComponent::graphicsConfigID); 6567 CHECK_NULL(AwtComponent::graphicsConfigID); 6568 6569 AwtComponent::focusableID = env->GetFieldID(cls, "focusable", "Z"); 6570 DASSERT(AwtComponent::focusableID); 6571 CHECK_NULL(AwtComponent::focusableID); 6572 6573 AwtComponent::appContextID = env->GetFieldID(cls, "appContext", 6574 "Lsun/awt/AppContext;"); 6575 DASSERT(AwtComponent::appContextID); 6576 CHECK_NULL(AwtComponent::appContextID); 6577 6578 AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig", 6579 "Lsun/awt/Win32GraphicsConfig;"); 6580 DASSERT(AwtComponent::peerGCID); 6581 CHECK_NULL(AwtComponent::peerGCID); 6582 6583 AwtComponent::hwndID = env->GetFieldID(peerCls, "hwnd", "J"); 6584 DASSERT(AwtComponent::hwndID); 6585 CHECK_NULL(AwtComponent::hwndID); 6586 6587 AwtComponent::cursorID = env->GetFieldID(cls, "cursor", "Ljava/awt/Cursor;"); 6588 DASSERT(AwtComponent::cursorID); 6589 CHECK_NULL(AwtComponent::cursorID); 6590 6591 /* method ids */ 6592 AwtComponent::getFontMID = 6593 env->GetMethodID(cls, "getFont_NoClientCode", "()Ljava/awt/Font;"); 6594 DASSERT(AwtComponent::getFontMID); 6595 CHECK_NULL(AwtComponent::getFontMID); 6596 6597 AwtComponent::getToolkitMID = 6598 env->GetMethodID(cls, "getToolkitImpl", "()Ljava/awt/Toolkit;"); 6599 DASSERT(AwtComponent::getToolkitMID); 6600 CHECK_NULL(AwtComponent::getToolkitMID); 6601 6602 AwtComponent::isEnabledMID = env->GetMethodID(cls, "isEnabledImpl", "()Z"); 6603 DASSERT(AwtComponent::isEnabledMID); 6604 CHECK_NULL(AwtComponent::isEnabledMID); 6605 6606 AwtComponent::getLocationOnScreenMID = 6607 env->GetMethodID(cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;"); 6608 DASSERT(AwtComponent::getLocationOnScreenMID); 6609 CHECK_NULL(AwtComponent::getLocationOnScreenMID); 6610 6611 AwtComponent::replaceSurfaceDataMID = 6612 env->GetMethodID(peerCls, "replaceSurfaceData", "()V"); 6613 DASSERT(AwtComponent::replaceSurfaceDataMID); 6614 CHECK_NULL(AwtComponent::replaceSurfaceDataMID); 6615 6616 AwtComponent::replaceSurfaceDataLaterMID = 6617 env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V"); 6618 DASSERT(AwtComponent::replaceSurfaceDataLaterMID); 6619 CHECK_NULL(AwtComponent::replaceSurfaceDataLaterMID); 6620 6621 AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V"); 6622 DASSERT(AwtComponent::disposeLaterMID); 6623 CHECK_NULL(AwtComponent::disposeLaterMID); 6624 6625 CATCH_BAD_ALLOC; 6626 } 6627 6628 } /* extern "C" */ 6629 6630 6631 /************************************************************************ 6632 * ComponentPeer native methods 6633 */ 6634 6635 extern "C" { 6636 6637 /* 6638 * Class: sun_awt_windows_WComponentPeer 6639 * Method: pShow 6640 * Signature: ()V 6641 */ 6642 JNIEXPORT void JNICALL 6643 Java_sun_awt_windows_WComponentPeer_pShow(JNIEnv *env, jobject self) 6644 { 6645 TRY; 6646 6647 jobject selfGlobalRef = env->NewGlobalRef(self); 6648 6649 AwtToolkit::GetInstance().SyncCall(AwtComponent::_Show, (void *)selfGlobalRef); 6650 // selfGlobalRef is deleted in _Show 6651 6652 CATCH_BAD_ALLOC; 6653 } 6654 6655 /* 6656 * Class: sun_awt_windows_WComponentPeer 6657 * Method: hide 6658 * Signature: ()V 6659 */ 6660 JNIEXPORT void JNICALL 6661 Java_sun_awt_windows_WComponentPeer_hide(JNIEnv *env, jobject self) 6662 { 6663 TRY; 6664 6665 jobject selfGlobalRef = env->NewGlobalRef(self); 6666 6667 AwtToolkit::GetInstance().SyncCall(AwtComponent::_Hide, (void *)selfGlobalRef); 6668 // selfGlobalRef is deleted in _Hide 6669 6670 CATCH_BAD_ALLOC; 6671 } 6672 6673 /* 6674 * Class: sun_awt_windows_WComponentPeer 6675 * Method: enable 6676 * Signature: ()V 6677 */ 6678 JNIEXPORT void JNICALL 6679 Java_sun_awt_windows_WComponentPeer_enable(JNIEnv *env, jobject self) 6680 { 6681 TRY; 6682 6683 jobject selfGlobalRef = env->NewGlobalRef(self); 6684 6685 AwtToolkit::GetInstance().SyncCall(AwtComponent::_Enable, (void *)selfGlobalRef); 6686 // selfGlobalRef is deleted in _Enable 6687 6688 CATCH_BAD_ALLOC; 6689 } 6690 6691 /* 6692 * Class: sun_awt_windows_WComponentPeer 6693 * Method: disable 6694 * Signature: ()V 6695 */ 6696 JNIEXPORT void JNICALL 6697 Java_sun_awt_windows_WComponentPeer_disable(JNIEnv *env, jobject self) 6698 { 6699 TRY; 6700 6701 jobject selfGlobalRef = env->NewGlobalRef(self); 6702 6703 AwtToolkit::GetInstance().SyncCall(AwtComponent::_Disable, (void *)selfGlobalRef); 6704 // selfGlobalRef is deleted in _Disable 6705 6706 CATCH_BAD_ALLOC; 6707 } 6708 6709 /* 6710 * Class: sun_awt_windows_WComponentPeer 6711 * Method: getLocationOnScreen 6712 * Signature: ()Ljava/awt/Point; 6713 */ 6714 JNIEXPORT jobject JNICALL 6715 Java_sun_awt_windows_WComponentPeer_getLocationOnScreen(JNIEnv *env, jobject self) 6716 { 6717 TRY; 6718 6719 jobject selfGlobalRef = env->NewGlobalRef(self); 6720 6721 jobject resultGlobalRef = (jobject)AwtToolkit::GetInstance().SyncCall( 6722 (void*(*)(void*))AwtComponent::_GetLocationOnScreen, (void *)selfGlobalRef); 6723 // selfGlobalRef is deleted in _GetLocationOnScreen 6724 if (resultGlobalRef != NULL) 6725 { 6726 jobject resultLocalRef = env->NewLocalRef(resultGlobalRef); 6727 env->DeleteGlobalRef(resultGlobalRef); 6728 return resultLocalRef; 6729 } 6730 6731 return NULL; 6732 6733 CATCH_BAD_ALLOC_RET(NULL); 6734 } 6735 6736 /* 6737 * Class: sun_awt_windows_WComponentPeer 6738 * Method: reshape 6739 * Signature: (IIII)V 6740 */ 6741 JNIEXPORT void JNICALL 6742 Java_sun_awt_windows_WComponentPeer_reshape(JNIEnv *env, jobject self, 6743 jint x, jint y, jint w, jint h) 6744 { 6745 TRY; 6746 6747 ReshapeStruct *rs = new ReshapeStruct; 6748 rs->component = env->NewGlobalRef(self); 6749 rs->x = x; 6750 rs->y = y; 6751 rs->w = w; 6752 rs->h = h; 6753 6754 AwtToolkit::GetInstance().SyncCall(AwtComponent::_Reshape, rs); 6755 // global ref and rs are deleted in _Reshape 6756 6757 CATCH_BAD_ALLOC; 6758 } 6759 6760 /* 6761 * Class: sun_awt_windows_WComponentPeer 6762 * Method: reshape 6763 * Signature: (IIII)V 6764 */ 6765 JNIEXPORT void JNICALL 6766 Java_sun_awt_windows_WComponentPeer_reshapeNoCheck(JNIEnv *env, jobject self, 6767 jint x, jint y, jint w, jint h) 6768 { 6769 TRY; 6770 6771 ReshapeStruct *rs = new ReshapeStruct; 6772 rs->component = env->NewGlobalRef(self); 6773 rs->x = x; 6774 rs->y = y; 6775 rs->w = w; 6776 rs->h = h; 6777 6778 AwtToolkit::GetInstance().SyncCall(AwtComponent::_ReshapeNoCheck, rs); 6779 // global ref and rs are deleted in _ReshapeNoCheck 6780 6781 CATCH_BAD_ALLOC; 6782 } 6783 6784 6785 /* 6786 * Class: sun_awt_windows_WComponentPeer 6787 * Method: nativeHandleEvent 6788 * Signature: (Ljava/awt/AWTEvent;)V 6789 */ 6790 JNIEXPORT void JNICALL 6791 Java_sun_awt_windows_WComponentPeer_nativeHandleEvent(JNIEnv *env, 6792 jobject self, 6793 jobject event) 6794 { 6795 TRY; 6796 6797 jobject selfGlobalRef = env->NewGlobalRef(self); 6798 jobject eventGlobalRef = env->NewGlobalRef(event); 6799 6800 NativeHandleEventStruct *nhes = new NativeHandleEventStruct; 6801 nhes->component = selfGlobalRef; 6802 nhes->event = eventGlobalRef; 6803 6804 AwtToolkit::GetInstance().SyncCall(AwtComponent::_NativeHandleEvent, nhes); 6805 // global refs and nhes are deleted in _NativeHandleEvent 6806 6807 CATCH_BAD_ALLOC; 6808 } 6809 6810 /* 6811 * Class: sun_awt_windows_WComponentPeer 6812 * Method: _dispose 6813 * Signature: ()V 6814 */ 6815 JNIEXPORT void JNICALL 6816 Java_sun_awt_windows_WComponentPeer__1dispose(JNIEnv *env, jobject self) 6817 { 6818 TRY_NO_HANG; 6819 6820 AwtObject::_Dispose(self); 6821 6822 CATCH_BAD_ALLOC; 6823 } 6824 6825 /* 6826 * Class: sun_awt_windows_WComponentPeer 6827 * Method: _setForeground 6828 * Signature: (I)V 6829 */ 6830 JNIEXPORT void JNICALL 6831 Java_sun_awt_windows_WComponentPeer__1setForeground(JNIEnv *env, jobject self, 6832 jint rgb) 6833 { 6834 TRY; 6835 6836 jobject selfGlobalRef = env->NewGlobalRef(self); 6837 6838 SetColorStruct *scs = new SetColorStruct; 6839 scs->component = selfGlobalRef; 6840 scs->rgb = rgb; 6841 6842 AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetForeground, scs); 6843 // selfGlobalRef and scs are deleted in _SetForeground() 6844 6845 CATCH_BAD_ALLOC; 6846 } 6847 6848 /* 6849 * Class: sun_awt_windows_WComponentPeer 6850 * Method: _setBackground 6851 * Signature: (I)V 6852 */ 6853 JNIEXPORT void JNICALL 6854 Java_sun_awt_windows_WComponentPeer__1setBackground(JNIEnv *env, jobject self, 6855 jint rgb) 6856 { 6857 TRY; 6858 6859 jobject selfGlobalRef = env->NewGlobalRef(self); 6860 6861 SetColorStruct *scs = new SetColorStruct; 6862 scs->component = selfGlobalRef; 6863 scs->rgb = rgb; 6864 6865 AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetBackground, scs); 6866 // selfGlobalRef and scs are deleted in _SetBackground() 6867 6868 CATCH_BAD_ALLOC; 6869 } 6870 6871 /* 6872 * Class: sun_awt_windows_WComponentPeer 6873 * Method: _setFont 6874 * Signature: (Ljava/awt/Font;)V 6875 */ 6876 JNIEXPORT void JNICALL 6877 Java_sun_awt_windows_WComponentPeer__1setFont(JNIEnv *env, jobject self, 6878 jobject font) 6879 { 6880 TRY; 6881 6882 jobject selfGlobalRef = env->NewGlobalRef(self); 6883 jobject fontGlobalRef = env->NewGlobalRef(font); 6884 6885 SetFontStruct *sfs = new SetFontStruct; 6886 sfs->component = selfGlobalRef; 6887 sfs->font = fontGlobalRef; 6888 6889 AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetFont, sfs); 6890 // global refs and sfs are deleted in _SetFont() 6891 6892 CATCH_BAD_ALLOC; 6893 } 6894 6895 /* 6896 * Class: sun_awt_windows_WComponentPeer 6897 * Method: focusGained 6898 * Signature: (Z) 6899 */ 6900 JNIEXPORT void JNICALL Java_sun_awt_windows_WComponentPeer_setFocus 6901 (JNIEnv *env, jobject self, jboolean doSetFocus) 6902 { 6903 TRY; 6904 6905 jobject selfGlobalRef = env->NewGlobalRef(self); 6906 6907 SetFocusStruct *sfs = new SetFocusStruct; 6908 sfs->component = selfGlobalRef; 6909 sfs->doSetFocus = doSetFocus; 6910 6911 AwtToolkit::GetInstance().SyncCall( 6912 (void*(*)(void*))AwtComponent::_SetFocus, sfs); 6913 // global refs and self are deleted in _SetFocus 6914 6915 CATCH_BAD_ALLOC; 6916 } 6917 6918 /* 6919 * Class: sun_awt_windows_WComponentPeer 6920 * Method: start 6921 * Signature: ()V 6922 */ 6923 JNIEXPORT void JNICALL 6924 Java_sun_awt_windows_WComponentPeer_start(JNIEnv *env, jobject self) 6925 { 6926 TRY; 6927 6928 jobject selfGlobalRef = env->NewGlobalRef(self); 6929 6930 AwtToolkit::GetInstance().SyncCall(AwtComponent::_Start, (void *)selfGlobalRef); 6931 // selfGlobalRef is deleted in _Start 6932 6933 CATCH_BAD_ALLOC; 6934 } 6935 6936 /* 6937 * Class: sun_awt_windows_WComponentPeer 6938 * Method: beginValidate 6939 * Signature: ()V 6940 */ 6941 JNIEXPORT void JNICALL 6942 Java_sun_awt_windows_WComponentPeer_beginValidate(JNIEnv *env, jobject self) 6943 { 6944 TRY; 6945 6946 jobject selfGlobalRef = env->NewGlobalRef(self); 6947 6948 AwtToolkit::GetInstance().SyncCall(AwtComponent::_BeginValidate, (void *)selfGlobalRef); 6949 // selfGlobalRef is deleted in _BeginValidate 6950 6951 CATCH_BAD_ALLOC; 6952 } 6953 6954 /* 6955 * Class: sun_awt_windows_WComponentPeer 6956 * Method: endValidate 6957 * Signature: ()V 6958 */ 6959 JNIEXPORT void JNICALL 6960 Java_sun_awt_windows_WComponentPeer_endValidate(JNIEnv *env, jobject self) 6961 { 6962 TRY; 6963 6964 jobject selfGlobalRef = env->NewGlobalRef(self); 6965 6966 AwtToolkit::GetInstance().SyncCall(AwtComponent::_EndValidate, (void *)selfGlobalRef); 6967 // selfGlobalRef is deleted in _EndValidate 6968 6969 CATCH_BAD_ALLOC; 6970 } 6971 6972 JNIEXPORT void JNICALL 6973 Java_sun_awt_windows_WComponentPeer_updateWindow(JNIEnv *env, jobject self) 6974 { 6975 TRY; 6976 6977 jobject selfGlobalRef = env->NewGlobalRef(self); 6978 6979 AwtToolkit::GetInstance().SyncCall(AwtComponent::_UpdateWindow, (void *)selfGlobalRef); 6980 // selfGlobalRef is deleted in _UpdateWindow 6981 6982 CATCH_BAD_ALLOC; 6983 } 6984 6985 /* 6986 * Class: sun_awt_windows_WComponentPeer 6987 * Method: addNativeDropTarget 6988 * Signature: ()L 6989 */ 6990 6991 JNIEXPORT jlong JNICALL 6992 Java_sun_awt_windows_WComponentPeer_addNativeDropTarget(JNIEnv *env, 6993 jobject self) 6994 { 6995 TRY; 6996 6997 jobject selfGlobalRef = env->NewGlobalRef(self); 6998 6999 return ptr_to_jlong(AwtToolkit::GetInstance().SyncCall( 7000 (void*(*)(void*))AwtComponent::_AddNativeDropTarget, 7001 (void *)selfGlobalRef)); 7002 // selfGlobalRef is deleted in _AddNativeDropTarget 7003 7004 CATCH_BAD_ALLOC_RET(0); 7005 } 7006 7007 /* 7008 * Class: sun_awt_windows_WComponentPeer 7009 * Method: removeNativeDropTarget 7010 * Signature: ()V 7011 */ 7012 7013 JNIEXPORT void JNICALL 7014 Java_sun_awt_windows_WComponentPeer_removeNativeDropTarget(JNIEnv *env, 7015 jobject self) 7016 { 7017 TRY; 7018 7019 jobject selfGlobalRef = env->NewGlobalRef(self); 7020 7021 AwtToolkit::GetInstance().SyncCall( 7022 AwtComponent::_RemoveNativeDropTarget, (void *)selfGlobalRef); 7023 // selfGlobalRef is deleted in _RemoveNativeDropTarget 7024 7025 CATCH_BAD_ALLOC; 7026 } 7027 7028 /* 7029 * Class: sun_awt_windows_WComponentPeer 7030 * Method: getTargetGC 7031 * Signature: ()Ljava/awt/GraphicsConfiguration; 7032 */ 7033 JNIEXPORT jobject JNICALL 7034 Java_sun_awt_windows_WComponentPeer_getTargetGC(JNIEnv* env, jobject theThis) 7035 { 7036 TRY; 7037 7038 jobject targetObj; 7039 jobject gc = 0; 7040 7041 targetObj = env->GetObjectField(theThis, AwtObject::targetID); 7042 DASSERT(targetObj); 7043 7044 gc = env->GetObjectField(targetObj, AwtComponent::graphicsConfigID); 7045 return gc; 7046 7047 CATCH_BAD_ALLOC_RET(NULL); 7048 } 7049 7050 /* 7051 * Class: sun_awt_windows_WComponentPeer 7052 * Method: createPrintedPixels 7053 * Signature: (IIIIII)I[ 7054 */ 7055 JNIEXPORT jintArray JNICALL 7056 Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env, 7057 jobject self, jint srcX, jint srcY, jint srcW, jint srcH, jint alpha) 7058 { 7059 TRY; 7060 7061 jobject selfGlobalRef = env->NewGlobalRef(self); 7062 7063 CreatePrintedPixelsStruct *cpps = new CreatePrintedPixelsStruct; 7064 cpps->component = selfGlobalRef; 7065 cpps->srcx = srcX; 7066 cpps->srcy = srcY; 7067 cpps->srcw = srcW; 7068 cpps->srch = srcH; 7069 cpps->alpha = alpha; 7070 7071 jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall( 7072 (void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps); 7073 // selfGlobalRef and cpps are deleted in _CreatePrintedPixels 7074 if (globalRef != NULL) 7075 { 7076 jintArray localRef = (jintArray)env->NewLocalRef(globalRef); 7077 env->DeleteGlobalRef(globalRef); 7078 return localRef; 7079 } 7080 else 7081 { 7082 return NULL; 7083 } 7084 7085 CATCH_BAD_ALLOC_RET(NULL); 7086 } 7087 7088 /* 7089 * Class: sun_awt_windows_WComponentPeer 7090 * Method: nativeHandlesWheelScrolling 7091 * Signature: ()Z 7092 */ 7093 JNIEXPORT jboolean JNICALL 7094 Java_sun_awt_windows_WComponentPeer_nativeHandlesWheelScrolling (JNIEnv* env, 7095 jobject self) 7096 { 7097 TRY; 7098 7099 return (jboolean)AwtToolkit::GetInstance().SyncCall( 7100 (void *(*)(void *))AwtComponent::_NativeHandlesWheelScrolling, 7101 env->NewGlobalRef(self)); 7102 // global ref is deleted in _NativeHandlesWheelScrolling 7103 7104 CATCH_BAD_ALLOC_RET(NULL); 7105 } 7106 7107 /* 7108 * Class: sun_awt_windows_WComponentPeer 7109 * Method: isObscured 7110 * Signature: ()Z 7111 */ 7112 JNIEXPORT jboolean JNICALL 7113 Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv* env, 7114 jobject self) 7115 { 7116 TRY; 7117 7118 jobject selfGlobalRef = env->NewGlobalRef(self); 7119 7120 return (jboolean)AwtToolkit::GetInstance().SyncCall( 7121 (void*(*)(void*))AwtComponent::_IsObscured, 7122 (void *)selfGlobalRef); 7123 // selfGlobalRef is deleted in _IsObscured 7124 7125 CATCH_BAD_ALLOC_RET(NULL); 7126 } 7127 7128 JNIEXPORT void JNICALL 7129 Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv* env, jobject self, jobject parent) { 7130 TRY; 7131 7132 typedef AwtComponent* PComponent; 7133 AwtComponent** comps = new PComponent[2]; 7134 AwtComponent* comp = (AwtComponent*)JNI_GET_PDATA(self); 7135 AwtComponent* parentComp = (AwtComponent*)JNI_GET_PDATA(parent); 7136 comps[0] = comp; 7137 comps[1] = parentComp; 7138 7139 AwtToolkit::GetInstance().SyncCall(AwtComponent::SetParent, comps); 7140 // comps is deleted in SetParent 7141 7142 CATCH_BAD_ALLOC; 7143 } 7144 7145 JNIEXPORT void JNICALL 7146 Java_sun_awt_windows_WComponentPeer_setRectangularShape(JNIEnv* env, jobject self, 7147 jint x1, jint y1, jint x2, jint y2, jobject region) 7148 { 7149 TRY; 7150 7151 SetRectangularShapeStruct * data = new SetRectangularShapeStruct; 7152 data->component = env->NewGlobalRef(self); 7153 data->x1 = x1; 7154 data->x2 = x2; 7155 data->y1 = y1; 7156 data->y2 = y2; 7157 if (region) { 7158 data->region = env->NewGlobalRef(region); 7159 } else { 7160 data->region = NULL; 7161 } 7162 7163 AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetRectangularShape, data); 7164 // global refs and data are deleted in _SetRectangularShape 7165 7166 CATCH_BAD_ALLOC; 7167 } 7168 7169 JNIEXPORT void JNICALL 7170 Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv* env, jobject self, jlong above) 7171 { 7172 TRY; 7173 7174 SetZOrderStruct * data = new SetZOrderStruct; 7175 data->component = env->NewGlobalRef(self); 7176 data->above = above; 7177 7178 AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetZOrder, data); 7179 // global refs and data are deleted in _SetLower 7180 7181 CATCH_BAD_ALLOC; 7182 } 7183 7184 } /* extern "C" */ 7185 7186 7187 /************************************************************************ 7188 * Diagnostic routines 7189 */ 7190 7191 #ifdef DEBUG 7192 7193 void AwtComponent::VerifyState() 7194 { 7195 if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) { 7196 return; 7197 } 7198 7199 if (m_callbacksEnabled == FALSE) { 7200 /* Component is not fully setup yet. */ 7201 return; 7202 } 7203 7204 /* Get target bounds. */ 7205 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 7206 if (env->PushLocalFrame(10) < 0) 7207 return; 7208 7209 jobject target = GetTarget(env); 7210 7211 jint x = env->GetIntField(target, AwtComponent::xID); 7212 jint y = env->GetIntField(target, AwtComponent::yID); 7213 jint width = env->GetIntField(target, AwtComponent::widthID); 7214 jint height = env->GetIntField(target, AwtComponent::heightID); 7215 7216 /* Convert target origin to absolute coordinates */ 7217 while (TRUE) { 7218 7219 jobject parent = env->GetObjectField(target, AwtComponent::parentID); 7220 if (parent == NULL) { 7221 break; 7222 } 7223 x += env->GetIntField(parent, AwtComponent::xID); 7224 y += env->GetIntField(parent, AwtComponent::yID); 7225 7226 /* If this component has insets, factor them in, but ignore 7227 * top-level windows. 7228 */ 7229 jobject parent2 = env->GetObjectField(parent, AwtComponent::parentID); 7230 if (parent2 != NULL) { 7231 jobject peer = GetPeerForTarget(env, parent); 7232 if (peer != NULL && 7233 JNU_IsInstanceOfByName(env, peer, 7234 "sun/awt/windows/WPanelPeer") > 0) { 7235 jobject insets = 7236 JNU_CallMethodByName(env, NULL, peer,"insets", 7237 "()Ljava/awt/Insets;").l; 7238 x += (env)->GetIntField(insets, AwtInsets::leftID); 7239 y += (env)->GetIntField(insets, AwtInsets::topID); 7240 } 7241 } 7242 env->DeleteLocalRef(target); 7243 target = parent; 7244 } 7245 7246 x = ScaleUpX(x); 7247 y = ScaleUpY(y); 7248 width = ScaleUpX(width); 7249 height = ScaleUpY(height); 7250 7251 // Test whether component's bounds match the native window's 7252 RECT rect; 7253 VERIFY(::GetWindowRect(GetHWnd(), &rect)); 7254 #if 0 7255 DASSERT( (x == rect.left) && 7256 (y == rect.top) && 7257 (width == (rect.right-rect.left)) && 7258 (height == (rect.bottom-rect.top)) ); 7259 #else 7260 BOOL fSizeValid = ( (x == rect.left) && 7261 (y == rect.top) && 7262 (width == (rect.right-rect.left)) && 7263 (height == (rect.bottom-rect.top)) ); 7264 #endif 7265 7266 // See if visible state matches 7267 BOOL wndVisible = ::IsWindowVisible(GetHWnd()); 7268 jboolean targetVisible; 7269 // To avoid possibly running client code on the toolkit thread, don't 7270 // do the following check if we're running on the toolkit thread. 7271 if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) { 7272 targetVisible = JNU_CallMethodByName(env, NULL, GetTarget(env), 7273 "isShowing", "()Z").z; 7274 DASSERT(!safe_ExceptionOccurred(env)); 7275 } else { 7276 targetVisible = wndVisible ? 1 : 0; 7277 } 7278 #if 0 7279 DASSERT( (targetVisible && wndVisible) || 7280 (!targetVisible && !wndVisible) ); 7281 #else 7282 BOOL fVisibleValid = ( (targetVisible && wndVisible) || 7283 (!targetVisible && !wndVisible) ); 7284 #endif 7285 7286 // Check enabled state 7287 BOOL wndEnabled = ::IsWindowEnabled(GetHWnd()); 7288 jboolean enabled = (jboolean)env->GetBooleanField(target, 7289 AwtComponent::enabledID); 7290 #if 0 7291 DASSERT( (enabled && wndEnabled) || 7292 (!enabled && !wndEnabled) ); 7293 #else 7294 BOOL fEnabledValid = ((enabled && wndEnabled) || 7295 (!(enabled && !wndEnabled) )); 7296 7297 if (!fSizeValid || !fVisibleValid || !fEnabledValid) { 7298 printf("AwtComponent::ValidateState() failed:\n"); 7299 // To avoid possibly running client code on the toolkit thread, don't 7300 // do the following call if we're running on the toolkit thread. 7301 if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) { 7302 jstring targetStr = 7303 (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env), 7304 "getName", 7305 "()Ljava/lang/String;").l; 7306 DASSERT(!safe_ExceptionOccurred(env)); 7307 LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL); 7308 printf("\t%S\n", targetStrW); 7309 JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW); 7310 } 7311 printf("\twas: [%d,%d,%dx%d]\n", x, y, width, height); 7312 if (!fSizeValid) { 7313 printf("\tshould be: [%d,%d,%dx%d]\n", rect.left, rect.top, 7314 rect.right-rect.left, rect.bottom-rect.top); 7315 } 7316 if (!fVisibleValid) { 7317 printf("\tshould be: %s\n", 7318 (targetVisible) ? "visible" : "hidden"); 7319 } 7320 if (!fEnabledValid) { 7321 printf("\tshould be: %s\n", 7322 enabled ? "enabled" : "disabled"); 7323 } 7324 } 7325 #endif 7326 env->PopLocalFrame(0); 7327 } 7328 #endif //DEBUG 7329 7330 // Methods for globally managed DC list 7331 7332 /** 7333 * Add a new DC to the DC list for this component. 7334 */ 7335 void DCList::AddDC(HDC hDC, HWND hWnd) 7336 { 7337 DCItem *newItem = new DCItem; 7338 newItem->hDC = hDC; 7339 newItem->hWnd = hWnd; 7340 AddDCItem(newItem); 7341 } 7342 7343 void DCList::AddDCItem(DCItem *newItem) 7344 { 7345 listLock.Enter(); 7346 newItem->next = head; 7347 head = newItem; 7348 listLock.Leave(); 7349 } 7350 7351 /** 7352 * Given a DC and window handle, remove the DC from the DC list 7353 * and return TRUE if it exists on the current list. Otherwise 7354 * return FALSE. 7355 * A DC may not exist on the list because it has already 7356 * been released elsewhere (for example, the window 7357 * destruction process may release a DC while a rendering 7358 * thread may also want to release a DC when it notices that 7359 * its DC is obsolete for the current window). 7360 */ 7361 DCItem *DCList::RemoveDC(HDC hDC, HWND hWnd) 7362 { 7363 listLock.Enter(); 7364 DCItem **prevPtrPtr = &head; 7365 DCItem *listPtr = head; 7366 while (listPtr) { 7367 DCItem *nextPtr = listPtr->next; 7368 if (listPtr->hDC == hDC && listPtr->hWnd == hWnd) { 7369 *prevPtrPtr = nextPtr; 7370 break; 7371 } 7372 prevPtrPtr = &listPtr->next; 7373 listPtr = nextPtr; 7374 } 7375 listLock.Leave(); 7376 return listPtr; 7377 } 7378 7379 /** 7380 * Remove all DCs from the DC list which are associated with 7381 * the same window as hWnd. Return the list of those 7382 * DC's to the caller (which will then probably want to 7383 * call ReleaseDC() for the returned DCs). 7384 */ 7385 DCItem *DCList::RemoveAllDCs(HWND hWnd) 7386 { 7387 listLock.Enter(); 7388 DCItem **prevPtrPtr = &head; 7389 DCItem *listPtr = head; 7390 DCItem *newListPtr = NULL; 7391 BOOL ret = FALSE; 7392 while (listPtr) { 7393 DCItem *nextPtr = listPtr->next; 7394 if (listPtr->hWnd == hWnd) { 7395 *prevPtrPtr = nextPtr; 7396 listPtr->next = newListPtr; 7397 newListPtr = listPtr; 7398 } else { 7399 prevPtrPtr = &listPtr->next; 7400 } 7401 listPtr = nextPtr; 7402 } 7403 listLock.Leave(); 7404 return newListPtr; 7405 } 7406 7407 7408 /** 7409 * Realize palettes of all existing HDC objects 7410 */ 7411 void DCList::RealizePalettes(int screen) 7412 { 7413 listLock.Enter(); 7414 DCItem *listPtr = head; 7415 while (listPtr) { 7416 AwtWin32GraphicsDevice::RealizePalette(listPtr->hDC, screen); 7417 listPtr = listPtr->next; 7418 } 7419 listLock.Leave(); 7420 } 7421 7422 void MoveDCToPassiveList(HDC hDC, HWND hWnd) { 7423 DCItem *removedDC; 7424 if ((removedDC = activeDCList.RemoveDC(hDC, hWnd)) != NULL) { 7425 passiveDCList.AddDCItem(removedDC); 7426 } 7427 } 7428 7429 void ReleaseDCList(HWND hwnd, DCList &list) { 7430 DCItem *removedDCs = list.RemoveAllDCs(hwnd); 7431 while (removedDCs) { 7432 DCItem *tmpDCList = removedDCs; 7433 DASSERT(::GetObjectType(tmpDCList->hDC) == OBJ_DC); 7434 int retValue = ::ReleaseDC(tmpDCList->hWnd, tmpDCList->hDC); 7435 VERIFY(retValue != 0); 7436 if (retValue != 0) { 7437 // Valid ReleaseDC call; need to decrement GDI object counter 7438 AwtGDIObject::Decrement(); 7439 } 7440 removedDCs = removedDCs->next; 7441 delete tmpDCList; 7442 } 7443 }