1 /*
   2  * Copyright (c) 1996, 2010, 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_Dialog.h"
  28 #include "awt_Window.h"
  29 
  30 #include <windowsx.h>
  31 
  32 #include "java_awt_Dialog.h"
  33 
  34 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
  35  */
  36 
  37 /************************************************************************/
  38 // Struct for _SetIMMOption() method
  39 struct SetIMMOptionStruct {
  40     jobject dialog;
  41     jstring option;
  42 };
  43 /************************************************************************
  44  * AwtDialog fields
  45  */
  46 
  47 jfieldID AwtDialog::titleID;
  48 jfieldID AwtDialog::undecoratedID;
  49 
  50 #if defined(DEBUG)
  51 // counts how many nested modal dialogs are open, a sanity
  52 // check to ensure the somewhat complicated disable/enable
  53 // code is working properly
  54 int AwtModalityNestCounter = 0;
  55 #endif
  56 
  57 HHOOK AWTModalHook;
  58 HHOOK AWTMouseHook;
  59 
  60 int VisibleModalDialogsCount = 0;
  61 
  62 /************************************************************************
  63  * AwtDialog class methods
  64  */
  65 
  66 AwtDialog::AwtDialog() {
  67     m_modalWnd = NULL;
  68 }
  69 
  70 AwtDialog::~AwtDialog()
  71 {
  72 }
  73 
  74 void AwtDialog::Dispose()
  75 {
  76     if (m_modalWnd != NULL) {
  77         WmEndModal();
  78     }
  79     AwtFrame::Dispose();
  80 }
  81 
  82 LPCTSTR AwtDialog::GetClassName() {
  83   return AWT_DIALOG_WINDOW_CLASS_NAME;
  84 }
  85 
  86 void AwtDialog::FillClassInfo(WNDCLASSEX *lpwc)
  87 {
  88     AwtWindow::FillClassInfo(lpwc);
  89     //Fixed 6280303: REGRESSION: Java cup icon appears in title bar of dialogs
  90     // Dialog inherits icon from its owner dinamically
  91     lpwc->hIcon = NULL;
  92     lpwc->hIconSm = NULL;
  93 }
  94 
  95 /*
  96  * Create a new AwtDialog object and window.
  97  */
  98 AwtDialog* AwtDialog::Create(jobject peer, jobject parent)
  99 {
 100     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 101 
 102     jobject background = NULL;
 103     jobject target = NULL;
 104     AwtDialog* dialog = NULL;
 105 
 106     try {
 107         if (env->EnsureLocalCapacity(2) < 0) {
 108             return NULL;
 109         }
 110 
 111         PDATA pData;
 112         AwtWindow* awtParent = NULL;
 113         HWND hwndParent = NULL;
 114         target = env->GetObjectField(peer, AwtObject::targetID);
 115         JNI_CHECK_NULL_GOTO(target, "null target", done);
 116 
 117         if (parent != NULL) {
 118             JNI_CHECK_PEER_GOTO(parent, done);
 119             awtParent = (AwtWindow *)(JNI_GET_PDATA(parent));
 120             hwndParent = awtParent->GetHWnd();
 121         } else {
 122             // There is no way to prevent a parentless dialog from showing on
 123             //  the taskbar other than to specify an invisible parent and set
 124             //  WS_POPUP style for the dialog. Using toolkit window here. That
 125             //  will also excludes the dialog from appearing in window list while
 126             //  ALT+TAB'ing
 127             // From the other point, it may be confusing when the dialog without
 128             //  an owner is missing on the toolbar. So, do not set any fake
 129             //  parent window here.
 130 //            hwndParent = AwtToolkit::GetInstance().GetHWnd();
 131         }
 132         dialog = new AwtDialog();
 133 
 134         {
 135             int colorId = COLOR_3DFACE;
 136             DWORD style = WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN;
 137             if (hwndParent != NULL) {
 138                 style |= WS_POPUP;
 139             }
 140             style &= ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
 141             DWORD exStyle = WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME;
 142 
 143             if (GetRTL()) {
 144                 exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
 145                 if (GetRTLReadingOrder())
 146                     exStyle |= WS_EX_RTLREADING;
 147             }
 148 
 149 
 150             if (env->GetBooleanField(target, AwtDialog::undecoratedID) == JNI_TRUE) {
 151                 style = WS_POPUP | WS_CLIPCHILDREN;
 152                 exStyle = 0;
 153                 dialog->m_isUndecorated = TRUE;
 154             }
 155 
 156             jint x = env->GetIntField(target, AwtComponent::xID);
 157             jint y = env->GetIntField(target, AwtComponent::yID);
 158             jint width = env->GetIntField(target, AwtComponent::widthID);
 159             jint height = env->GetIntField(target, AwtComponent::heightID);
 160 
 161             dialog->CreateHWnd(env, L"",
 162                                style, exStyle,
 163                                x, y, width, height,
 164                                hwndParent,
 165                                NULL,
 166                                ::GetSysColor(COLOR_WINDOWTEXT),
 167                                ::GetSysColor(colorId),
 168                                peer);
 169 
 170             dialog->RecalcNonClient();
 171             dialog->UpdateSystemMenu();
 172 
 173             /*
 174              * Initialize icon as inherited from parent if it exists
 175              */
 176             if (parent != NULL) {
 177                 dialog->m_hIcon = awtParent->GetHIcon();
 178                 dialog->m_hIconSm = awtParent->GetHIconSm();
 179                 dialog->m_iconInherited = TRUE;
 180             }
 181             dialog->DoUpdateIcon();
 182 
 183 
 184             background = env->GetObjectField(target,
 185                                              AwtComponent::backgroundID);
 186             if (background == NULL) {
 187                 JNU_CallMethodByName(env, NULL,
 188                                      peer, "setDefaultColor", "()V");
 189             }
 190         }
 191     } catch (...) {
 192         env->DeleteLocalRef(background);
 193         env->DeleteLocalRef(target);
 194         throw;
 195     }
 196 
 197 done:
 198     env->DeleteLocalRef(background);
 199     env->DeleteLocalRef(target);
 200 
 201     return dialog;
 202 }
 203 
 204 MsgRouting AwtDialog::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
 205     // By the request from Swing team, click on the Dialog's title should generate Ungrab
 206     if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) {
 207         m_grabbedWindow->Ungrab();
 208     }
 209 
 210     if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
 211         // Dialog is non-maximizable
 212         if ((button & DBL_CLICK) && hitTest == HTCAPTION) {
 213             return mrConsume;
 214         }
 215     }
 216     return AwtFrame::WmNcMouseDown(hitTest, x, y, button);
 217 }
 218 
 219 LRESULT CALLBACK AwtDialog::ModalFilterProc(int code,
 220                                             WPARAM wParam, LPARAM lParam)
 221 {
 222     HWND hWnd = (HWND)wParam;
 223     HWND blocker = AwtWindow::GetModalBlocker(hWnd);
 224     if (::IsWindow(blocker) &&
 225         ((code == HCBT_ACTIVATE) ||
 226          (code == HCBT_SETFOCUS)))
 227     {
 228         // fix for 6270632: this window and all its blockers can be minimized by
 229         // "show desktop" button, so we should restore them first
 230         if (::IsIconic(hWnd)) {
 231             ::ShowWindow(hWnd, SW_RESTORE);
 232         }
 233         PopupAllDialogs(blocker, TRUE, ::GetForegroundWindow(), FALSE);
 234         // return 1 to prevent the system from allowing the operation
 235         return 1;
 236     }
 237     return CallNextHookEx(0, code, wParam, lParam);
 238 }
 239 
 240 LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode,
 241                                           WPARAM wParam, LPARAM lParam)
 242 {
 243     if (nCode >= 0)
 244     {
 245         MOUSEHOOKSTRUCT *mhs = (MOUSEHOOKSTRUCT *)lParam;
 246         HWND hWnd = mhs->hwnd;
 247         if ((wParam == WM_LBUTTONDOWN) ||
 248             (wParam == WM_MBUTTONDOWN) ||
 249             (wParam == WM_RBUTTONDOWN) ||
 250             (wParam == WM_MOUSEACTIVATE) ||
 251             (wParam == WM_MOUSEWHEEL) ||
 252             (wParam == WM_NCLBUTTONDOWN) ||
 253             (wParam == WM_NCMBUTTONDOWN) ||
 254             (wParam == WM_NCRBUTTONDOWN))
 255         {
 256             HWND blocker = AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(hWnd));
 257             if (::IsWindow(blocker)) {
 258                 BOOL onTaskbar = !(::WindowFromPoint(mhs->pt) == hWnd);
 259                 PopupAllDialogs(hWnd, FALSE, ::GetForegroundWindow(), onTaskbar);
 260                 // return a nonzero value to prevent the system from passing
 261                 // the message to the target window procedure
 262                 return 1;
 263             }
 264         }
 265     }
 266 
 267     return CallNextHookEx(0, nCode, wParam, lParam);
 268 }
 269 
 270 /*
 271  * The function goes through the heirarchy of the blocker dialogs and
 272  * popups all the dialogs. Note that the function starts from the top
 273  * blocker dialog and goes down to the dialog which is the bottom dialog.
 274  * Using another traversal may cause to the flickering issue as a bottom
 275  * dialog will cover a top dialog for some period of time.
 276  */
 277 void AwtDialog::PopupAllDialogs(HWND dialog, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar)
 278 {
 279     HWND blocker = AwtWindow::GetModalBlocker(dialog);
 280     BOOL isBlocked = ::IsWindow(blocker);
 281     if (isBlocked) {
 282         PopupAllDialogs(blocker, isModalHook, prevFGWindow, onTaskbar);
 283     }
 284     PopupOneDialog(dialog, blocker, isModalHook, prevFGWindow, onTaskbar);
 285 }
 286 
 287 /*
 288  * The function popups the dialog, it distinguishes non-blocked dialogs
 289  * and activates the dialogs (sets as foreground window). If the dialog is
 290  * blocked, then it changes the Z-order of the dialog.
 291  */
 292 void AwtDialog::PopupOneDialog(HWND dialog, HWND blocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar)
 293 {
 294     if (dialog == AwtToolkit::GetInstance().GetHWnd()) {
 295         return;
 296     }
 297 
 298     // fix for 6494032
 299     if (isModalHook && !::IsWindowVisible(dialog)) {
 300         ::ShowWindow(dialog, SW_SHOWNA);
 301     }
 302 
 303     BOOL isBlocked = ::IsWindow(blocker);
 304     UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE;
 305 
 306     if (isBlocked) {
 307         // Fix for 6829546: if blocker is a top-most window, but window isn't, then
 308         // calling ::SetWindowPos(dialog, blocker, ...) makes window top-most as well
 309         BOOL isBlockerTopmost = (::GetWindowLong(blocker, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
 310         BOOL isDialogTopmost = (::GetWindowLong(dialog, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
 311         if (!isBlockerTopmost || isDialogTopmost) {
 312             ::SetWindowPos(dialog, blocker, 0, 0, 0, 0, flags);
 313         } else {
 314             ::SetWindowPos(dialog, HWND_TOP, 0, 0, 0, 0, flags);
 315         }
 316     } else {
 317         ::SetWindowPos(dialog, HWND_TOP, 0, 0, 0, 0, flags);
 318         // no beep/flash if the mouse was clicked in the taskbar menu
 319         // or the dialog is currently inactive
 320         if (!isModalHook && !onTaskbar && (dialog == prevFGWindow)) {
 321             AnimateModalBlocker(dialog);
 322         }
 323         ::BringWindowToTop(dialog);
 324         ::SetForegroundWindow(dialog);
 325     }
 326 }
 327 
 328 void AwtDialog::AnimateModalBlocker(HWND window)
 329 {
 330     ::MessageBeep(MB_OK);
 331     // some heuristics: 3 times x 64 milliseconds
 332     AwtWindow::FlashWindowEx(window, 3, 64, FLASHW_CAPTION);
 333 }
 334 
 335 LRESULT CALLBACK AwtDialog::MouseHookProc_NonTT(int nCode,
 336                                                 WPARAM wParam, LPARAM lParam)
 337 {
 338     static HWND lastHWnd = NULL;
 339     if (nCode >= 0)
 340     {
 341         MOUSEHOOKSTRUCT *mhs = (MOUSEHOOKSTRUCT *)lParam;
 342         HWND hWnd = mhs->hwnd;
 343         HWND blocker = AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(hWnd));
 344         if (::IsWindow(blocker)) {
 345             if ((wParam == WM_MOUSEMOVE) ||
 346                 (wParam == WM_NCMOUSEMOVE))
 347             {
 348                 if (lastHWnd != hWnd) {
 349                     static HCURSOR hArrowCur = ::LoadCursor(NULL, IDC_ARROW);
 350                     ::SetCursor(hArrowCur);
 351                     lastHWnd = hWnd;
 352                 }
 353                 ::PostMessage(hWnd, WM_SETCURSOR, (WPARAM)hWnd, 0);
 354             } else if (wParam == WM_MOUSELEAVE) {
 355                 lastHWnd = NULL;
 356             }
 357 
 358             AwtDialog::MouseHookProc(nCode, wParam, lParam);
 359             return 1;
 360         }
 361     }
 362 
 363     return CallNextHookEx(0, nCode, wParam, lParam);
 364 }
 365 
 366 void AwtDialog::Show()
 367 {
 368     m_visible = true;
 369     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 370 
 371     BOOL locationByPlatform = env->GetBooleanField(GetTarget(env), AwtWindow::locationByPlatformID);
 372     if (locationByPlatform) {
 373          moveToDefaultLocation();
 374     }
 375     EnableTranslucency(TRUE);
 376     if (IsFocusableWindow() && (IsAutoRequestFocus() || IsFocusedWindowModalBlocker())) {
 377         ::ShowWindow(GetHWnd(), SW_SHOW);
 378     } else {
 379         ::ShowWindow(GetHWnd(), SW_SHOWNA);
 380     }
 381 }
 382 
 383 void AwtDialog::DoUpdateIcon()
 384 {
 385     AwtFrame::DoUpdateIcon();
 386     //Workaround windows bug:
 387     //Decorations are not updated correctly for owned dialogs
 388     //when changing dlg with icon <--> dlg without icon
 389     RECT winRect;
 390     RECT clientRect;
 391     ::GetWindowRect(GetHWnd(), &winRect);
 392     ::GetClientRect(GetHWnd(), &clientRect);
 393     ::MapWindowPoints(HWND_DESKTOP, GetHWnd(), (LPPOINT)&winRect, 2);
 394     HRGN winRgn = CreateRectRgnIndirect(&winRect);
 395     HRGN clientRgn = CreateRectRgnIndirect(&clientRect);
 396     ::CombineRgn(winRgn, winRgn, clientRgn, RGN_DIFF);
 397     ::RedrawWindow(GetHWnd(), NULL, winRgn, RDW_FRAME | RDW_INVALIDATE);
 398     ::DeleteObject(winRgn);
 399     ::DeleteObject(clientRgn);
 400 }
 401 
 402 HICON AwtDialog::GetEffectiveIcon(int iconType)
 403 {
 404     HWND hOwner = ::GetWindow(GetHWnd(), GW_OWNER);
 405     BOOL isResizable = ((GetStyle() & WS_THICKFRAME) != 0);
 406     BOOL smallIcon = ((iconType == ICON_SMALL) || (iconType == 2/*ICON_SMALL2*/));
 407     HICON hIcon = (smallIcon) ? GetHIconSm() : GetHIcon();
 408     if ((hIcon == NULL) && (isResizable || (hOwner == NULL))) {
 409         //Java cup icon is not loaded in window class for dialogs
 410         //It needs to be set explicitly for resizable dialogs
 411         //and ownerless dialogs
 412         hIcon = (smallIcon) ? AwtToolkit::GetInstance().GetAwtIconSm() :
 413             AwtToolkit::GetInstance().GetAwtIcon();
 414     } else if ((hIcon != NULL) && IsIconInherited() && !isResizable) {
 415         //Non-resizable dialogs without explicitely set icon
 416         //Should have no icon
 417         hIcon = NULL;
 418     }
 419     return hIcon;
 420 }
 421 
 422 void AwtDialog::CheckInstallModalHook() {
 423     VisibleModalDialogsCount++;
 424     if (VisibleModalDialogsCount == 1) {
 425         AWTModalHook = ::SetWindowsHookEx(WH_CBT, (HOOKPROC)ModalFilterProc,
 426                                          0, AwtToolkit::MainThread());
 427         AWTMouseHook = ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)MouseHookProc,
 428                                          0, AwtToolkit::MainThread());
 429     }
 430 }
 431 
 432 void AwtDialog::CheckUninstallModalHook() {
 433     if (VisibleModalDialogsCount == 1) {
 434         UnhookWindowsHookEx(AWTModalHook);
 435         UnhookWindowsHookEx(AWTMouseHook);
 436     }
 437     VisibleModalDialogsCount--;
 438 }
 439 
 440 void AwtDialog::ModalPerformActivation(HWND hWnd)
 441 {
 442     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 443 
 444     AwtWindow *w = (AwtWindow *)AwtComponent::GetComponent(hWnd);
 445     if ((w != NULL) && w->IsEmbeddedFrame()) {
 446         jobject target = w->GetTarget(env);
 447         env->CallVoidMethod(target, AwtFrame::activateEmbeddingTopLevelMID);
 448         env->DeleteLocalRef(target);
 449     } else {
 450         ::BringWindowToTop(hWnd);
 451         ::SetForegroundWindow(hWnd);
 452     }
 453 }
 454 
 455 void AwtDialog::ModalActivateNextWindow(HWND dialogHWnd,
 456                                         jobject dialogTarget, jobject dialogPeer)
 457 {
 458     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 459 
 460     jclass wwindowPeerCls = env->FindClass("sun/awt/windows/WWindowPeer");
 461     jmethodID getActiveWindowsMID = env->GetStaticMethodID(wwindowPeerCls,
 462                                                            "getActiveWindowHandles", "()[J");
 463     DASSERT(getActiveWindowsMID != NULL);
 464     jlongArray windows = (jlongArray)(env->CallStaticObjectMethod(wwindowPeerCls,
 465                                                                   getActiveWindowsMID));
 466     if (windows == NULL) {
 467         return;
 468     }
 469 
 470     jboolean isCopy;
 471     jlong *ws = env->GetLongArrayElements(windows, &isCopy);
 472     int windowsCount = env->GetArrayLength(windows);
 473     for (int i = windowsCount - 1; i >= 0; i--) {
 474         HWND w = (HWND)ws[i];
 475         if ((w != dialogHWnd) && ModalCanBeActivated(w)) {
 476             AwtDialog::ModalPerformActivation(w);
 477             break;
 478         }
 479     }
 480     env->ReleaseLongArrayElements(windows, ws, 0);
 481 
 482     env->DeleteLocalRef(windows);
 483 }
 484 
 485 MsgRouting AwtDialog::WmShowModal()
 486 {
 487     DASSERT(::GetCurrentThreadId() == AwtToolkit::MainThread());
 488 
 489     // fix for 6213128: release capture (got by popups, choices, etc) when
 490     // modal dialog is shown
 491     HWND capturer = ::GetCapture();
 492     if (capturer != NULL) {
 493       ::ReleaseCapture();
 494     }
 495 
 496     SendMessage(WM_AWT_COMPONENT_SHOW);
 497 
 498     CheckInstallModalHook();
 499 
 500     m_modalWnd = GetHWnd();
 501 
 502     return mrConsume;
 503 }
 504 
 505 MsgRouting AwtDialog::WmEndModal()
 506 {
 507     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 508 
 509     DASSERT( ::GetCurrentThreadId() == AwtToolkit::MainThread() );
 510     DASSERT( ::IsWindow(m_modalWnd) );
 511 
 512     m_modalWnd = NULL;
 513 
 514     CheckUninstallModalHook();
 515 
 516     HWND parentHWnd = ::GetParent(GetHWnd());
 517     jobject peer = GetPeer(env);
 518     jobject target = GetTarget(env);
 519     if (::GetForegroundWindow() == GetHWnd()) {
 520         ModalActivateNextWindow(GetHWnd(), target, peer);
 521     }
 522     // hide the dialog
 523     SendMessage(WM_AWT_COMPONENT_HIDE);
 524 
 525     env->DeleteLocalRef(target);
 526 
 527     return mrConsume;
 528 }
 529 
 530 void AwtDialog::SetResizable(BOOL isResizable)
 531 {
 532     // call superclass
 533     AwtFrame::SetResizable(isResizable);
 534 
 535     LONG    style = GetStyle();
 536     LONG    xstyle = GetStyleEx();
 537     if (isResizable || IsUndecorated()) {
 538     // remove modal frame
 539         xstyle &= ~WS_EX_DLGMODALFRAME;
 540     } else {
 541     // add modal frame
 542         xstyle |= WS_EX_DLGMODALFRAME;
 543     }
 544     // dialogs are never minimizable/maximizable, so remove those bits
 545     style &= ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
 546     SetStyle(style);
 547     SetStyleEx(xstyle);
 548     RedrawNonClient();
 549 }
 550 
 551 // Adjust system menu so that:
 552 //  Non-resizable dialogs only have Move and Close items
 553 //  Resizable dialogs have the full system menu with
 554 //     Maximize, Minimize items disabled (the items
 555 //     get disabled by the native system).
 556 // This perfectly mimics the native MS Windows behavior.
 557 // Normally, Win32 dialog system menu handling is done via
 558 // CreateDialog/DefDlgProc, but our dialogs are using DefWindowProc
 559 // so we handle the system menu ourselves
 560 void AwtDialog::UpdateSystemMenu()
 561 {
 562     HWND    hWndSelf = GetHWnd();
 563     BOOL    isResizable = IsResizable();
 564 
 565     // before restoring the default menu, check if there is an
 566     // InputMethodManager menu item already.  Note that it assumes
 567     // that the length of the InputMethodManager menu item string
 568     // should not be longer than 256 bytes.
 569     MENUITEMINFO  mii;
 570     memset(&mii, 0, sizeof(MENUITEMINFO));
 571     TCHAR         immItem[256];
 572     BOOL          hasImm;
 573     mii.cbSize = sizeof(MENUITEMINFO);
 574     mii.fMask = MIIM_TYPE;
 575     mii.cch = sizeof(immItem);
 576     mii.dwTypeData = immItem;
 577     hasImm = ::GetMenuItemInfo(GetSystemMenu(hWndSelf, FALSE),
 578                                SYSCOMMAND_IMM, FALSE, &mii);
 579 
 580     // restore the default menu
 581     ::GetSystemMenu(hWndSelf, TRUE);
 582     // now get a working copy of the menu
 583     HMENU hMenuSys = GetSystemMenu(hWndSelf, FALSE);
 584 
 585     if (!isResizable) {
 586         // remove inapplicable sizing commands
 587         ::DeleteMenu(hMenuSys, SC_MINIMIZE, MF_BYCOMMAND);
 588         ::DeleteMenu(hMenuSys, SC_RESTORE, MF_BYCOMMAND);
 589         ::DeleteMenu(hMenuSys, SC_MAXIMIZE, MF_BYCOMMAND);
 590         ::DeleteMenu(hMenuSys, SC_SIZE, MF_BYCOMMAND);
 591         // remove separator if only 3 items left (Move, Separator, and Close)
 592         if (::GetMenuItemCount(hMenuSys) == 3) {
 593             MENUITEMINFO mi;
 594             memset(&mi, 0, sizeof(MENUITEMINFO));
 595             mi.cbSize = sizeof(MENUITEMINFO);
 596             mi.fMask = MIIM_TYPE;
 597             ::GetMenuItemInfo(hMenuSys, 1, TRUE, &mi);
 598             if (mi.fType & MFT_SEPARATOR) {
 599                 ::DeleteMenu(hMenuSys, 1, MF_BYPOSITION);
 600             }
 601         }
 602     }
 603 
 604     // if there was the InputMethodManager menu item, restore it.
 605     if (hasImm) {
 606         ::AppendMenu(hMenuSys, MF_STRING, SYSCOMMAND_IMM, immItem);
 607     }
 608 }
 609 
 610 // Override WmStyleChanged to adjust system menu for sizable/non-resizable dialogs
 611 MsgRouting AwtDialog::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss)
 612 {
 613     UpdateSystemMenu();
 614     DoUpdateIcon();
 615     return mrConsume;
 616 }
 617 
 618 MsgRouting AwtDialog::WmSize(UINT type, int w, int h)
 619 {
 620     if (type == SIZE_MAXIMIZED || type == SIZE_MINIMIZED
 621             || (type == SIZE_RESTORED && !IsResizing()))
 622     {
 623         UpdateSystemMenu(); // adjust to reflect restored vs. maximized state
 624     }
 625 
 626     return AwtFrame::WmSize(type, w, h);
 627 }
 628 
 629 LRESULT AwtDialog::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
 630 {
 631     MsgRouting mr = mrDoDefault;
 632     LRESULT retValue = 0L;
 633 
 634     switch(message) {
 635         case WM_AWT_DLG_SHOWMODAL:
 636             mr = WmShowModal();
 637             break;
 638         case WM_AWT_DLG_ENDMODAL:
 639             mr = WmEndModal();
 640             break;
 641     }
 642 
 643     if (mr != mrConsume) {
 644         retValue = AwtFrame::WindowProc(message, wParam, lParam);
 645     }
 646     return retValue;
 647 }
 648 
 649 void AwtDialog::_ShowModal(void *param)
 650 {
 651     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 652 
 653     jobject self = (jobject)param;
 654 
 655     AwtDialog *d = NULL;
 656 
 657     PDATA pData;
 658     JNI_CHECK_PEER_GOTO(self, ret);
 659     d = (AwtDialog *)pData;
 660     if (::IsWindow(d->GetHWnd())) {
 661         d->SendMessage(WM_AWT_DLG_SHOWMODAL);
 662     }
 663 ret:
 664     env->DeleteGlobalRef(self);
 665 }
 666 
 667 void AwtDialog::_EndModal(void *param)
 668 {
 669     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 670 
 671     jobject self = (jobject)param;
 672 
 673     AwtDialog *d = NULL;
 674 
 675     PDATA pData;
 676     JNI_CHECK_PEER_GOTO(self, ret);
 677     d = (AwtDialog *)pData;
 678     if (::IsWindow(d->GetHWnd())) {
 679         d->SendMessage(WM_AWT_DLG_ENDMODAL);
 680     }
 681 ret:
 682     env->DeleteGlobalRef(self);
 683 }
 684 
 685 void AwtDialog::_SetIMMOption(void *param)
 686 {
 687     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 688 
 689     SetIMMOptionStruct *sios = (SetIMMOptionStruct *)param;
 690     jobject self = sios->dialog;
 691     jstring option = sios->option;
 692 
 693     int badAlloc = 0;
 694     LPCTSTR coption;
 695     LPCTSTR empty = TEXT("InputMethod");
 696     AwtDialog *d = NULL;
 697 
 698     PDATA pData;
 699     JNI_CHECK_PEER_GOTO(self, ret);
 700     JNI_CHECK_NULL_GOTO(option, "null IMMOption", ret);
 701 
 702     d = (AwtDialog *)pData;
 703     if (::IsWindow(d->GetHWnd()))
 704     {
 705         coption = JNU_GetStringPlatformChars(env, option, NULL);
 706         if (coption == NULL)
 707         {
 708             badAlloc = 1;
 709         }
 710         if (!badAlloc)
 711         {
 712             HMENU hSysMenu = ::GetSystemMenu(d->GetHWnd(), FALSE);
 713             ::AppendMenu(hSysMenu,  MF_STRING, SYSCOMMAND_IMM, coption);
 714 
 715             if (coption != empty)
 716             {
 717                 JNU_ReleaseStringPlatformChars(env, option, coption);
 718             }
 719         }
 720     }
 721 ret:
 722     env->DeleteGlobalRef(self);
 723     env->DeleteGlobalRef(option);
 724 
 725     delete sios;
 726 
 727     if (badAlloc)
 728     {
 729         throw std::bad_alloc();
 730     }
 731 }
 732 
 733 /************************************************************************
 734  * Dialog native methods
 735  */
 736 
 737 extern "C" {
 738 
 739 JNIEXPORT void JNICALL
 740 Java_java_awt_Dialog_initIDs(JNIEnv *env, jclass cls)
 741 {
 742     TRY;
 743 
 744     /* java.awt.Dialog fields and methods */
 745     AwtDialog::titleID
 746         = env->GetFieldID(cls, "title", "Ljava/lang/String;");
 747     AwtDialog::undecoratedID
 748         = env->GetFieldID(cls,"undecorated","Z");
 749 
 750     DASSERT(AwtDialog::undecoratedID != NULL);
 751     DASSERT(AwtDialog::titleID != NULL);
 752 
 753     CATCH_BAD_ALLOC;
 754 }
 755 
 756 } /* extern "C" */
 757 
 758 
 759 /************************************************************************
 760  * DialogPeer native methods
 761  */
 762 
 763 extern "C" {
 764 
 765 /*
 766  * Class:     sun_awt_windows_WDialogPeer
 767  * Method:    create
 768  * Signature: (Lsun/awt/windows/WComponentPeer;)V
 769  */
 770 JNIEXPORT void JNICALL
 771 Java_sun_awt_windows_WDialogPeer_createAwtDialog(JNIEnv *env, jobject self,
 772                                         jobject parent)
 773 {
 774     TRY;
 775 
 776     PDATA pData;
 777     AwtToolkit::CreateComponent(self, parent,
 778                                 (AwtToolkit::ComponentFactory)
 779                                 AwtDialog::Create);
 780     JNI_CHECK_PEER_CREATION_RETURN(self);
 781 
 782     CATCH_BAD_ALLOC;
 783 }
 784 
 785 /*
 786  * Class:     sun_awt_windows_WDialogPeer
 787  * Method:    _show
 788  * Signature: ()V
 789  */
 790 JNIEXPORT void JNICALL
 791 Java_sun_awt_windows_WDialogPeer_showModal(JNIEnv *env, jobject self)
 792 {
 793     TRY;
 794 
 795     jobject selfGlobalRef = env->NewGlobalRef(self);
 796 
 797     AwtToolkit::GetInstance().SyncCall(AwtDialog::_ShowModal,
 798         (void *)selfGlobalRef);
 799     // selfGlobalRef is deleted in _ShowModal
 800 
 801     CATCH_BAD_ALLOC;
 802 }
 803 
 804 /*
 805  * Class:     sun_awt_windows_WDialogPeer
 806  * Method:    _hide
 807  * Signature: ()V
 808  */
 809 JNIEXPORT void JNICALL
 810 Java_sun_awt_windows_WDialogPeer_endModal(JNIEnv *env, jobject self)
 811 {
 812     TRY;
 813 
 814     jobject selfGlobalRef = env->NewGlobalRef(self);
 815 
 816     AwtToolkit::GetInstance().SyncCall(AwtDialog::_EndModal,
 817         (void *)selfGlobalRef);
 818     // selfGlobalRef is deleted in _EndModal
 819 
 820     CATCH_BAD_ALLOC;
 821 }
 822 
 823 /*
 824  * Class:     sun_awt_windows_WFramePeer
 825  * Method:    pSetIMMOption
 826  * Signature: (Ljava/lang/String;)V
 827  */
 828 JNIEXPORT void JNICALL
 829 Java_sun_awt_windows_WDialogPeer_pSetIMMOption(JNIEnv *env, jobject self,
 830                                                jstring option)
 831 {
 832     TRY;
 833 
 834     SetIMMOptionStruct *sios = new SetIMMOptionStruct;
 835     sios->dialog = env->NewGlobalRef(self);
 836     sios->option = (jstring)env->NewGlobalRef(option);
 837 
 838     AwtToolkit::GetInstance().SyncCall(AwtDialog::_SetIMMOption, sios);
 839     // global refs and sios are deleted in _SetIMMOption
 840 
 841     CATCH_BAD_ALLOC;
 842 }
 843 } /* extern "C" */