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