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