1 /* 2 * Copyright (c) 1996, 2011, 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_Toolkit.h" 27 #include "awt_Frame.h" 28 #include "awt_MenuBar.h" 29 #include "awt_Dialog.h" 30 #include "awt_IconCursor.h" 31 #include "awt_Win32GraphicsDevice.h" 32 #include "ComCtl32Util.h" 33 34 #include <windowsx.h> 35 36 #include <java_lang_Integer.h> 37 #include <sun_awt_EmbeddedFrame.h> 38 #include <sun_awt_windows_WEmbeddedFrame.h> 39 #include <sun_awt_windows_WEmbeddedFramePeer.h> 40 41 42 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. 43 */ 44 45 /***********************************************************************/ 46 // Struct for _SetState() method 47 struct SetStateStruct { 48 jobject frame; 49 jint state; 50 }; 51 // Struct for _SetMaximizedBounds() method 52 struct SetMaximizedBoundsStruct { 53 jobject frame; 54 jint x, y; 55 jint width, height; 56 }; 57 // Struct for _SetMenuBar() method 58 struct SetMenuBarStruct { 59 jobject frame; 60 jobject menubar; 61 }; 62 63 // Struct for _SetIMMOption() method 64 struct SetIMMOptionStruct { 65 jobject frame; 66 jstring option; 67 }; 68 // Struct for _SynthesizeWmActivate() method 69 struct SynthesizeWmActivateStruct { 70 jobject frame; 71 jboolean doActivate; 72 }; 73 // Struct for _NotifyModalBlocked() method 74 struct NotifyModalBlockedStruct { 75 jobject frame; 76 jobject peer; 77 jobject blockerPeer; 78 jboolean blocked; 79 }; 80 // Information about thread containing modal blocked embedded frames 81 struct BlockedThreadStruct { 82 int framesCount; 83 HHOOK mouseHook; 84 HHOOK modalHook; 85 }; 86 /************************************************************************ 87 * AwtFrame fields 88 */ 89 90 jfieldID AwtFrame::handleID; 91 92 jfieldID AwtFrame::undecoratedID; 93 jmethodID AwtFrame::getExtendedStateMID; 94 jmethodID AwtFrame::setExtendedStateMID; 95 96 jmethodID AwtFrame::activateEmbeddingTopLevelMID; 97 98 Hashtable AwtFrame::sm_BlockedThreads("AWTBlockedThreads"); 99 100 /************************************************************************ 101 * AwtFrame methods 102 */ 103 104 AwtFrame::AwtFrame() { 105 m_parentWnd = NULL; 106 menuBar = NULL; 107 m_isEmbedded = FALSE; 108 m_ignoreWmSize = FALSE; 109 m_isMenuDropped = FALSE; 110 m_isInputMethodWindow = FALSE; 111 m_isUndecorated = FALSE; 112 m_imeTargetComponent = NULL; 113 m_actualFocusedWindow = NULL; 114 m_iconic = FALSE; 115 m_zoomed = FALSE; 116 m_maxBoundsSet = FALSE; 117 m_forceResetZoomed = FALSE; 118 119 isInManualMoveOrSize = FALSE; 120 grabbedHitTest = 0; 121 } 122 123 AwtFrame::~AwtFrame() 124 { 125 } 126 127 void AwtFrame::Dispose() 128 { 129 AwtWindow::Dispose(); 130 } 131 132 LPCTSTR AwtFrame::GetClassName() { 133 return AWT_FRAME_WINDOW_CLASS_NAME; 134 } 135 136 /* 137 * Create a new AwtFrame object and window. 138 */ 139 AwtFrame* AwtFrame::Create(jobject self, jobject parent) 140 { 141 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 142 if (env->EnsureLocalCapacity(1) < 0) { 143 return NULL; 144 } 145 146 PDATA pData; 147 HWND hwndParent = NULL; 148 AwtFrame* frame; 149 jclass cls = NULL; 150 jclass inputMethodWindowCls = NULL; 151 jobject target = NULL; 152 153 try { 154 target = env->GetObjectField(self, AwtObject::targetID); 155 JNI_CHECK_NULL_GOTO(target, "target", done); 156 157 if (parent != NULL) { 158 JNI_CHECK_PEER_GOTO(parent, done); 159 { 160 AwtFrame* parent = (AwtFrame *)pData; 161 hwndParent = parent->GetHWnd(); 162 } 163 } 164 165 frame = new AwtFrame(); 166 167 { 168 /* 169 * A variation on Netscape's hack for embedded frames: the client 170 * area of the browser is a Java Frame for parenting purposes, but 171 * really a Windows child window 172 */ 173 cls = env->FindClass("sun/awt/EmbeddedFrame"); 174 if (cls == NULL) { 175 return NULL; 176 } 177 INT_PTR handle; 178 jboolean isEmbeddedInstance = env->IsInstanceOf(target, cls); 179 jboolean isEmbedded = FALSE; 180 181 if (isEmbeddedInstance) { 182 handle = static_cast<INT_PTR>(env->GetLongField(target, AwtFrame::handleID)); 183 if (handle != 0) { 184 isEmbedded = TRUE; 185 } 186 } 187 frame->m_isEmbedded = isEmbedded; 188 189 if (isEmbedded) { 190 hwndParent = (HWND)handle; 191 RECT rect; 192 ::GetClientRect(hwndParent, &rect); 193 //Fix for 6328675: SWT_AWT.new_Frame doesn't occupy client area under JDK6 194 frame->m_isUndecorated = true; 195 /* 196 * Fix for BugTraq ID 4337754. 197 * Initialize m_peerObject before the first call 198 * to AwtFrame::GetClassName(). 199 */ 200 frame->m_peerObject = env->NewGlobalRef(self); 201 frame->RegisterClass(); 202 DWORD exStyle = WS_EX_NOPARENTNOTIFY; 203 204 if (GetRTL()) { 205 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; 206 if (GetRTLReadingOrder()) 207 exStyle |= WS_EX_RTLREADING; 208 } 209 210 frame->m_hwnd = ::CreateWindowEx(exStyle, 211 frame->GetClassName(), TEXT(""), 212 WS_CHILD | WS_CLIPCHILDREN, 213 0, 0, 214 rect.right, rect.bottom, 215 hwndParent, NULL, 216 AwtToolkit::GetInstance().GetModuleHandle(), 217 NULL); 218 frame->LinkObjects(env, self); 219 frame->SubclassHWND(); 220 221 // Update target's dimensions to reflect this embedded window. 222 ::GetClientRect(frame->m_hwnd, &rect); 223 ::MapWindowPoints(frame->m_hwnd, hwndParent, (LPPOINT)&rect, 2); 224 225 env->SetIntField(target, AwtComponent::xID, rect.left); 226 env->SetIntField(target, AwtComponent::yID, rect.top); 227 env->SetIntField(target, AwtComponent::widthID, 228 rect.right-rect.left); 229 env->SetIntField(target, AwtComponent::heightID, 230 rect.bottom-rect.top); 231 frame->InitPeerGraphicsConfig(env, self); 232 AwtToolkit::GetInstance().RegisterEmbedderProcessId(hwndParent); 233 } else { 234 jint state = env->CallIntMethod(self, AwtFrame::getExtendedStateMID); 235 DWORD exStyle; 236 DWORD style; 237 238 // for input method windows, use minimal decorations 239 inputMethodWindowCls = env->FindClass("sun/awt/im/InputMethodWindow"); 240 if ((inputMethodWindowCls != NULL) && env->IsInstanceOf(target, inputMethodWindowCls)) { 241 //for below-the-spot composition window, use no decoration 242 if (env->GetBooleanField(target, AwtFrame::undecoratedID) == JNI_TRUE){ 243 exStyle = 0; 244 style = WS_POPUP|WS_CLIPCHILDREN; 245 frame->m_isUndecorated = TRUE; 246 } else { 247 exStyle = WS_EX_PALETTEWINDOW; 248 style = WS_CLIPCHILDREN; 249 } 250 frame->m_isInputMethodWindow = TRUE; 251 } else if (env->GetBooleanField(target, AwtFrame::undecoratedID) == JNI_TRUE) { 252 exStyle = 0; 253 style = WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN | 254 WS_MAXIMIZEBOX | WS_MINIMIZEBOX; 255 if (state & java_awt_Frame_ICONIFIED) { 256 frame->setIconic(TRUE); 257 } 258 frame->m_isUndecorated = TRUE; 259 } else { 260 exStyle = WS_EX_WINDOWEDGE; 261 style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN; 262 if (state & java_awt_Frame_ICONIFIED) { 263 frame->setIconic(TRUE); 264 } 265 } 266 267 if (GetRTL()) { 268 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; 269 if (GetRTLReadingOrder()) 270 exStyle |= WS_EX_RTLREADING; 271 } 272 273 jint x = env->GetIntField(target, AwtComponent::xID); 274 jint y = env->GetIntField(target, AwtComponent::yID); 275 jint width = env->GetIntField(target, AwtComponent::widthID); 276 jint height = env->GetIntField(target, AwtComponent::heightID); 277 278 frame->CreateHWnd(env, L"", 279 style, 280 exStyle, 281 0, 0, 0, 0, 282 hwndParent, 283 NULL, 284 ::GetSysColor(COLOR_WINDOWTEXT), 285 ::GetSysColor(COLOR_WINDOWFRAME), 286 self); 287 /* 288 * Reshape here instead of during create, so that a 289 * WM_NCCALCSIZE is sent. 290 */ 291 frame->Reshape(x, y, width, height); 292 } 293 } 294 } catch (...) { 295 env->DeleteLocalRef(target); 296 env->DeleteLocalRef(cls); 297 env->DeleteLocalRef(inputMethodWindowCls); 298 throw; 299 } 300 301 done: 302 env->DeleteLocalRef(target); 303 env->DeleteLocalRef(cls); 304 env->DeleteLocalRef(inputMethodWindowCls); 305 306 return frame; 307 } 308 309 LRESULT AwtFrame::ProxyWindowProc(UINT message, WPARAM wParam, LPARAM lParam, MsgRouting &mr) 310 { 311 LRESULT retValue = 0L; 312 313 AwtComponent *focusOwner = NULL; 314 AwtComponent *imeTargetComponent = NULL; 315 316 // IME and input language related messages need to be sent to a window 317 // which has the Java input focus 318 switch (message) { 319 case WM_IME_STARTCOMPOSITION: 320 case WM_IME_ENDCOMPOSITION: 321 case WM_IME_COMPOSITION: 322 case WM_IME_SETCONTEXT: 323 case WM_IME_NOTIFY: 324 case WM_IME_CONTROL: 325 case WM_IME_COMPOSITIONFULL: 326 case WM_IME_SELECT: 327 case WM_IME_CHAR: 328 case WM_IME_REQUEST: 329 case WM_IME_KEYDOWN: 330 case WM_IME_KEYUP: 331 case WM_INPUTLANGCHANGEREQUEST: 332 case WM_INPUTLANGCHANGE: 333 if (message == WM_IME_STARTCOMPOSITION) { 334 SetImeTargetComponent(sm_focusOwner); 335 } 336 imeTargetComponent = AwtComponent::GetComponent(GetImeTargetComponent()); 337 if (imeTargetComponent != NULL && 338 imeTargetComponent != this) // avoid recursive calls 339 { 340 retValue = imeTargetComponent->WindowProc(message, wParam, lParam); 341 mr = mrConsume; 342 } 343 if (message == WM_IME_ENDCOMPOSITION) { 344 SetImeTargetComponent(NULL); 345 } 346 break; 347 case WM_SETFOCUS: 348 if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain 349 350 if (!sm_suppressFocusAndActivation && IsEmbeddedFrame()) { 351 AwtSetActiveWindow(); 352 } 353 mr = mrConsume; 354 break; 355 case WM_KILLFOCUS: 356 if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain 357 358 if (!sm_suppressFocusAndActivation && IsEmbeddedFrame()) { 359 AwtWindow::SynthesizeWmActivate(FALSE, GetHWnd(), NULL); 360 361 } else if (sm_restoreFocusAndActivation) { 362 if (AwtComponent::GetFocusedWindow() != NULL) { 363 AwtWindow *focusedWindow = (AwtWindow*)GetComponent(AwtComponent::GetFocusedWindow()); 364 if (focusedWindow != NULL) { 365 // Will just silently restore native focus & activation. 366 focusedWindow->AwtSetActiveWindow(); 367 } 368 } 369 } 370 mr = mrConsume; 371 break; 372 case 0x0127: // WM_CHANGEUISTATE 373 case 0x0128: // WM_UPDATEUISTATE 374 mr = mrConsume; 375 break; 376 } 377 378 return retValue; 379 } 380 381 LRESULT AwtFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 382 { 383 MsgRouting mr = mrDoDefault; 384 LRESULT retValue = 0L; 385 386 retValue = ProxyWindowProc(message, wParam, lParam, mr); 387 388 if (mr != mrConsume) { 389 retValue = AwtWindow::WindowProc(message, wParam, lParam); 390 } 391 return retValue; 392 } 393 394 MsgRouting AwtFrame::WmShowWindow(BOOL show, UINT status) 395 { 396 /* 397 * Fix for 6492970. 398 * When a non-focusable toplevel is shown alone the Java process 399 * is not foreground. If one shows another (focusable) toplevel 400 * the native platform not always makes it foreground (see the CR). 401 * Even worse, sometimes it sends the newly shown toplevel WM_ACTIVATE 402 * message. This breaks Java focus. To workaround the problem we 403 * set the toplevel being shown foreground programmatically. 404 * The fix is localized to non-foreground process case only. 405 * (See also: 6599270) 406 */ 407 if (!IsEmbeddedFrame() && show == TRUE && status == 0) { 408 HWND fgHWnd = ::GetForegroundWindow(); 409 if (fgHWnd != NULL) { 410 DWORD fgProcessID; 411 ::GetWindowThreadProcessId(fgHWnd, &fgProcessID); 412 413 if (fgProcessID != ::GetCurrentProcessId()) { 414 AwtWindow* window = (AwtWindow*)GetComponent(GetHWnd()); 415 416 if (window != NULL && window->IsFocusableWindow() && window->IsAutoRequestFocus() && 417 !::IsWindow(GetModalBlocker(GetHWnd()))) 418 { 419 // When the Java process is not allowed to set the foreground window 420 // (see MSDN) the request below will just have no effect. 421 ::SetForegroundWindow(GetHWnd()); 422 } 423 } 424 } 425 } 426 return AwtWindow::WmShowWindow(show, status); 427 } 428 429 MsgRouting AwtFrame::WmMouseUp(UINT flags, int x, int y, int button) { 430 if (isInManualMoveOrSize) { 431 isInManualMoveOrSize = FALSE; 432 ::ReleaseCapture(); 433 return mrConsume; 434 } 435 return AwtWindow::WmMouseUp(flags, x, y, button); 436 } 437 438 MsgRouting AwtFrame::WmMouseMove(UINT flags, int x, int y) { 439 /** 440 * If this Frame is non-focusable then we should implement move and size operation for it by 441 * ourselfves because we don't dispatch appropriate mouse messages to default window procedure. 442 */ 443 if (!IsFocusableWindow() && isInManualMoveOrSize) { 444 DWORD curPos = ::GetMessagePos(); 445 x = GET_X_LPARAM(curPos); 446 y = GET_Y_LPARAM(curPos); 447 RECT r; 448 ::GetWindowRect(GetHWnd(), &r); 449 POINT mouseLoc = {x, y}; 450 mouseLoc.x -= savedMousePos.x; 451 mouseLoc.y -= savedMousePos.y; 452 savedMousePos.x = x; 453 savedMousePos.y = y; 454 if (grabbedHitTest == HTCAPTION) { 455 ::SetWindowPos(GetHWnd(), NULL, r.left+mouseLoc.x, r.top+mouseLoc.y, 456 r.right-r.left, r.bottom-r.top, 457 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); 458 } else { 459 switch (grabbedHitTest) { 460 case HTTOP: 461 r.top += mouseLoc.y; 462 break; 463 case HTBOTTOM: 464 r.bottom += mouseLoc.y; 465 break; 466 case HTRIGHT: 467 r.right += mouseLoc.x; 468 break; 469 case HTLEFT: 470 r.left += mouseLoc.x; 471 break; 472 case HTTOPLEFT: 473 r.left += mouseLoc.x; 474 r.top += mouseLoc.y; 475 break; 476 case HTTOPRIGHT: 477 r.top += mouseLoc.y; 478 r.right += mouseLoc.x; 479 break; 480 case HTBOTTOMLEFT: 481 r.left += mouseLoc.x; 482 r.bottom += mouseLoc.y; 483 break; 484 case HTBOTTOMRIGHT: 485 case HTSIZE: 486 r.right += mouseLoc.x; 487 r.bottom += mouseLoc.y; 488 break; 489 } 490 491 ::SetWindowPos(GetHWnd(), NULL, r.left, r.top, 492 r.right-r.left, r.bottom-r.top, 493 SWP_NOACTIVATE | SWP_NOZORDER | 494 SWP_NOCOPYBITS | SWP_DEFERERASE); 495 } 496 return mrConsume; 497 } else { 498 return AwtWindow::WmMouseMove(flags, x, y); 499 } 500 } 501 502 MsgRouting AwtFrame::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) { 503 if (!IsFocusableWindow() && (button & LEFT_BUTTON)) { 504 /* 505 * Fix for 6399659. 506 * The native system shouldn't activate the next window in z-order 507 * when minimizing non-focusable window. 508 */ 509 if (hitTest == HTMINBUTTON) { 510 ::ShowWindow(GetHWnd(), SW_SHOWMINNOACTIVE); 511 return mrConsume; 512 } 513 /** 514 * If this Frame is non-focusable then we should implement move and size operation for it by 515 * ourselfves because we don't dispatch appropriate mouse messages to default window procedure. 516 */ 517 if ((button & DBL_CLICK) && hitTest == HTCAPTION) { 518 // Double click on caption - maximize or restore Frame. 519 if (IsResizable()) { 520 if (::IsZoomed(GetHWnd())) { 521 ::ShowWindow(GetHWnd(), SW_SHOWNOACTIVATE); 522 } else { 523 ::ShowWindow(GetHWnd(), SW_MAXIMIZE); 524 } 525 } 526 return mrConsume; 527 } 528 switch (hitTest) { 529 case HTMAXBUTTON: 530 if (IsResizable()) { 531 if (::IsZoomed(GetHWnd())) { 532 ::ShowWindow(GetHWnd(), SW_SHOWNOACTIVATE); 533 } else { 534 ::ShowWindow(GetHWnd(), SW_MAXIMIZE); 535 } 536 } 537 return mrConsume; 538 default: 539 return mrDoDefault; 540 } 541 } 542 return AwtWindow::WmNcMouseUp(hitTest, x, y, button); 543 } 544 545 MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) { 546 // By Swing request, click on the Frame's decorations (even on 547 // grabbed Frame) should generate UngrabEvent 548 if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) { 549 m_grabbedWindow->Ungrab(); 550 } 551 if (!IsFocusableWindow() && (button & LEFT_BUTTON)) { 552 switch (hitTest) { 553 case HTTOP: 554 case HTBOTTOM: 555 case HTLEFT: 556 case HTRIGHT: 557 case HTTOPLEFT: 558 case HTTOPRIGHT: 559 case HTBOTTOMLEFT: 560 case HTBOTTOMRIGHT: 561 case HTSIZE: 562 // Zoomed or non-resizable unfocusable frames should not be resizable. 563 if (isZoomed() || !IsResizable()) { 564 return mrConsume; 565 } 566 case HTCAPTION: 567 // We are going to perform default mouse action on non-client area of this window 568 // Grab mouse for this purpose and store coordinates for motion vector calculation 569 savedMousePos.x = x; 570 savedMousePos.y = y; 571 ::SetCapture(GetHWnd()); 572 isInManualMoveOrSize = TRUE; 573 grabbedHitTest = hitTest; 574 return mrConsume; 575 default: 576 return mrDoDefault; 577 } 578 } 579 return AwtWindow::WmNcMouseDown(hitTest, x, y, button); 580 } 581 582 // Override AwtWindow::Reshape() to handle minimized/maximized 583 // frames (see 6525850, 4065534) 584 void AwtFrame::Reshape(int x, int y, int width, int height) 585 { 586 if (isIconic()) { 587 // normal AwtComponent::Reshape will not work for iconified windows so... 588 WINDOWPLACEMENT wp; 589 POINT ptMinPosition = {x,y}; 590 POINT ptMaxPosition = {0,0}; 591 RECT rcNormalPosition = {x,y,x+width,y+height}; 592 RECT rcWorkspace; 593 HWND hWndDesktop = GetDesktopWindow(); 594 HWND hWndSelf = GetHWnd(); 595 596 // SetWindowPlacement takes workspace coordinates, but 597 // if taskbar is at top of screen, workspace coords != 598 // screen coords, so offset by workspace origin 599 VERIFY(::SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&rcWorkspace, 0)); 600 ::OffsetRect(&rcNormalPosition, -rcWorkspace.left, -rcWorkspace.top); 601 602 // set the window size for when it is not-iconified 603 wp.length = sizeof(wp); 604 wp.flags = WPF_SETMINPOSITION; 605 wp.showCmd = IsVisible() ? SW_SHOWMINIMIZED : SW_HIDE; 606 wp.ptMinPosition = ptMinPosition; 607 wp.ptMaxPosition = ptMaxPosition; 608 wp.rcNormalPosition = rcNormalPosition; 609 610 // If the call is not guarded with ignoreWmSize, 611 // a regression for bug 4851435 appears. 612 // Having this call guarded also prevents 613 // changing the iconified state of the frame 614 // while calling the Frame.setBounds() method. 615 m_ignoreWmSize = TRUE; 616 ::SetWindowPlacement(hWndSelf, &wp); 617 m_ignoreWmSize = FALSE; 618 619 return; 620 } 621 622 if (isZoomed()) { 623 // setting size of maximized window, we remove the 624 // maximized state bit (matches Motif behaviour) 625 // (calling ShowWindow(SW_RESTORE) would fire an 626 // activation event which we don't want) 627 LONG style = GetStyle(); 628 DASSERT(style & WS_MAXIMIZE); 629 style ^= WS_MAXIMIZE; 630 SetStyle(style); 631 } 632 633 AwtWindow::Reshape(x, y, width, height); 634 } 635 636 637 /* Show the frame in it's current state */ 638 void 639 AwtFrame::Show() 640 { 641 m_visible = true; 642 HWND hwnd = GetHWnd(); 643 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 644 645 DTRACE_PRINTLN3("AwtFrame::Show:%s%s%s", 646 m_iconic ? " iconic" : "", 647 m_zoomed ? " zoomed" : "", 648 m_iconic || m_zoomed ? "" : " normal"); 649 650 BOOL locationByPlatform = env->GetBooleanField(GetTarget(env), AwtWindow::locationByPlatformID); 651 652 if (locationByPlatform) { 653 moveToDefaultLocation(); 654 } 655 EnableTranslucency(TRUE); 656 657 BOOL autoRequestFocus = IsAutoRequestFocus(); 658 659 if (m_iconic) { 660 if (m_zoomed) { 661 // This whole function could probably be rewritten to use 662 // ::SetWindowPlacement but MS docs doesn't tell if 663 // ::SetWindowPlacement is a proper superset of 664 // ::ShowWindow. So let's be conservative and only use it 665 // here, where we really do need it. 666 DTRACE_PRINTLN("AwtFrame::Show(SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED"); 667 WINDOWPLACEMENT wp; 668 ::ZeroMemory(&wp, sizeof(WINDOWPLACEMENT)); 669 wp.length = sizeof(WINDOWPLACEMENT); 670 ::GetWindowPlacement(hwnd, &wp); 671 if (!IsFocusableWindow() || !autoRequestFocus) { 672 wp.showCmd = SW_SHOWMINNOACTIVE; 673 } else { 674 wp.showCmd = SW_SHOWMINIMIZED; 675 } 676 wp.flags |= WPF_RESTORETOMAXIMIZED; 677 ::SetWindowPlacement(hwnd, &wp); 678 } 679 else { 680 DTRACE_PRINTLN("AwtFrame::Show(SW_SHOWMINIMIZED)"); 681 if (!IsFocusableWindow() || !autoRequestFocus) { 682 ::ShowWindow(hwnd, SW_SHOWMINNOACTIVE); 683 } else { 684 ::ShowWindow(hwnd, SW_SHOWMINIMIZED); 685 } 686 } 687 } 688 else if (m_zoomed) { 689 DTRACE_PRINTLN("AwtFrame::Show(SW_SHOWMAXIMIZED)"); 690 if (!autoRequestFocus) { 691 692 m_filterFocusAndActivation = TRUE; 693 ::ShowWindow(hwnd, SW_MAXIMIZE); 694 m_filterFocusAndActivation = FALSE; 695 696 } else if (!IsFocusableWindow()) { 697 ::ShowWindow(hwnd, SW_MAXIMIZE); 698 } else { 699 ::ShowWindow(hwnd, SW_SHOWMAXIMIZED); 700 } 701 } 702 else if (m_isInputMethodWindow) { 703 // Don't activate input methow window 704 DTRACE_PRINTLN("AwtFrame::Show(SW_SHOWNA)"); 705 ::ShowWindow(hwnd, SW_SHOWNA); 706 707 // After the input method window shown, we have to adjust the 708 // IME candidate window position. Here is why. 709 // Usually, when IMM opens the candidate window, it sends WM_IME_NOTIFY w/ 710 // IMN_OPENCANDIDATE message to the awt component window. The 711 // awt component makes a Java call to acquire the text position 712 // in order to show the candidate window just below the input method window. 713 // However, by the time it acquires the position, the input method window 714 // hasn't been displayed yet, the position returned is just below 715 // the composed text and when the input method window is shown, it 716 // will hide part of the candidate list. To fix this, we have to 717 // adjust the candidate window position after the input method window 718 // is shown. See bug 5012944. 719 AdjustCandidateWindowPos(); 720 } 721 else { 722 // Nor iconic, nor zoomed (handled above) - so use SW_RESTORE 723 // to show in "normal" state regardless of whatever stale 724 // state might the invisible window still has. 725 DTRACE_PRINTLN("AwtFrame::Show(SW_RESTORE)"); 726 if (!IsFocusableWindow() || !autoRequestFocus) { 727 ::ShowWindow(hwnd, SW_SHOWNOACTIVATE); 728 } else { 729 ::ShowWindow(hwnd, SW_RESTORE); 730 } 731 } 732 } 733 734 void 735 AwtFrame::SendWindowStateEvent(int oldState, int newState) 736 { 737 SendWindowEvent(java_awt_event_WindowEvent_WINDOW_STATE_CHANGED, 738 NULL, oldState, newState); 739 } 740 741 void 742 AwtFrame::ClearMaximizedBounds() 743 { 744 m_maxBoundsSet = FALSE; 745 } 746 747 void AwtFrame::AdjustCandidateWindowPos() 748 { 749 // This method should only be called if the current frame 750 // is the input method window frame. 751 if (!m_isInputMethodWindow) { 752 return; 753 } 754 755 RECT inputWinRec, focusWinRec; 756 AwtComponent *comp = AwtComponent::GetComponent(AwtComponent::sm_focusOwner); 757 if (comp == NULL) { 758 return; 759 } 760 761 ::GetWindowRect(GetHWnd(), &inputWinRec); 762 ::GetWindowRect(sm_focusOwner, &focusWinRec); 763 764 LPARAM candType = comp->GetCandidateType(); 765 HWND defaultIMEWnd = ::ImmGetDefaultIMEWnd(GetHWnd()); 766 if (defaultIMEWnd == NULL) { 767 return; 768 } 769 UINT bits = 1; 770 // adjusts the candidate window position 771 for (int iCandType = 0; iCandType < 32; iCandType++, bits<<=1) { 772 if (candType & bits) { 773 CANDIDATEFORM cf; 774 cf.dwIndex = iCandType; 775 cf.dwStyle = CFS_CANDIDATEPOS; 776 // Since the coordinates are relative to the containing window, 777 // we have to calculate the coordinates as below. 778 cf.ptCurrentPos.x = inputWinRec.left - focusWinRec.left; 779 cf.ptCurrentPos.y = inputWinRec.bottom - focusWinRec.top; 780 781 // sends IMC_SETCANDIDATEPOS to IMM to move the candidate window. 782 ::SendMessage(defaultIMEWnd, WM_IME_CONTROL, IMC_SETCANDIDATEPOS, (LPARAM)&cf); 783 } 784 } 785 } 786 787 void 788 AwtFrame::SetMaximizedBounds(int x, int y, int w, int h) 789 { 790 m_maxPos.x = x; 791 m_maxPos.y = y; 792 m_maxSize.x = w; 793 m_maxSize.y = h; 794 m_maxBoundsSet = TRUE; 795 } 796 797 MsgRouting AwtFrame::WmGetMinMaxInfo(LPMINMAXINFO lpmmi) 798 { 799 //Firstly call AwtWindow's function 800 MsgRouting r = AwtWindow::WmGetMinMaxInfo(lpmmi); 801 802 //Then replace maxPos & maxSize if necessary 803 if (!m_maxBoundsSet) { 804 return r; 805 } 806 807 if (m_maxPos.x != java_lang_Integer_MAX_VALUE) 808 lpmmi->ptMaxPosition.x = m_maxPos.x; 809 if (m_maxPos.y != java_lang_Integer_MAX_VALUE) 810 lpmmi->ptMaxPosition.y = m_maxPos.y; 811 if (m_maxSize.x != java_lang_Integer_MAX_VALUE) 812 lpmmi->ptMaxSize.x = m_maxSize.x; 813 if (m_maxSize.y != java_lang_Integer_MAX_VALUE) 814 lpmmi->ptMaxSize.y = m_maxSize.y; 815 return mrConsume; 816 } 817 818 MsgRouting AwtFrame::WmSize(UINT type, int w, int h) 819 { 820 currentWmSizeState = type; 821 if (currentWmSizeState == SIZE_MINIMIZED) { 822 UpdateSecurityWarningVisibility(); 823 } 824 825 if (m_ignoreWmSize) { 826 return mrDoDefault; 827 } 828 829 DTRACE_PRINTLN6("AwtFrame::WmSize: %dx%d,%s visible, state%s%s%s", 830 w, h, 831 ::IsWindowVisible(GetHWnd()) ? "" : " not", 832 m_iconic ? " iconic" : "", 833 m_zoomed ? " zoomed" : "", 834 m_iconic || m_zoomed ? "" : " normal"); 835 836 BOOL iconify = type == SIZE_MINIMIZED; 837 838 // Note that zoom may be set to TRUE in several cases: 839 // 1. type == SIZE_MAXIMIZED means that either the user or 840 // the developer (via setExtendedState(MAXIMIZED_BOTH) 841 // maximizes the frame. 842 // 2. type == SIZE_MINIMIZED && isZoomed() means that a maximized 843 // frame is to be minimized. If the user minimizes a maximized 844 // frame, we need to keep the zoomed property TRUE. However, 845 // if the developer calls setExtendedState(ICONIFIED), i.e. 846 // w/o combining the ICONIFIED state with the MAXIMIZED state, 847 // we MUST RESET the zoomed property. 848 // The flag m_forceResetZoomed identifies the latter case. 849 BOOL zoom = 850 ( 851 type == SIZE_MAXIMIZED 852 || 853 (type == SIZE_MINIMIZED && isZoomed()) 854 ) 855 && !m_forceResetZoomed; 856 857 // Set the new state and send appropriate Java event 858 jint oldState = java_awt_Frame_NORMAL; 859 if (isIconic()) { 860 oldState |= java_awt_Frame_ICONIFIED; 861 } 862 if (isZoomed()) { 863 oldState |= java_awt_Frame_MAXIMIZED_BOTH; 864 } 865 866 jint newState = java_awt_Frame_NORMAL; 867 if (iconify) { 868 newState |= java_awt_Frame_ICONIFIED; 869 } 870 if (zoom) { 871 newState |= java_awt_Frame_MAXIMIZED_BOTH; 872 } 873 874 setIconic(iconify); 875 setZoomed(zoom); 876 877 jint changed = oldState ^ newState; 878 if (changed != 0) { 879 DTRACE_PRINTLN2("AwtFrame::WmSize: reporting state change %x -> %x", 880 oldState, newState); 881 882 // sync target with peer 883 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 884 env->CallVoidMethod(GetPeer(env), AwtFrame::setExtendedStateMID, newState); 885 886 // report (de)iconification to old clients 887 if (changed & java_awt_Frame_ICONIFIED) { 888 if (newState & java_awt_Frame_ICONIFIED) { 889 SendWindowEvent(java_awt_event_WindowEvent_WINDOW_ICONIFIED); 890 } else { 891 SendWindowEvent(java_awt_event_WindowEvent_WINDOW_DEICONIFIED); 892 } 893 } 894 895 // New (since 1.4) state change event 896 SendWindowStateEvent(oldState, newState); 897 } 898 899 // If window is in iconic state, do not send COMPONENT_RESIZED event 900 if (isIconic()) { 901 return mrDoDefault; 902 } 903 904 return AwtWindow::WmSize(type, w, h); 905 } 906 907 MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) 908 { 909 jint type; 910 911 if (nState != WA_INACTIVE) { 912 if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd())) || 913 CheckActivateActualFocusedWindow(opposite)) 914 { 915 return mrConsume; 916 } 917 type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; 918 AwtComponent::SetFocusedWindow(GetHWnd()); 919 920 } else { 921 if (!::IsWindow(AwtWindow::GetModalBlocker(opposite))) { 922 // If deactivation happens because of press on grabbing 923 // window - this is nonsense, since grabbing window is 924 // assumed to have focus and watch for deactivation. But 925 // this can happen - if grabbing window is proxied Window, 926 // with Frame keeping real focus for it. 927 if (m_grabbedWindow != NULL) { 928 if (m_grabbedWindow->GetHWnd() == opposite) { 929 // Do nothing 930 } else { 931 // Normally, we would rather check that this == 932 // grabbed window, and focus is leaving it - 933 // ungrab. But since we know about proxied 934 // windows, we simply assume this is one of the 935 // known cases. 936 if (!m_grabbedWindow->IsOneOfOwnersOf((AwtWindow*)AwtComponent::GetComponent(opposite))) { 937 m_grabbedWindow->Ungrab(); 938 } 939 } 940 } 941 CheckRetainActualFocusedWindow(opposite); 942 943 type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; 944 AwtComponent::SetFocusedWindow(NULL); 945 sm_focusOwner = NULL; 946 } 947 } 948 949 SendWindowEvent(type, opposite); 950 return mrConsume; 951 } 952 953 BOOL AwtFrame::CheckActivateActualFocusedWindow(HWND deactivatedOpositeHWnd) 954 { 955 if (m_actualFocusedWindow != NULL) { 956 HWND hwnd = m_actualFocusedWindow->GetHWnd(); 957 if (hwnd != NULL && ::IsWindowVisible(hwnd)) { 958 SynthesizeWmActivate(TRUE, hwnd, deactivatedOpositeHWnd); 959 return TRUE; 960 } 961 m_actualFocusedWindow = NULL; 962 } 963 return FALSE; 964 } 965 966 void AwtFrame::CheckRetainActualFocusedWindow(HWND activatedOpositeHWnd) 967 { 968 // If actual focused window is not this Frame 969 if (AwtComponent::GetFocusedWindow() != GetHWnd()) { 970 // Make sure the actual focused window is an owned window of this frame 971 AwtWindow *focusedWindow = (AwtWindow *)AwtComponent::GetComponent(AwtComponent::GetFocusedWindow()); 972 if (focusedWindow != NULL && focusedWindow->GetOwningFrameOrDialog() == this) { 973 974 // Check that the opposite window is not this frame, nor an owned window of this frame 975 if (activatedOpositeHWnd != NULL) { 976 AwtWindow *oppositeWindow = (AwtWindow *)AwtComponent::GetComponent(activatedOpositeHWnd); 977 if (oppositeWindow && oppositeWindow != this && 978 oppositeWindow->GetOwningFrameOrDialog() != this) 979 { 980 m_actualFocusedWindow = focusedWindow; 981 } 982 } else { 983 m_actualFocusedWindow = focusedWindow; 984 } 985 } 986 } 987 } 988 989 BOOL AwtFrame::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest) 990 { 991 if (hittest == HTCLIENT) { 992 // Don't let the actualFocusedWindow to steal focus if: 993 // a) the frame is clicked in its client area; 994 // b) focus is requested to some of the frame's child. 995 m_actualFocusedWindow = NULL; 996 } 997 return AwtWindow::AwtSetActiveWindow(isMouseEventCause); 998 } 999 1000 MsgRouting AwtFrame::WmEnterMenuLoop(BOOL isTrackPopupMenu) 1001 { 1002 if ( !isTrackPopupMenu ) { 1003 m_isMenuDropped = TRUE; 1004 } 1005 return mrDoDefault; 1006 } 1007 1008 MsgRouting AwtFrame::WmExitMenuLoop(BOOL isTrackPopupMenu) 1009 { 1010 if ( !isTrackPopupMenu ) { 1011 m_isMenuDropped = FALSE; 1012 } 1013 return mrDoDefault; 1014 } 1015 1016 AwtMenuBar* AwtFrame::GetMenuBar() 1017 { 1018 return menuBar; 1019 } 1020 1021 void AwtFrame::SetMenuBar(AwtMenuBar* mb) 1022 { 1023 menuBar = mb; 1024 if (mb == NULL) { 1025 // Remove existing menu bar, if any. 1026 ::SetMenu(GetHWnd(), NULL); 1027 } else { 1028 if (menuBar->GetHMenu() != NULL) { 1029 ::SetMenu(GetHWnd(), menuBar->GetHMenu()); 1030 } 1031 } 1032 } 1033 1034 MsgRouting AwtFrame::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT& drawInfo) 1035 { 1036 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1037 1038 // if the item to be redrawn is the menu bar, then do it 1039 AwtMenuBar* awtMenubar = GetMenuBar(); 1040 if (drawInfo.CtlType == ODT_MENU && (awtMenubar != NULL) && 1041 (::GetMenu( GetHWnd() ) == (HMENU)drawInfo.hwndItem) ) 1042 { 1043 awtMenubar->DrawItem(drawInfo); 1044 return mrConsume; 1045 } 1046 1047 return AwtComponent::WmDrawItem(ctrlId, drawInfo); 1048 } 1049 1050 MsgRouting AwtFrame::WmMeasureItem(UINT ctrlId, MEASUREITEMSTRUCT& measureInfo) 1051 { 1052 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1053 AwtMenuBar* awtMenubar = GetMenuBar(); 1054 if ((measureInfo.CtlType == ODT_MENU) && (awtMenubar != NULL)) 1055 { 1056 // AwtMenu instance is stored in itemData. Use it to check if this 1057 // menu is the menu bar. 1058 AwtMenu * pMenu = (AwtMenu *) measureInfo.itemData; 1059 DASSERT(pMenu != NULL); 1060 if ( pMenu == awtMenubar ) 1061 { 1062 HWND hWnd = GetHWnd(); 1063 HDC hDC = ::GetDC(hWnd); 1064 DASSERT(hDC != NULL); 1065 awtMenubar->MeasureItem(hDC, measureInfo); 1066 VERIFY(::ReleaseDC(hWnd, hDC)); 1067 return mrConsume; 1068 } 1069 } 1070 1071 return AwtComponent::WmMeasureItem(ctrlId, measureInfo); 1072 } 1073 1074 MsgRouting AwtFrame::WmGetIcon(WPARAM iconType, LRESULT& retVal) 1075 { 1076 //Workaround windows bug: 1077 //when reseting from specific icon to class icon 1078 //taskbar is not updated 1079 if (iconType <= 2 /*ICON_SMALL2*/) { 1080 retVal = (LRESULT)GetEffectiveIcon(iconType); 1081 return mrConsume; 1082 } else { 1083 return mrDoDefault; 1084 } 1085 } 1086 1087 void AwtFrame::DoUpdateIcon() 1088 { 1089 //Workaround windows bug: 1090 //when reseting from specific icon to class icon 1091 //taskbar is not updated 1092 HICON hIcon = GetEffectiveIcon(ICON_BIG); 1093 HICON hIconSm = GetEffectiveIcon(ICON_SMALL); 1094 SendMessage(WM_SETICON, ICON_BIG, (LPARAM)hIcon); 1095 SendMessage(WM_SETICON, ICON_SMALL, (LPARAM)hIconSm); 1096 } 1097 1098 HICON AwtFrame::GetEffectiveIcon(int iconType) 1099 { 1100 BOOL smallIcon = ((iconType == ICON_SMALL) || (iconType == 2/*ICON_SMALL2*/)); 1101 HICON hIcon = (smallIcon) ? GetHIconSm() : GetHIcon(); 1102 if (hIcon == NULL) { 1103 hIcon = (smallIcon) ? AwtToolkit::GetInstance().GetAwtIconSm() : 1104 AwtToolkit::GetInstance().GetAwtIcon(); 1105 } 1106 return hIcon; 1107 } 1108 1109 static BOOL keepOnMinimize(jobject peer) { 1110 static BOOL checked = FALSE; 1111 static BOOL keep = FALSE; 1112 if (!checked) { 1113 keep = (JNU_GetStaticFieldByName(AwtToolkit::GetEnv(), NULL, 1114 "sun/awt/windows/WFramePeer", "keepOnMinimize", "Z").z) == JNI_TRUE; 1115 checked = TRUE; 1116 } 1117 return keep; 1118 } 1119 1120 MsgRouting AwtFrame::WmSysCommand(UINT uCmdType, int xPos, int yPos) 1121 { 1122 // ignore any WM_SYSCOMMAND if this window is blocked by modal dialog 1123 if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) { 1124 return mrConsume; 1125 } 1126 1127 if (uCmdType == (SYSCOMMAND_IMM & 0xFFF0)){ 1128 JNIEnv* env = AwtToolkit::GetEnv(); 1129 JNU_CallMethodByName(env, NULL, m_peerObject, 1130 "notifyIMMOptionChange", "()V"); 1131 DASSERT(!safe_ExceptionOccurred(env)); 1132 return mrConsume; 1133 } 1134 if ((uCmdType == SC_MINIMIZE) && keepOnMinimize(m_peerObject)) { 1135 ::ShowWindow(GetHWnd(),SW_SHOWMINIMIZED); 1136 return mrConsume; 1137 } 1138 return AwtWindow::WmSysCommand(uCmdType, xPos, yPos); 1139 } 1140 1141 LRESULT AwtFrame::WinThreadExecProc(ExecuteArgs * args) 1142 { 1143 switch( args->cmdId ) { 1144 case FRAME_SETMENUBAR: 1145 { 1146 jobject mbPeer = (jobject)args->param1; 1147 1148 // cancel any currently dropped down menus 1149 if (m_isMenuDropped) { 1150 SendMessage(WM_CANCELMODE); 1151 } 1152 1153 if (mbPeer == NULL) { 1154 // Remove existing menu bar, if any 1155 SetMenuBar(NULL); 1156 } else { 1157 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1158 AwtMenuBar* menuBar = (AwtMenuBar *)JNI_GET_PDATA(mbPeer); 1159 SetMenuBar(menuBar); 1160 } 1161 DrawMenuBar(); 1162 break; 1163 } 1164 1165 default: 1166 AwtWindow::WinThreadExecProc(args); 1167 break; 1168 } 1169 1170 return 0L; 1171 } 1172 1173 void AwtFrame::_SynthesizeWmActivate(void *param) 1174 { 1175 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1176 1177 SynthesizeWmActivateStruct *sas = (SynthesizeWmActivateStruct *)param; 1178 jobject self = sas->frame; 1179 jboolean doActivate = sas->doActivate; 1180 1181 AwtFrame *frame = NULL; 1182 1183 PDATA pData; 1184 JNI_CHECK_PEER_GOTO(self, ret); 1185 frame = (AwtFrame *)pData; 1186 1187 SynthesizeWmActivate(doActivate, frame->GetHWnd(), NULL); 1188 ret: 1189 env->DeleteGlobalRef(self); 1190 1191 delete sas; 1192 } 1193 1194 jobject AwtFrame::_GetBoundsPrivate(void *param) 1195 { 1196 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1197 1198 jobject self = (jobject)param; 1199 1200 jobject result = NULL; 1201 AwtFrame *f = NULL; 1202 1203 PDATA pData; 1204 JNI_CHECK_PEER_GOTO(self, ret); 1205 f = (AwtFrame *)pData; 1206 if (::IsWindow(f->GetHWnd())) 1207 { 1208 RECT rect; 1209 ::GetWindowRect(f->GetHWnd(), &rect); 1210 HWND parent = ::GetParent(f->GetHWnd()); 1211 if (::IsWindow(parent)) 1212 { 1213 POINT zero; 1214 zero.x = 0; 1215 zero.y = 0; 1216 ::ClientToScreen(parent, &zero); 1217 ::OffsetRect(&rect, -zero.x, -zero.y); 1218 } 1219 1220 result = JNU_NewObjectByName(env, "java/awt/Rectangle", "(IIII)V", 1221 rect.left, rect.top, rect.bottom-rect.top, rect.right-rect.left); 1222 } 1223 ret: 1224 env->DeleteGlobalRef(self); 1225 1226 if (result != NULL) 1227 { 1228 jobject resultGlobalRef = env->NewGlobalRef(result); 1229 env->DeleteLocalRef(result); 1230 return resultGlobalRef; 1231 } 1232 else 1233 { 1234 return NULL; 1235 } 1236 } 1237 1238 void AwtFrame::_SetState(void *param) 1239 { 1240 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1241 1242 SetStateStruct *sss = (SetStateStruct *)param; 1243 jobject self = sss->frame; 1244 jint state = sss->state; 1245 1246 AwtFrame *f = NULL; 1247 1248 PDATA pData; 1249 JNI_CHECK_PEER_GOTO(self, ret); 1250 f = (AwtFrame *)pData; 1251 HWND hwnd = f->GetHWnd(); 1252 if (::IsWindow(hwnd)) 1253 { 1254 DASSERT(!IsBadReadPtr(f, sizeof(AwtFrame))); 1255 1256 BOOL iconify = (state & java_awt_Frame_ICONIFIED) != 0; 1257 BOOL zoom = (state & java_awt_Frame_MAXIMIZED_BOTH) 1258 == java_awt_Frame_MAXIMIZED_BOTH; 1259 1260 DTRACE_PRINTLN4("WFramePeer.setState:%s%s ->%s%s", 1261 f->isIconic() ? " iconic" : "", 1262 f->isZoomed() ? " zoomed" : "", 1263 iconify ? " iconic" : "", 1264 zoom ? " zoomed" : ""); 1265 1266 if (::IsWindowVisible(hwnd)) { 1267 BOOL focusable = f->IsFocusableWindow(); 1268 1269 WINDOWPLACEMENT wp; 1270 ::ZeroMemory(&wp, sizeof(wp)); 1271 wp.length = sizeof(wp); 1272 ::GetWindowPlacement(hwnd, &wp); 1273 1274 // Iconify first. 1275 // If both iconify & zoom are TRUE, handle this case 1276 // with wp.flags field below. 1277 if (iconify) { 1278 wp.showCmd = focusable ? SW_MINIMIZE : SW_SHOWMINNOACTIVE; 1279 } else if (zoom) { 1280 wp.showCmd = focusable ? SW_SHOWMAXIMIZED : SW_MAXIMIZE; 1281 } else { // zoom == iconify == FALSE 1282 wp.showCmd = focusable ? SW_RESTORE : SW_SHOWNOACTIVATE; 1283 } 1284 1285 if (zoom && iconify) { 1286 wp.flags |= WPF_RESTORETOMAXIMIZED; 1287 } else { 1288 wp.flags &= ~WPF_RESTORETOMAXIMIZED; 1289 } 1290 1291 if (!zoom) { 1292 f->m_forceResetZoomed = TRUE; 1293 } 1294 1295 // The SetWindowPlacement() causes the WmSize() invocation 1296 // which, in turn, actually updates the m_iconic & m_zoomed flags 1297 // as well as sends Java event (WINDOW_STATE_CHANGED.) 1298 ::SetWindowPlacement(hwnd, &wp); 1299 1300 f->m_forceResetZoomed = FALSE; 1301 } else { 1302 DTRACE_PRINTLN(" not visible, just recording the requested state"); 1303 1304 f->setIconic(iconify); 1305 f->setZoomed(zoom); 1306 } 1307 } 1308 ret: 1309 env->DeleteGlobalRef(self); 1310 1311 delete sss; 1312 } 1313 1314 jint AwtFrame::_GetState(void *param) 1315 { 1316 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1317 1318 jobject self = (jobject)param; 1319 1320 jint result = java_awt_Frame_NORMAL; 1321 AwtFrame *f = NULL; 1322 1323 PDATA pData; 1324 JNI_CHECK_PEER_GOTO(self, ret); 1325 f = (AwtFrame *)pData; 1326 if (::IsWindow(f->GetHWnd())) 1327 { 1328 DASSERT(!::IsBadReadPtr(f, sizeof(AwtFrame))); 1329 if (f->isIconic()) { 1330 result |= java_awt_Frame_ICONIFIED; 1331 } 1332 if (f->isZoomed()) { 1333 result |= java_awt_Frame_MAXIMIZED_BOTH; 1334 } 1335 1336 DTRACE_PRINTLN2("WFramePeer.getState:%s%s", 1337 f->isIconic() ? " iconic" : "", 1338 f->isZoomed() ? " zoomed" : ""); 1339 } 1340 ret: 1341 env->DeleteGlobalRef(self); 1342 1343 return result; 1344 } 1345 1346 void AwtFrame::_SetMaximizedBounds(void *param) 1347 { 1348 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1349 1350 SetMaximizedBoundsStruct *smbs = (SetMaximizedBoundsStruct *)param; 1351 jobject self = smbs->frame; 1352 int x = smbs->x; 1353 int y = smbs->y; 1354 int width = smbs->width; 1355 int height = smbs->height; 1356 1357 AwtFrame *f = NULL; 1358 1359 PDATA pData; 1360 JNI_CHECK_PEER_GOTO(self, ret); 1361 f = (AwtFrame *)pData; 1362 if (::IsWindow(f->GetHWnd())) 1363 { 1364 DASSERT(!::IsBadReadPtr(f, sizeof(AwtFrame))); 1365 f->SetMaximizedBounds(x, y, width, height); 1366 } 1367 ret: 1368 env->DeleteGlobalRef(self); 1369 1370 delete smbs; 1371 } 1372 1373 void AwtFrame::_ClearMaximizedBounds(void *param) 1374 { 1375 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1376 1377 jobject self = (jobject)param; 1378 1379 AwtFrame *f = NULL; 1380 1381 PDATA pData; 1382 JNI_CHECK_PEER_GOTO(self, ret); 1383 f = (AwtFrame *)pData; 1384 if (::IsWindow(f->GetHWnd())) 1385 { 1386 DASSERT(!::IsBadReadPtr(f, sizeof(AwtFrame))); 1387 f->ClearMaximizedBounds(); 1388 } 1389 ret: 1390 env->DeleteGlobalRef(self); 1391 } 1392 1393 void AwtFrame::_SetMenuBar(void *param) 1394 { 1395 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1396 1397 SetMenuBarStruct *smbs = (SetMenuBarStruct *)param; 1398 jobject self = smbs->frame; 1399 jobject menubar = smbs->menubar; 1400 1401 AwtFrame *f = NULL; 1402 1403 PDATA pData; 1404 JNI_CHECK_PEER_GOTO(self, ret); 1405 f = (AwtFrame *)pData; 1406 if (::IsWindow(f->GetHWnd())) 1407 { 1408 ExecuteArgs args; 1409 args.cmdId = FRAME_SETMENUBAR; 1410 args.param1 = (LPARAM)menubar; 1411 f->WinThreadExecProc(&args); 1412 } 1413 ret: 1414 env->DeleteGlobalRef(self); 1415 env->DeleteGlobalRef(menubar); 1416 1417 delete smbs; 1418 } 1419 1420 void AwtFrame::_SetIMMOption(void *param) 1421 { 1422 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1423 1424 SetIMMOptionStruct *sios = (SetIMMOptionStruct *)param; 1425 jobject self = sios->frame; 1426 jstring option = sios->option; 1427 1428 int badAlloc = 0; 1429 LPCTSTR coption; 1430 LPCTSTR empty = TEXT("InputMethod"); 1431 AwtFrame *f = NULL; 1432 1433 PDATA pData; 1434 JNI_CHECK_PEER_GOTO(self, ret); 1435 JNI_CHECK_NULL_GOTO(option, "IMMOption argument", ret); 1436 1437 f = (AwtFrame *)pData; 1438 if (::IsWindow(f->GetHWnd())) 1439 { 1440 coption = JNU_GetStringPlatformChars(env, option, NULL); 1441 if (coption == NULL) 1442 { 1443 badAlloc = 1; 1444 } 1445 if (!badAlloc) 1446 { 1447 HMENU hSysMenu = ::GetSystemMenu(f->GetHWnd(), FALSE); 1448 ::AppendMenu(hSysMenu, MF_STRING, SYSCOMMAND_IMM, coption); 1449 1450 if (coption != empty) 1451 { 1452 JNU_ReleaseStringPlatformChars(env, option, coption); 1453 } 1454 } 1455 } 1456 ret: 1457 env->DeleteGlobalRef(self); 1458 env->DeleteGlobalRef(option); 1459 1460 delete sios; 1461 1462 if (badAlloc) 1463 { 1464 throw std::bad_alloc(); 1465 } 1466 } 1467 1468 void AwtFrame::_NotifyModalBlocked(void *param) 1469 { 1470 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 1471 1472 NotifyModalBlockedStruct *nmbs = (NotifyModalBlockedStruct *)param; 1473 jobject self = nmbs->frame; 1474 jobject peer = nmbs->peer; 1475 jobject blockerPeer = nmbs->blockerPeer; 1476 jboolean blocked = nmbs->blocked; 1477 1478 PDATA pData; 1479 1480 pData = JNI_GET_PDATA(peer); 1481 AwtFrame *f = (AwtFrame *)pData; 1482 1483 // dialog here may be NULL, for example, if the blocker is a native dialog 1484 // however, we need to install/unistall modal hooks anyway 1485 pData = JNI_GET_PDATA(blockerPeer); 1486 AwtDialog *d = (AwtDialog *)pData; 1487 1488 if ((f != NULL) && ::IsWindow(f->GetHWnd())) 1489 { 1490 // get an HWND of the toplevel window this embedded frame is within 1491 HWND fHWnd = f->GetHWnd(); 1492 while (::GetParent(fHWnd) != NULL) { 1493 fHWnd = ::GetParent(fHWnd); 1494 } 1495 // we must get a toplevel hwnd here, however due to some strange 1496 // behaviour of Java Plugin (a bug?) when running in IE at 1497 // this moment the embedded frame hasn't been placed into the 1498 // browser yet and fHWnd is not a toplevel, so we shouldn't install 1499 // the hook here 1500 if ((::GetWindowLong(fHWnd, GWL_STYLE) & WS_CHILD) == 0) { 1501 // if this toplevel is created in another thread, we should install 1502 // the modal hook into it to track window activation and mouse events 1503 DWORD fThread = ::GetWindowThreadProcessId(fHWnd, NULL); 1504 if (fThread != AwtToolkit::GetInstance().MainThread()) { 1505 // check if this thread has been already blocked 1506 BlockedThreadStruct *blockedThread = (BlockedThreadStruct *)sm_BlockedThreads.get((void *)fThread); 1507 if (blocked) { 1508 if (blockedThread == NULL) { 1509 blockedThread = new BlockedThreadStruct; 1510 blockedThread->framesCount = 1; 1511 blockedThread->modalHook = ::SetWindowsHookEx(WH_CBT, (HOOKPROC)AwtDialog::ModalFilterProc, 1512 0, fThread); 1513 blockedThread->mouseHook = ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)AwtDialog::MouseHookProc_NonTT, 1514 0, fThread); 1515 sm_BlockedThreads.put((void *)fThread, blockedThread); 1516 } else { 1517 blockedThread->framesCount++; 1518 } 1519 } else { 1520 // see the comment above: if Java Plugin behaviour when running in IE 1521 // was right, blockedThread would be always not NULL here 1522 if (blockedThread != NULL) { 1523 DASSERT(blockedThread->framesCount > 0); 1524 if ((blockedThread->framesCount) == 1) { 1525 ::UnhookWindowsHookEx(blockedThread->modalHook); 1526 ::UnhookWindowsHookEx(blockedThread->mouseHook); 1527 sm_BlockedThreads.remove((void *)fThread); 1528 delete blockedThread; 1529 } else { 1530 blockedThread->framesCount--; 1531 } 1532 } 1533 } 1534 } 1535 } 1536 } 1537 1538 env->DeleteGlobalRef(self); 1539 env->DeleteGlobalRef(peer); 1540 env->DeleteGlobalRef(blockerPeer); 1541 1542 delete nmbs; 1543 } 1544 1545 /************************************************************************ 1546 * WFramePeer native methods 1547 */ 1548 1549 extern "C" { 1550 1551 /* 1552 * Class: java_awt_Frame 1553 * Method: initIDs 1554 * Signature: ()V 1555 */ 1556 JNIEXPORT void JNICALL 1557 Java_java_awt_Frame_initIDs(JNIEnv *env, jclass cls) 1558 { 1559 TRY; 1560 1561 AwtFrame::undecoratedID = env->GetFieldID(cls,"undecorated","Z"); 1562 DASSERT(AwtFrame::undecoratedID != NULL); 1563 1564 CATCH_BAD_ALLOC; 1565 } 1566 1567 /* 1568 * Class: sun_awt_windows_WFramePeer 1569 * Method: initIDs 1570 * Signature: ()V 1571 */ 1572 JNIEXPORT void JNICALL 1573 Java_sun_awt_windows_WFramePeer_initIDs(JNIEnv *env, jclass cls) 1574 { 1575 TRY; 1576 1577 AwtFrame::setExtendedStateMID = env->GetMethodID(cls, "setExtendedState", "(I)V"); 1578 AwtFrame::getExtendedStateMID = env->GetMethodID(cls, "getExtendedState", "()I"); 1579 1580 DASSERT(AwtFrame::setExtendedStateMID); 1581 DASSERT(AwtFrame::getExtendedStateMID); 1582 1583 CATCH_BAD_ALLOC; 1584 } 1585 1586 /* 1587 * Class: sun_awt_windows_WFramePeer 1588 * Method: setState 1589 * Signature: (I)V 1590 */ 1591 JNIEXPORT void JNICALL 1592 Java_sun_awt_windows_WFramePeer_setState(JNIEnv *env, jobject self, 1593 jint state) 1594 { 1595 TRY; 1596 1597 SetStateStruct *sss = new SetStateStruct; 1598 sss->frame = env->NewGlobalRef(self); 1599 sss->state = state; 1600 1601 AwtToolkit::GetInstance().SyncCall(AwtFrame::_SetState, sss); 1602 // global ref and sss are deleted in _SetState() 1603 1604 CATCH_BAD_ALLOC; 1605 } 1606 1607 /* 1608 * Class: sun_awt_windows_WFramePeer 1609 * Method: getState 1610 * Signature: ()I 1611 */ 1612 JNIEXPORT jint JNICALL 1613 Java_sun_awt_windows_WFramePeer_getState(JNIEnv *env, jobject self) 1614 { 1615 TRY; 1616 1617 jobject selfGlobalRef = env->NewGlobalRef(self); 1618 1619 return static_cast<jint>(reinterpret_cast<INT_PTR>(AwtToolkit::GetInstance().SyncCall( 1620 (void*(*)(void*))AwtFrame::_GetState, 1621 (void *)selfGlobalRef))); 1622 // selfGlobalRef is deleted in _GetState() 1623 1624 CATCH_BAD_ALLOC_RET(java_awt_Frame_NORMAL); 1625 } 1626 1627 1628 /* 1629 * Class: sun_awt_windows_WFramePeer 1630 * Method: setMaximizedBounds 1631 * Signature: (IIII)V 1632 */ 1633 JNIEXPORT void JNICALL 1634 Java_sun_awt_windows_WFramePeer_setMaximizedBounds(JNIEnv *env, jobject self, 1635 jint x, jint y, jint width, jint height) 1636 { 1637 TRY; 1638 1639 SetMaximizedBoundsStruct *smbs = new SetMaximizedBoundsStruct; 1640 smbs->frame = env->NewGlobalRef(self); 1641 smbs->x = x; 1642 smbs->y = y; 1643 smbs->width = width; 1644 smbs->height = height; 1645 1646 AwtToolkit::GetInstance().SyncCall(AwtFrame::_SetMaximizedBounds, smbs); 1647 // global ref and smbs are deleted in _SetMaximizedBounds() 1648 1649 CATCH_BAD_ALLOC; 1650 } 1651 1652 1653 /* 1654 * Class: sun_awt_windows_WFramePeer 1655 * Method: clearMaximizedBounds 1656 * Signature: ()V 1657 */ 1658 JNIEXPORT void JNICALL 1659 Java_sun_awt_windows_WFramePeer_clearMaximizedBounds(JNIEnv *env, jobject self) 1660 { 1661 TRY; 1662 1663 jobject selfGlobalRef = env->NewGlobalRef(self); 1664 1665 AwtToolkit::GetInstance().SyncCall(AwtFrame::_ClearMaximizedBounds, 1666 (void *)selfGlobalRef); 1667 // selfGlobalRef is deleted in _ClearMaximizedBounds() 1668 1669 CATCH_BAD_ALLOC; 1670 } 1671 1672 1673 /* 1674 * Class: sun_awt_windows_WFramePeer 1675 * Method: setMenuBar0 1676 * Signature: (Lsun/awt/windows/WMenuBarPeer;)V 1677 */ 1678 JNIEXPORT void JNICALL 1679 Java_sun_awt_windows_WFramePeer_setMenuBar0(JNIEnv *env, jobject self, 1680 jobject mbPeer) 1681 { 1682 TRY; 1683 1684 SetMenuBarStruct *smbs = new SetMenuBarStruct; 1685 smbs->frame = env->NewGlobalRef(self); 1686 smbs->menubar = env->NewGlobalRef(mbPeer); 1687 1688 AwtToolkit::GetInstance().SyncCall(AwtFrame::_SetMenuBar, smbs); 1689 // global refs ans smbs are deleted in _SetMenuBar() 1690 1691 CATCH_BAD_ALLOC; 1692 } 1693 1694 /* 1695 * Class: sun_awt_windows_WFramePeer 1696 * Method: create 1697 * Signature: (Lsun/awt/windows/WComponentPeer;)V 1698 */ 1699 JNIEXPORT void JNICALL 1700 Java_sun_awt_windows_WFramePeer_createAwtFrame(JNIEnv *env, jobject self, 1701 jobject parent) 1702 { 1703 TRY; 1704 1705 AwtToolkit::CreateComponent(self, parent, 1706 (AwtToolkit::ComponentFactory) 1707 AwtFrame::Create); 1708 PDATA pData; 1709 JNI_CHECK_PEER_CREATION_RETURN(self); 1710 1711 CATCH_BAD_ALLOC; 1712 } 1713 1714 /* 1715 * Class: sun_awt_windows_WFramePeer 1716 * Method: getSysMenuHeight 1717 * Signature: ()I 1718 */ 1719 JNIEXPORT jint JNICALL 1720 Java_sun_awt_windows_WFramePeer_getSysMenuHeight(JNIEnv *env, jclass self) 1721 { 1722 TRY; 1723 1724 return ::GetSystemMetrics(SM_CYMENUSIZE); 1725 1726 CATCH_BAD_ALLOC_RET(0); 1727 } 1728 1729 /* 1730 * Class: sun_awt_windows_WFramePeer 1731 * Method: pSetIMMOption 1732 * Signature: (Ljava/lang/String;)V 1733 */ 1734 JNIEXPORT void JNICALL 1735 Java_sun_awt_windows_WFramePeer_pSetIMMOption(JNIEnv *env, jobject self, 1736 jstring option) 1737 { 1738 TRY; 1739 1740 SetIMMOptionStruct *sios = new SetIMMOptionStruct; 1741 sios->frame = env->NewGlobalRef(self); 1742 sios->option = (jstring)env->NewGlobalRef(option); 1743 1744 AwtToolkit::GetInstance().SyncCall(AwtFrame::_SetIMMOption, sios); 1745 // global refs and sios are deleted in _SetIMMOption() 1746 1747 CATCH_BAD_ALLOC; 1748 } 1749 1750 } /* extern "C" */ 1751 1752 1753 /************************************************************************ 1754 * EmbeddedFrame native methods 1755 */ 1756 1757 extern "C" { 1758 1759 /* 1760 * Class: sun_awt_EmbeddedFrame 1761 * Method: setPeer 1762 * Signature: (Ljava/awt/peer/ComponentPeer;)V 1763 */ 1764 JNIEXPORT void JNICALL 1765 Java_sun_awt_EmbeddedFrame_setPeer(JNIEnv *env, jobject self, jobject lpeer) 1766 { 1767 TRY; 1768 1769 jclass cls; 1770 jfieldID fid; 1771 1772 cls = env->GetObjectClass(self); 1773 fid = env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;"); 1774 env->SetObjectField(self, fid, lpeer); 1775 1776 CATCH_BAD_ALLOC; 1777 } 1778 1779 } /* extern "C" */ 1780 1781 1782 /************************************************************************ 1783 * WEmbeddedFrame native methods 1784 */ 1785 1786 extern "C" { 1787 1788 /* 1789 * Class: sun_awt_windows_WFramePeer 1790 * Method: initIDs 1791 * Signature: (Lsun/awt/windows/WMenuBarPeer;)V 1792 */ 1793 JNIEXPORT void JNICALL 1794 Java_sun_awt_windows_WEmbeddedFrame_initIDs(JNIEnv *env, jclass cls) 1795 { 1796 TRY; 1797 1798 AwtFrame::handleID = env->GetFieldID(cls, "handle", "J"); 1799 DASSERT(AwtFrame::handleID != NULL); 1800 1801 AwtFrame::activateEmbeddingTopLevelMID = env->GetMethodID(cls, "activateEmbeddingTopLevel", "()V"); 1802 DASSERT(AwtFrame::activateEmbeddingTopLevelMID != NULL); 1803 1804 CATCH_BAD_ALLOC; 1805 } 1806 1807 JNIEXPORT void JNICALL 1808 Java_sun_awt_windows_WEmbeddedFrame_notifyModalBlockedImpl(JNIEnv *env, 1809 jobject self, 1810 jobject peer, 1811 jobject blockerPeer, 1812 jboolean blocked) 1813 { 1814 TRY; 1815 1816 NotifyModalBlockedStruct *nmbs = new NotifyModalBlockedStruct; 1817 nmbs->frame = env->NewGlobalRef(self); 1818 nmbs->peer = env->NewGlobalRef(peer); 1819 nmbs->blockerPeer = env->NewGlobalRef(blockerPeer); 1820 nmbs->blocked = blocked; 1821 1822 AwtToolkit::GetInstance().SyncCall(AwtFrame::_NotifyModalBlocked, nmbs); 1823 // global refs and nmbs are deleted in _NotifyModalBlocked() 1824 1825 CATCH_BAD_ALLOC; 1826 } 1827 1828 } /* extern "C" */ 1829 1830 1831 /************************************************************************ 1832 * WEmbeddedFramePeer native methods 1833 */ 1834 1835 extern "C" { 1836 1837 JNIEXPORT void JNICALL 1838 Java_sun_awt_windows_WEmbeddedFramePeer_create(JNIEnv *env, jobject self, 1839 jobject parent) 1840 { 1841 TRY; 1842 1843 JNI_CHECK_NULL_RETURN(self, "peer"); 1844 AwtToolkit::CreateComponent(self, parent, 1845 (AwtToolkit::ComponentFactory) 1846 AwtFrame::Create); 1847 PDATA pData; 1848 JNI_CHECK_PEER_CREATION_RETURN(self); 1849 1850 CATCH_BAD_ALLOC; 1851 } 1852 1853 JNIEXPORT jobject JNICALL 1854 Java_sun_awt_windows_WEmbeddedFramePeer_getBoundsPrivate(JNIEnv *env, jobject self) 1855 { 1856 TRY; 1857 1858 jobject result = (jobject)AwtToolkit::GetInstance().SyncCall( 1859 (void *(*)(void *))AwtFrame::_GetBoundsPrivate, 1860 env->NewGlobalRef(self)); 1861 // global ref is deleted in _GetBoundsPrivate 1862 1863 if (result != NULL) 1864 { 1865 jobject resultLocalRef = env->NewLocalRef(result); 1866 env->DeleteGlobalRef(result); 1867 return resultLocalRef; 1868 } 1869 else 1870 { 1871 return NULL; 1872 } 1873 1874 CATCH_BAD_ALLOC_RET(NULL); 1875 } 1876 1877 JNIEXPORT void JNICALL 1878 Java_sun_awt_windows_WEmbeddedFramePeer_synthesizeWmActivate(JNIEnv *env, jobject self, jboolean doActivate) 1879 { 1880 TRY; 1881 1882 SynthesizeWmActivateStruct *sas = new SynthesizeWmActivateStruct; 1883 sas->frame = env->NewGlobalRef(self); 1884 sas->doActivate = doActivate; 1885 1886 /* 1887 * WARNING: invoking this function without synchronization by m_Sync CriticalSection. 1888 * Taking this lock results in a deadlock. 1889 */ 1890 AwtToolkit::GetInstance().InvokeFunction(AwtFrame::_SynthesizeWmActivate, sas); 1891 // global ref and sas are deleted in _SynthesizeWmActivate() 1892 1893 CATCH_BAD_ALLOC; 1894 } 1895 1896 } /* extern "C" */