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