1/*
2 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#include "jni_util.h"
27#include "awt_Toolkit.h"
28#include "awt_Dialog.h"
29#include "awt_Window.h"
30
31#include <windowsx.h>
32
33#include "java_awt_Dialog.h"
34
35/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
36 */
37
38/************************************************************************/
39// Struct for _SetIMMOption() method
40struct SetIMMOptionStruct {
41    jobject dialog;
42    jstring option;
43};
44/************************************************************************
45 * AwtDialog fields
46 */
47
48jfieldID AwtDialog::titleID;
49jfieldID AwtDialog::undecoratedID;
50
51#if defined(DEBUG)
52// counts how many nested modal dialogs are open, a sanity
53// check to ensure the somewhat complicated disable/enable
54// code is working properly
55int AwtModalityNestCounter = 0;
56#endif
57
58HHOOK AWTModalHook;
59HHOOK AWTMouseHook;
60
61int VisibleModalDialogsCount = 0;
62
63/************************************************************************
64 * AwtDialog class methods
65 */
66
67AwtDialog::AwtDialog() {
68    m_modalWnd = NULL;
69}
70
71AwtDialog::~AwtDialog()
72{
73}
74
75void AwtDialog::Dispose()
76{
77    if (m_modalWnd != NULL) {
78        WmEndModal();
79    }
80    AwtFrame::Dispose();
81}
82
83LPCTSTR AwtDialog::GetClassName() {
84  return AWT_DIALOG_WINDOW_CLASS_NAME;
85}
86
87void AwtDialog::FillClassInfo(WNDCLASSEX *lpwc)
88{
89    AwtWindow::FillClassInfo(lpwc);
90    //Fixed 6280303: REGRESSION: Java cup icon appears in title bar of dialogs
91    // Dialog inherits icon from its owner dinamically
92    lpwc->hIcon = NULL;
93    lpwc->hIconSm = NULL;
94}
95
96/*
97 * Create a new AwtDialog object and window.
98 */
99AwtDialog* AwtDialog::Create(jobject peer, jobject parent)
100{
101    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
102
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    } catch (...) {
185        env->DeleteLocalRef(target);
186        throw;
187    }
188
189done:
190    env->DeleteLocalRef(target);
191
192    return dialog;
193}
194
195MsgRouting AwtDialog::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
196    // By the request from Swing team, click on the Dialog's title should generate Ungrab
197    if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) {
198        m_grabbedWindow->Ungrab();
199    }
200
201    if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
202        // Dialog is non-maximizable
203        if ((button & DBL_CLICK) && hitTest == HTCAPTION) {
204            return mrConsume;
205        }
206    }
207    return AwtFrame::WmNcMouseDown(hitTest, x, y, button);
208}
209
210LRESULT CALLBACK AwtDialog::ModalFilterProc(int code,
211                                            WPARAM wParam, LPARAM lParam)
212{
213    HWND hWnd = (HWND)wParam;
214    HWND blocker = AwtWindow::GetModalBlocker(hWnd);
215    if (::IsWindow(blocker) &&
216        ((code == HCBT_ACTIVATE) ||
217         (code == HCBT_SETFOCUS)))
218    {
219        // fix for 6270632: this window and all its blockers can be minimized by
220        // "show desktop" button, so we should restore them first
221        if (::IsIconic(hWnd)) {
222            ::ShowWindow(hWnd, SW_RESTORE);
223        }
224        PopupBlockers(blocker, TRUE, ::GetForegroundWindow(), FALSE);
225        // return 1 to prevent the system from allowing the operation
226        return 1;
227    }
228    return CallNextHookEx(0, code, wParam, lParam);
229}
230
231LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode,
232                                          WPARAM wParam, LPARAM lParam)
233{
234    if (nCode >= 0)
235    {
236        MOUSEHOOKSTRUCT *mhs = (MOUSEHOOKSTRUCT *)lParam;
237        HWND hWnd = mhs->hwnd;
238        if ((wParam == WM_LBUTTONDOWN) ||
239            (wParam == WM_MBUTTONDOWN) ||
240            (wParam == WM_RBUTTONDOWN) ||
241            (wParam == WM_MOUSEACTIVATE) ||
242            (wParam == WM_MOUSEWHEEL) ||
243            (wParam == WM_MOUSEHWHEEL) ||
244            (wParam == WM_NCLBUTTONDOWN) ||
245            (wParam == WM_NCMBUTTONDOWN) ||
246            (wParam == WM_NCRBUTTONDOWN))
247        {
248            HWND blocker = AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(hWnd));
249            if (::IsWindow(blocker)) {
250                BOOL onTaskbar = !(::WindowFromPoint(mhs->pt) == hWnd);
251                PopupBlockers(blocker, FALSE, ::GetForegroundWindow(), onTaskbar);
252                // return a nonzero value to prevent the system from passing
253                // the message to the target window procedure
254                return 1;
255            }
256        }
257    }
258
259    return CallNextHookEx(0, nCode, wParam, lParam);
260}
261
262/*
263 * The function goes through the hierarchy of the blockers and
264 * popups all the blockers. Note that the function starts from the top
265 * blocker and goes down to the blocker which is the bottom one.
266 * Using another traversal algorithm (bottom->top) may cause to flickering
267 * as the bottom blocker will cover the top blocker for a while.
268 */
269void AwtDialog::PopupBlockers(HWND blocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar)
270{
271    HWND nextBlocker = AwtWindow::GetModalBlocker(blocker);
272    BOOL nextBlockerExists = ::IsWindow(nextBlocker);
273    if (nextBlockerExists) {
274        PopupBlockers(nextBlocker, isModalHook, prevFGWindow, onTaskbar);
275    }
276    PopupBlocker(blocker, nextBlocker, isModalHook, prevFGWindow, onTaskbar);
277}
278
279/*
280 * The function popups the blocker, for a non-blocked blocker we need
281 * to activate the blocker but if a blocker is blocked, then we need
282 * to change z-order of the blocker placing the blocker under the next blocker.
283 */
284void AwtDialog::PopupBlocker(HWND blocker, HWND nextBlocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar)
285{
286    if (blocker == AwtToolkit::GetInstance().GetHWnd()) {
287        return;
288    }
289
290    // fix for 6494032
291    if (isModalHook && !::IsWindowVisible(blocker)) {
292        ::ShowWindow(blocker, SW_SHOWNA);
293    }
294
295    BOOL nextBlockerExists = ::IsWindow(nextBlocker);
296    UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE;
297
298    if (nextBlockerExists) {
299        // Fix for 6829546: if blocker is a top-most window, but window isn't, then
300        // calling ::SetWindowPos(dialog, blocker, ...) makes window top-most as well
301        BOOL topmostNextBlocker = (::GetWindowLong(nextBlocker, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
302        BOOL topmostBlocker = (::GetWindowLong(blocker, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
303        if (!topmostNextBlocker || topmostBlocker) {
304            ::SetWindowPos(blocker, nextBlocker, 0, 0, 0, 0, flags);
305        } else {
306            ::SetWindowPos(blocker, HWND_TOP, 0, 0, 0, 0, flags);
307        }
308    } else {
309        ::SetWindowPos(blocker, HWND_TOP, 0, 0, 0, 0, flags);
310        // no beep/flash if the mouse was clicked in the taskbar menu
311        // or the dialog is currently inactive
312        if (!isModalHook && !onTaskbar && (blocker == prevFGWindow)) {
313            AnimateModalBlocker(blocker);
314        }
315        ::BringWindowToTop(blocker);
316        ::SetForegroundWindow(blocker);
317    }
318}
319
320void AwtDialog::AnimateModalBlocker(HWND window)
321{
322    ::MessageBeep(MB_OK);
323    // some heuristics: 3 times x 64 milliseconds
324    AwtWindow::FlashWindowEx(window, 3, 64, FLASHW_CAPTION);
325}
326
327LRESULT CALLBACK AwtDialog::MouseHookProc_NonTT(int nCode,
328                                                WPARAM wParam, LPARAM lParam)
329{
330    static HWND lastHWnd = NULL;
331    if (nCode >= 0)
332    {
333        MOUSEHOOKSTRUCT *mhs = (MOUSEHOOKSTRUCT *)lParam;
334        HWND hWnd = mhs->hwnd;
335        HWND blocker = AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(hWnd));
336        if (::IsWindow(blocker)) {
337            if ((wParam == WM_MOUSEMOVE) ||
338                (wParam == WM_NCMOUSEMOVE))
339            {
340                if (lastHWnd != hWnd) {
341                    static HCURSOR hArrowCur = ::LoadCursor(NULL, IDC_ARROW);
342                    ::SetCursor(hArrowCur);
343                    lastHWnd = hWnd;
344                }
345                ::PostMessage(hWnd, WM_SETCURSOR, (WPARAM)hWnd, 0);
346            } else if (wParam == WM_MOUSELEAVE) {
347                lastHWnd = NULL;
348            }
349
350            AwtDialog::MouseHookProc(nCode, wParam, lParam);
351            return 1;
352        }
353    }
354
355    return CallNextHookEx(0, nCode, wParam, lParam);
356}
357
358void AwtDialog::Show()
359{
360    m_visible = true;
361    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
362
363    BOOL locationByPlatform = env->GetBooleanField(GetTarget(env), AwtWindow::locationByPlatformID);
364    if (locationByPlatform) {
365         moveToDefaultLocation();
366    }
367    EnableTranslucency(TRUE);
368    if (IsFocusableWindow() && (IsAutoRequestFocus() || IsFocusedWindowModalBlocker())) {
369        ::ShowWindow(GetHWnd(), SW_SHOW);
370    } else {
371        ::ShowWindow(GetHWnd(), SW_SHOWNA);
372    }
373}
374
375void AwtDialog::DoUpdateIcon()
376{
377    AwtFrame::DoUpdateIcon();
378    //Workaround windows bug:
379    //Decorations are not updated correctly for owned dialogs
380    //when changing dlg with icon <--> dlg without icon
381    RECT winRect;
382    RECT clientRect;
383    ::GetWindowRect(GetHWnd(), &winRect);
384    ::GetClientRect(GetHWnd(), &clientRect);
385    ::MapWindowPoints(HWND_DESKTOP, GetHWnd(), (LPPOINT)&winRect, 2);
386    HRGN winRgn = CreateRectRgnIndirect(&winRect);
387    HRGN clientRgn = CreateRectRgnIndirect(&clientRect);
388    ::CombineRgn(winRgn, winRgn, clientRgn, RGN_DIFF);
389    ::RedrawWindow(GetHWnd(), NULL, winRgn, RDW_FRAME | RDW_INVALIDATE);
390    ::DeleteObject(winRgn);
391    ::DeleteObject(clientRgn);
392}
393
394HICON AwtDialog::GetEffectiveIcon(int iconType)
395{
396    HWND hOwner = ::GetWindow(GetHWnd(), GW_OWNER);
397    BOOL isResizable = ((GetStyle() & WS_THICKFRAME) != 0);
398    BOOL smallIcon = ((iconType == ICON_SMALL) || (iconType == 2/*ICON_SMALL2*/));
399    HICON hIcon = (smallIcon) ? GetHIconSm() : GetHIcon();
400    if ((hIcon == NULL) && (isResizable || (hOwner == NULL))) {
401        //Java cup icon is not loaded in window class for dialogs
402        //It needs to be set explicitly for resizable dialogs
403        //and ownerless dialogs
404        hIcon = (smallIcon) ? AwtToolkit::GetInstance().GetAwtIconSm() :
405            AwtToolkit::GetInstance().GetAwtIcon();
406    } else if ((hIcon != NULL) && IsIconInherited() && !isResizable) {
407        //Non-resizable dialogs without explicitely set icon
408        //Should have no icon
409        hIcon = NULL;
410    }
411    return hIcon;
412}
413
414void AwtDialog::CheckInstallModalHook() {
415    VisibleModalDialogsCount++;
416    if (VisibleModalDialogsCount == 1) {
417        AWTModalHook = ::SetWindowsHookEx(WH_CBT, (HOOKPROC)ModalFilterProc,
418                                         0, AwtToolkit::MainThread());
419        AWTMouseHook = ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)MouseHookProc,
420                                         0, AwtToolkit::MainThread());
421    }
422}
423
424void AwtDialog::CheckUninstallModalHook() {
425    if (VisibleModalDialogsCount == 1) {
426        UnhookWindowsHookEx(AWTModalHook);
427        UnhookWindowsHookEx(AWTMouseHook);
428    }
429    VisibleModalDialogsCount--;
430}
431
432void AwtDialog::ModalPerformActivation(HWND hWnd)
433{
434    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
435
436    AwtWindow *w = (AwtWindow *)AwtComponent::GetComponent(hWnd);
437    if ((w != NULL) && w->IsEmbeddedFrame()) {
438        jobject target = w->GetTarget(env);
439        env->CallVoidMethod(target, AwtFrame::activateEmbeddingTopLevelMID);
440        env->DeleteLocalRef(target);
441    } else {
442        ::BringWindowToTop(hWnd);
443        ::SetForegroundWindow(hWnd);
444    }
445}
446
447void AwtDialog::ModalActivateNextWindow(HWND dialogHWnd,
448                                        jobject dialogTarget, jobject dialogPeer)
449{
450    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
451
452    jboolean exc;
453    jlongArray windows = (jlongArray) JNU_CallStaticMethodByName
454                                            (env,
455                                             &exc,
456                                             "sun/awt/windows/WWindowPeer",
457                                             "getActiveWindowHandles",
458                                             "(Ljava/awt/Component;)[J",
459                                             dialogTarget).l;
460    if (exc == JNI_TRUE) {
461        throw std::bad_alloc();
462    }
463    if (windows == NULL) {
464        return;
465    }
466
467    jboolean isCopy;
468    jlong *ws = env->GetLongArrayElements(windows, &isCopy);
469    if (ws == NULL) {
470        throw std::bad_alloc();
471    }
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
485MsgRouting 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
505MsgRouting 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
530void 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
560void 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
611MsgRouting AwtDialog::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss)
612{
613    UpdateSystemMenu();
614    DoUpdateIcon();
615    return mrConsume;
616}
617
618MsgRouting 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
629LRESULT 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
649void 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    }
663ret:
664    env->DeleteGlobalRef(self);
665}
666
667void 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    }
681ret:
682    env->DeleteGlobalRef(self);
683}
684
685void 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    }
721ret:
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
737extern "C" {
738
739JNIEXPORT void JNICALL
740Java_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    DASSERT(AwtDialog::titleID != NULL);
748    CHECK_NULL(AwtDialog::titleID);
749
750    AwtDialog::undecoratedID
751        = env->GetFieldID(cls,"undecorated","Z");
752    DASSERT(AwtDialog::undecoratedID != NULL);
753    CHECK_NULL(AwtDialog::undecoratedID);
754
755    CATCH_BAD_ALLOC;
756}
757
758} /* extern "C" */
759
760
761/************************************************************************
762 * DialogPeer native methods
763 */
764
765extern "C" {
766
767/*
768 * Class:     sun_awt_windows_WDialogPeer
769 * Method:    create
770 * Signature: (Lsun/awt/windows/WComponentPeer;)V
771 */
772JNIEXPORT void JNICALL
773Java_sun_awt_windows_WDialogPeer_createAwtDialog(JNIEnv *env, jobject self,
774                                        jobject parent)
775{
776    TRY;
777
778    PDATA pData;
779    AwtToolkit::CreateComponent(self, parent,
780                                (AwtToolkit::ComponentFactory)
781                                AwtDialog::Create);
782    JNI_CHECK_PEER_CREATION_RETURN(self);
783
784    CATCH_BAD_ALLOC;
785}
786
787/*
788 * Class:     sun_awt_windows_WDialogPeer
789 * Method:    _show
790 * Signature: ()V
791 */
792JNIEXPORT void JNICALL
793Java_sun_awt_windows_WDialogPeer_showModal(JNIEnv *env, jobject self)
794{
795    TRY;
796
797    jobject selfGlobalRef = env->NewGlobalRef(self);
798
799    AwtToolkit::GetInstance().SyncCall(AwtDialog::_ShowModal,
800        (void *)selfGlobalRef);
801    // selfGlobalRef is deleted in _ShowModal
802
803    CATCH_BAD_ALLOC;
804}
805
806/*
807 * Class:     sun_awt_windows_WDialogPeer
808 * Method:    _hide
809 * Signature: ()V
810 */
811JNIEXPORT void JNICALL
812Java_sun_awt_windows_WDialogPeer_endModal(JNIEnv *env, jobject self)
813{
814    TRY;
815
816    jobject selfGlobalRef = env->NewGlobalRef(self);
817
818    AwtToolkit::GetInstance().SyncCall(AwtDialog::_EndModal,
819        (void *)selfGlobalRef);
820    // selfGlobalRef is deleted in _EndModal
821
822    CATCH_BAD_ALLOC;
823}
824
825/*
826 * Class:     sun_awt_windows_WFramePeer
827 * Method:    pSetIMMOption
828 * Signature: (Ljava/lang/String;)V
829 */
830JNIEXPORT void JNICALL
831Java_sun_awt_windows_WDialogPeer_pSetIMMOption(JNIEnv *env, jobject self,
832                                               jstring option)
833{
834    TRY;
835
836    SetIMMOptionStruct *sios = new SetIMMOptionStruct;
837    sios->dialog = env->NewGlobalRef(self);
838    sios->option = (jstring)env->NewGlobalRef(option);
839
840    AwtToolkit::GetInstance().SyncCall(AwtDialog::_SetIMMOption, sios);
841    // global refs and sios are deleted in _SetIMMOption
842
843    CATCH_BAD_ALLOC;
844}
845} /* extern "C" */
846