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