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