/*
 * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "awt_Toolkit.h"
#include "awt_Frame.h"
#include "awt_MenuBar.h"
#include "awt_Dialog.h"
#include "awt_IconCursor.h"
#include "awt_Win32GraphicsDevice.h"
#include "ComCtl32Util.h"

#include <windowsx.h>

#include <java_lang_Integer.h>
#include <sun_awt_EmbeddedFrame.h>
#include <sun_awt_windows_WEmbeddedFrame.h>
#include <sun_awt_windows_WEmbeddedFramePeer.h>


/* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
 */

/***********************************************************************/
// Struct for _SetState() method
struct SetStateStruct {
    jobject frame;
    jint state;
};
// Struct for _SetMaximizedBounds() method
struct SetMaximizedBoundsStruct {
    jobject frame;
    jint x, y;
    jint width, height;
};
// Struct for _SetMenuBar() method
struct SetMenuBarStruct {
    jobject frame;
    jobject menubar;
};

// Struct for _SetIMMOption() method
struct SetIMMOptionStruct {
    jobject frame;
    jstring option;
};
// Struct for _SynthesizeWmActivate() method
struct SynthesizeWmActivateStruct {
    jobject frame;
    jboolean doActivate;
};
// Struct for _NotifyModalBlocked() method
struct NotifyModalBlockedStruct {
    jobject frame;
    jobject peer;
    jobject blockerPeer;
    jboolean blocked;
};
// Information about thread containing modal blocked embedded frames
struct BlockedThreadStruct {
    int framesCount;
    HHOOK mouseHook;
    HHOOK modalHook;
};
/************************************************************************
 * AwtFrame fields
 */

jfieldID AwtFrame::handleID;

jfieldID AwtFrame::undecoratedID;
jmethodID AwtFrame::getExtendedStateMID;
jmethodID AwtFrame::setExtendedStateMID;

jmethodID AwtFrame::activateEmbeddingTopLevelMID;

Hashtable AwtFrame::sm_BlockedThreads("AWTBlockedThreads");

/************************************************************************
 * AwtFrame methods
 */

AwtFrame::AwtFrame() {
    m_parentWnd = NULL;
    menuBar = NULL;
    m_isEmbedded = FALSE;
    m_ignoreWmSize = FALSE;
    m_isMenuDropped = FALSE;
    m_isInputMethodWindow = FALSE;
    m_isUndecorated = FALSE;
    m_proxyFocusOwner = NULL;
    m_lastProxiedFocusOwner = NULL;
    m_actualFocusedWindow = NULL;
    m_iconic = FALSE;
    m_zoomed = FALSE;
    m_maxBoundsSet = FALSE;
    m_forceResetZoomed = FALSE;

    isInManualMoveOrSize = FALSE;
    grabbedHitTest = 0;
}

AwtFrame::~AwtFrame()
{
}

void AwtFrame::Dispose()
{
    DestroyProxyFocusOwner();
    AwtWindow::Dispose();
}

LPCTSTR AwtFrame::GetClassName() {
    return AWT_FRAME_WINDOW_CLASS_NAME;
}

/*
 * Create a new AwtFrame object and window.
 */
AwtFrame* AwtFrame::Create(jobject self, jobject parent)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (env->EnsureLocalCapacity(1) < 0) {
        return NULL;
    }

    PDATA pData;
    HWND hwndParent = NULL;
    AwtFrame* frame;
    jclass cls = NULL;
    jclass inputMethodWindowCls = NULL;
    jobject target = NULL;

    try {
        target = env->GetObjectField(self, AwtObject::targetID);
        JNI_CHECK_NULL_GOTO(target, "target", done);

        if (parent != NULL) {
            JNI_CHECK_PEER_GOTO(parent, done);
            {
                AwtFrame* parent = (AwtFrame *)pData;
                hwndParent = parent->GetHWnd();
            }
        }

        frame = new AwtFrame();

        {
            /*
             * A variation on Netscape's hack for embedded frames: the client
             * area of the browser is a Java Frame for parenting purposes, but
             * really a Windows child window
             */
            cls = env->FindClass("sun/awt/EmbeddedFrame");
            if (cls == NULL) {
                return NULL;
            }
            INT_PTR handle;
            jboolean isEmbeddedInstance = env->IsInstanceOf(target, cls);
            jboolean isEmbedded = FALSE;

            if (isEmbeddedInstance) {
                handle = static_cast<INT_PTR>(env->GetLongField(target, AwtFrame::handleID));
                if (handle != 0) {
                    isEmbedded = TRUE;
                }
            }
            frame->m_isEmbedded = isEmbedded;

            if (isEmbedded) {
                hwndParent = (HWND)handle;
                RECT rect;
                ::GetClientRect(hwndParent, &rect);
                //Fix for 6328675: SWT_AWT.new_Frame doesn't occupy client area under JDK6
                frame->m_isUndecorated = true;
                /*
                 * Fix for BugTraq ID 4337754.
                 * Initialize m_peerObject before the first call
                 * to AwtFrame::GetClassName().
                 */
                frame->m_peerObject = env->NewGlobalRef(self);
                frame->RegisterClass();
                DWORD exStyle = WS_EX_NOPARENTNOTIFY;

                if (GetRTL()) {
                    exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
                    if (GetRTLReadingOrder())
                        exStyle |= WS_EX_RTLREADING;
                }

                frame->m_hwnd = ::CreateWindowEx(exStyle,
                                                 frame->GetClassName(), TEXT(""),
                                                 WS_CHILD | WS_CLIPCHILDREN,
                                                 0, 0,
                                                 rect.right, rect.bottom,
                                                 hwndParent, NULL,
                                                 AwtToolkit::GetInstance().GetModuleHandle(),
                                                 NULL);
                frame->LinkObjects(env, self);
                frame->SubclassHWND();

                // Update target's dimensions to reflect this embedded window.
                ::GetClientRect(frame->m_hwnd, &rect);
                ::MapWindowPoints(frame->m_hwnd, hwndParent, (LPPOINT)&rect, 2);

                env->SetIntField(target, AwtComponent::xID, rect.left);
                env->SetIntField(target, AwtComponent::yID, rect.top);
                env->SetIntField(target, AwtComponent::widthID,
                                 rect.right-rect.left);
                env->SetIntField(target, AwtComponent::heightID,
                                 rect.bottom-rect.top);
                frame->InitPeerGraphicsConfig(env, self);
                AwtToolkit::GetInstance().RegisterEmbedderProcessId(hwndParent);
            } else {
                jint state = env->CallIntMethod(self, AwtFrame::getExtendedStateMID);
                DWORD exStyle;
                DWORD style;

               // for input method windows, use minimal decorations
               inputMethodWindowCls = env->FindClass("sun/awt/im/InputMethodWindow");
               if ((inputMethodWindowCls != NULL) && env->IsInstanceOf(target, inputMethodWindowCls)) {
                   //for below-the-spot composition window, use no decoration
                   if (env->GetBooleanField(target, AwtFrame::undecoratedID) == JNI_TRUE){
                        exStyle = 0;
                        style = WS_POPUP|WS_CLIPCHILDREN;
                        frame->m_isUndecorated = TRUE;
                   } else {
                        exStyle = WS_EX_PALETTEWINDOW;
                        style = WS_CLIPCHILDREN;
                   }
                   frame->m_isInputMethodWindow = TRUE;
                } else if (env->GetBooleanField(target, AwtFrame::undecoratedID) == JNI_TRUE) {
                    exStyle = 0;
                    style = WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN |
                        WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
                  if (state & java_awt_Frame_ICONIFIED) {
                      frame->setIconic(TRUE);
                  }
                    frame->m_isUndecorated = TRUE;
                } else {
                    exStyle = WS_EX_WINDOWEDGE;
                    style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
                  if (state & java_awt_Frame_ICONIFIED) {
                      frame->setIconic(TRUE);
                  }
                }

                if (GetRTL()) {
                    exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR;
                    if (GetRTLReadingOrder())
                        exStyle |= WS_EX_RTLREADING;
                }

                jint x = env->GetIntField(target, AwtComponent::xID);
                jint y = env->GetIntField(target, AwtComponent::yID);
                jint width = env->GetIntField(target, AwtComponent::widthID);
                jint height = env->GetIntField(target, AwtComponent::heightID);

                frame->CreateHWnd(env, L"",
                                  style,
                                  exStyle,
                                  0, 0, 0, 0,
                                  hwndParent,
                                  NULL,
                                  ::GetSysColor(COLOR_WINDOWTEXT),
                                  ::GetSysColor(COLOR_WINDOWFRAME),
                                  self);
                /*
                 * Reshape here instead of during create, so that a
                 * WM_NCCALCSIZE is sent.
                 */
                frame->Reshape(x, y, width, height);
            }
        }
    } catch (...) {
        env->DeleteLocalRef(target);
        env->DeleteLocalRef(cls);
        env->DeleteLocalRef(inputMethodWindowCls);
        throw;
    }

done:
    env->DeleteLocalRef(target);
    env->DeleteLocalRef(cls);
    env->DeleteLocalRef(inputMethodWindowCls);

    return frame;
}

LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message,
                                           WPARAM wParam, LPARAM lParam)
{
    TRY;

    DASSERT(::IsWindow(hwnd));

    AwtFrame *parent = (AwtFrame *)
        AwtComponent::GetComponentImpl(::GetParent(hwnd));

    if (!parent || parent->GetProxyFocusOwner() != hwnd ||
        message == AwtComponent::WmAwtIsComponent ||
        message == WM_GETOBJECT)
    {
        return ComCtl32Util::GetInstance().DefWindowProc(NULL, hwnd, message, wParam, lParam);
    }

    AwtComponent *focusOwner = NULL;
    // IME and input language related messages need to be sent to a window
    // which has the Java input focus
    switch (message) {
        case WM_IME_STARTCOMPOSITION:
        case WM_IME_ENDCOMPOSITION:
        case WM_IME_COMPOSITION:
        case WM_IME_SETCONTEXT:
        case WM_IME_NOTIFY:
        case WM_IME_CONTROL:
        case WM_IME_COMPOSITIONFULL:
        case WM_IME_SELECT:
        case WM_IME_CHAR:
        case 0x0288: // WM_IME_REQUEST
        case WM_IME_KEYDOWN:
        case WM_IME_KEYUP:
        case WM_INPUTLANGCHANGEREQUEST:
        case WM_INPUTLANGCHANGE:
        // TODO: when a Choice's list is dropped down and we're scrolling in
        // the list WM_MOUSEWHEEL messages come to the poxy, not to the list. Why?
        case WM_MOUSEWHEEL:
            focusOwner = AwtComponent::GetComponent(parent->GetLastProxiedFocusOwner());
            if  (focusOwner != NULL) {
                return focusOwner->WindowProc(message, wParam, lParam);
            }
            break;
        case WM_SETFOCUS:
            if (!sm_suppressFocusAndActivation && parent->IsEmbeddedFrame()) {
                parent->AwtSetActiveWindow();
            }
            return 0;
        case WM_KILLFOCUS:
            if (!sm_suppressFocusAndActivation && parent->IsEmbeddedFrame()) {
                AwtWindow::SynthesizeWmActivate(FALSE, parent->GetHWnd(), NULL);

            } else if (sm_restoreFocusAndActivation) {
                if (AwtComponent::GetFocusedWindow() != NULL) {
                    AwtWindow *focusedWindow = (AwtWindow*)GetComponent(AwtComponent::GetFocusedWindow());
                    if (focusedWindow != NULL) {
                        // Will just silently restore native focus & activation.
                        focusedWindow->AwtSetActiveWindow();
                    }
                }
            }
            return 0;
        case 0x0127: // WM_CHANGEUISTATE
        case 0x0128: // WM_UPDATEUISTATE
            return 0;
    }
    return parent->WindowProc(message, wParam, lParam);

    CATCH_BAD_ALLOC_RET(0);
}

void AwtFrame::CreateProxyFocusOwner()
{
    if (AwtToolkit::IsMainThread()) {
        AwtFrame::_CreateProxyFocusOwner((void *)this);
    } else {
        AwtToolkit::GetInstance().InvokeFunction(AwtFrame::_CreateProxyFocusOwner, (void *)this);
    }
}

void AwtFrame::_CreateProxyFocusOwner(void *param)
{
    DASSERT(AwtToolkit::IsMainThread());

    AwtFrame *f = (AwtFrame *)param;
    DASSERT(f->m_proxyFocusOwner == NULL);

    f->m_proxyFocusOwner = ::CreateWindow(TEXT("STATIC"),
                                          TEXT("ProxyFocusOwner"),
                                          WS_CHILD,
                                          0, 0, 0, 0, f->GetHWnd(), NULL,
                                          AwtToolkit::GetInstance().
                                          GetModuleHandle(),
                                          NULL);

    f->m_proxyDefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(f->m_proxyFocusOwner, ProxyWindowProc);
}

void AwtFrame::DestroyProxyFocusOwner()
{
    // proxy focus owner must be destroyed on toolkit thread only
    if (AwtToolkit::IsMainThread()) {
        AwtFrame::_DestroyProxyFocusOwner((void *)this);
    } else {
        AwtToolkit::GetInstance().InvokeFunction(AwtFrame::_DestroyProxyFocusOwner, (void *)this);
    }
}

void AwtFrame::_DestroyProxyFocusOwner(void *param)
{
    DASSERT(AwtToolkit::IsMainThread());

    AwtFrame *f = (AwtFrame *)param;
    if (f->m_proxyFocusOwner != NULL) {
        HWND toDestroy = f->m_proxyFocusOwner;
        f->m_proxyFocusOwner = NULL;
        ComCtl32Util::GetInstance().UnsubclassHWND(toDestroy, ProxyWindowProc, f->m_proxyDefWindowProc);
        ::DestroyWindow(toDestroy);
    }
}

MsgRouting AwtFrame::WmShowWindow(BOOL show, UINT status)
{
    /*
     * Fix for 6492970.
     * When a non-focusable toplevel is shown alone the Java process
     * is not foreground. If one shows another (focusable) toplevel
     * the native platform not always makes it foreground (see the CR).
     * Even worse, sometimes it sends the newly shown toplevel WM_ACTIVATE
     * message. This breaks Java focus. To workaround the problem we
     * set the toplevel being shown foreground programmatically.
     * The fix is localized to non-foreground process case only.
     * (See also: 6599270)
     */
    if (!IsEmbeddedFrame() && show == TRUE && status == 0) {
        HWND fgHWnd = ::GetForegroundWindow();
        if (fgHWnd != NULL) {
            DWORD fgProcessID;
            ::GetWindowThreadProcessId(fgHWnd, &fgProcessID);

            if (fgProcessID != ::GetCurrentProcessId()) {
                AwtWindow* window = (AwtWindow*)GetComponent(GetHWnd());

                if (window != NULL && window->IsFocusableWindow() && window->IsAutoRequestFocus() &&
                    !::IsWindow(GetModalBlocker(GetHWnd())))
                {
                    // When the Java process is not allowed to set the foreground window
                    // (see MSDN) the request below will just have no effect.
                    ::SetForegroundWindow(GetHWnd());
                }
            }
        }
    }
    return AwtWindow::WmShowWindow(show, status);
}

MsgRouting AwtFrame::WmMouseUp(UINT flags, int x, int y, int button) {
    if (isInManualMoveOrSize) {
        isInManualMoveOrSize = FALSE;
        ::ReleaseCapture();
        return mrConsume;
    }
    return AwtWindow::WmMouseUp(flags, x, y, button);
}

MsgRouting AwtFrame::WmMouseMove(UINT flags, int x, int y) {
    /**
     * If this Frame is non-focusable then we should implement move and size operation for it by
     * ourselfves because we don't dispatch appropriate mouse messages to default window procedure.
     */
    if (!IsFocusableWindow() && isInManualMoveOrSize) {
        DWORD curPos = ::GetMessagePos();
        x = GET_X_LPARAM(curPos);
        y = GET_Y_LPARAM(curPos);
        RECT r;
        ::GetWindowRect(GetHWnd(), &r);
        POINT mouseLoc = {x, y};
        mouseLoc.x -= savedMousePos.x;
        mouseLoc.y -= savedMousePos.y;
        savedMousePos.x = x;
        savedMousePos.y = y;
        if (grabbedHitTest == HTCAPTION) {
            ::SetWindowPos(GetHWnd(), NULL, r.left+mouseLoc.x, r.top+mouseLoc.y,
                           r.right-r.left, r.bottom-r.top,
                           SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
        } else {
            switch (grabbedHitTest) {
            case HTTOP:
                r.top += mouseLoc.y;
                break;
            case HTBOTTOM:
                r.bottom += mouseLoc.y;
                break;
            case HTRIGHT:
                r.right += mouseLoc.x;
                break;
            case HTLEFT:
                r.left += mouseLoc.x;
                break;
            case HTTOPLEFT:
                r.left += mouseLoc.x;
                r.top += mouseLoc.y;
                break;
            case HTTOPRIGHT:
                r.top += mouseLoc.y;
                r.right += mouseLoc.x;
                break;
            case HTBOTTOMLEFT:
                r.left += mouseLoc.x;
                r.bottom += mouseLoc.y;
                break;
            case HTBOTTOMRIGHT:
            case HTSIZE:
                r.right += mouseLoc.x;
                r.bottom += mouseLoc.y;
                break;
            }

            ::SetWindowPos(GetHWnd(), NULL, r.left, r.top,
                           r.right-r.left, r.bottom-r.top,
                           SWP_NOACTIVATE | SWP_NOZORDER |
                           SWP_NOCOPYBITS | SWP_DEFERERASE);
        }
        return mrConsume;
    } else {
        return AwtWindow::WmMouseMove(flags, x, y);
    }
}

MsgRouting AwtFrame::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) {
    if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
        /*
         * Fix for 6399659.
         * The native system shouldn't activate the next window in z-order
         * when minimizing non-focusable window.
         */
        if (hitTest == HTMINBUTTON) {
            ::ShowWindow(GetHWnd(), SW_SHOWMINNOACTIVE);
            return mrConsume;
        }
        /**
         * If this Frame is non-focusable then we should implement move and size operation for it by
         * ourselfves because we don't dispatch appropriate mouse messages to default window procedure.
         */
        if ((button & DBL_CLICK) && hitTest == HTCAPTION) {
            // Double click on caption - maximize or restore Frame.
            if (IsResizable()) {
                if (::IsZoomed(GetHWnd())) {
                    ::ShowWindow(GetHWnd(), SW_SHOWNOACTIVATE);
                } else {
                    ::ShowWindow(GetHWnd(), SW_MAXIMIZE);
                }
            }
            return mrConsume;
        }
        switch (hitTest) {
        case HTMAXBUTTON:
            if (IsResizable()) {
                if (::IsZoomed(GetHWnd())) {
                    ::ShowWindow(GetHWnd(), SW_SHOWNOACTIVATE);
                } else {
                    ::ShowWindow(GetHWnd(), SW_MAXIMIZE);
                }
            }
            return mrConsume;
        default:
            return mrDoDefault;
        }
    }
    return AwtWindow::WmNcMouseUp(hitTest, x, y, button);
}

MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
    // By Swing request, click on the Frame's decorations (even on
    // grabbed Frame) should generate UngrabEvent
    if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) {
        m_grabbedWindow->Ungrab();
    }
    if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
        switch (hitTest) {
        case HTTOP:
        case HTBOTTOM:
        case HTLEFT:
        case HTRIGHT:
        case HTTOPLEFT:
        case HTTOPRIGHT:
        case HTBOTTOMLEFT:
        case HTBOTTOMRIGHT:
        case HTSIZE:
            // Zoomed or non-resizable unfocusable frames should not be resizable.
            if (isZoomed() || !IsResizable()) {
                return mrConsume;
            }
        case HTCAPTION:
            // We are going to perform default mouse action on non-client area of this window
            // Grab mouse for this purpose and store coordinates for motion vector calculation
            savedMousePos.x = x;
            savedMousePos.y = y;
            ::SetCapture(GetHWnd());
            isInManualMoveOrSize = TRUE;
            grabbedHitTest = hitTest;
            return mrConsume;
        default:
            return mrDoDefault;
        }
    }
    return AwtWindow::WmNcMouseDown(hitTest, x, y, button);
}

// Override AwtWindow::Reshape() to handle minimized/maximized
// frames (see 6525850, 4065534)
void AwtFrame::Reshape(int x, int y, int width, int height)
{
    if (isIconic()) {
    // normal AwtComponent::Reshape will not work for iconified windows so...
        WINDOWPLACEMENT wp;
        POINT       ptMinPosition = {x,y};
        POINT       ptMaxPosition = {0,0};
        RECT        rcNormalPosition = {x,y,x+width,y+height};
        RECT        rcWorkspace;
        HWND        hWndDesktop = GetDesktopWindow();
        HWND        hWndSelf = GetHWnd();

        // SetWindowPlacement takes workspace coordinates, but
        // if taskbar is at top of screen, workspace coords !=
        // screen coords, so offset by workspace origin
        VERIFY(::SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&rcWorkspace, 0));
        ::OffsetRect(&rcNormalPosition, -rcWorkspace.left, -rcWorkspace.top);

        // set the window size for when it is not-iconified
        wp.length = sizeof(wp);
        wp.flags = WPF_SETMINPOSITION;
        wp.showCmd = IsVisible() ? SW_SHOWMINIMIZED : SW_HIDE;
        wp.ptMinPosition = ptMinPosition;
        wp.ptMaxPosition = ptMaxPosition;
        wp.rcNormalPosition = rcNormalPosition;

        // If the call is not guarded with ignoreWmSize,
        // a regression for bug 4851435 appears.
        // Having this call guarded also prevents
        // changing the iconified state of the frame
        // while calling the Frame.setBounds() method.
        m_ignoreWmSize = TRUE;
        ::SetWindowPlacement(hWndSelf, &wp);
        m_ignoreWmSize = FALSE;

        return;
    }

    if (isZoomed()) {
    // setting size of maximized window, we remove the
    // maximized state bit (matches Motif behaviour)
    // (calling ShowWindow(SW_RESTORE) would fire an
    //  activation event which we don't want)
        LONG    style = GetStyle();
        DASSERT(style & WS_MAXIMIZE);
        style ^= WS_MAXIMIZE;
        SetStyle(style);
    }

    AwtWindow::Reshape(x, y, width, height);
}


/* Show the frame in it's current state */
void
AwtFrame::Show()
{
    m_visible = true;
    HWND hwnd = GetHWnd();
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    DTRACE_PRINTLN3("AwtFrame::Show:%s%s%s",
                  m_iconic ? " iconic" : "",
                  m_zoomed ? " zoomed" : "",
                  m_iconic || m_zoomed ? "" : " normal");

    BOOL locationByPlatform = env->GetBooleanField(GetTarget(env), AwtWindow::locationByPlatformID);

    if (locationByPlatform) {
         moveToDefaultLocation();
    }
    EnableTranslucency(TRUE);

    BOOL autoRequestFocus = IsAutoRequestFocus();

    if (m_iconic) {
        if (m_zoomed) {
            // This whole function could probably be rewritten to use
            // ::SetWindowPlacement but MS docs doesn't tell if
            // ::SetWindowPlacement is a proper superset of
            // ::ShowWindow.  So let's be conservative and only use it
            // here, where we really do need it.
            DTRACE_PRINTLN("AwtFrame::Show(SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED");
            WINDOWPLACEMENT wp;
            ::ZeroMemory(&wp, sizeof(WINDOWPLACEMENT));
            wp.length = sizeof(WINDOWPLACEMENT);
            ::GetWindowPlacement(hwnd, &wp);
            if (!IsFocusableWindow() || !autoRequestFocus) {
                wp.showCmd = SW_SHOWMINNOACTIVE;
            } else {
                wp.showCmd = SW_SHOWMINIMIZED;
            }
            wp.flags |= WPF_RESTORETOMAXIMIZED;
            ::SetWindowPlacement(hwnd, &wp);
        }
        else {
            DTRACE_PRINTLN("AwtFrame::Show(SW_SHOWMINIMIZED)");
            if (!IsFocusableWindow() || !autoRequestFocus) {
                ::ShowWindow(hwnd, SW_SHOWMINNOACTIVE);
            } else {
                ::ShowWindow(hwnd, SW_SHOWMINIMIZED);
            }
        }
    }
    else if (m_zoomed) {
        DTRACE_PRINTLN("AwtFrame::Show(SW_SHOWMAXIMIZED)");
        if (!autoRequestFocus) {

            m_filterFocusAndActivation = TRUE;
            ::ShowWindow(hwnd, SW_MAXIMIZE);
            m_filterFocusAndActivation = FALSE;

        } else if (!IsFocusableWindow()) {
            ::ShowWindow(hwnd, SW_MAXIMIZE);
        } else {
            ::ShowWindow(hwnd, SW_SHOWMAXIMIZED);
        }
    }
    else if (m_isInputMethodWindow) {
        // Don't activate input methow window
        DTRACE_PRINTLN("AwtFrame::Show(SW_SHOWNA)");
        ::ShowWindow(hwnd, SW_SHOWNA);

        // After the input method window shown, we have to adjust the
        // IME candidate window position. Here is why.
        // Usually, when IMM opens the candidate window, it sends WM_IME_NOTIFY w/
        // IMN_OPENCANDIDATE message to the awt component window. The
        // awt component makes a Java call to acquire the text position
        // in order to show the candidate window just below the input method window.
        // However, by the time it acquires the position, the input method window
        // hasn't been displayed yet, the position returned is just below
        // the composed text and when the input method window is shown, it
        // will hide part of the candidate list. To fix this, we have to
        // adjust the candidate window position after the input method window
        // is shown. See bug 5012944.
        AdjustCandidateWindowPos();
    }
    else {
        // Nor iconic, nor zoomed (handled above) - so use SW_RESTORE
        // to show in "normal" state regardless of whatever stale
        // state might the invisible window still has.
        DTRACE_PRINTLN("AwtFrame::Show(SW_RESTORE)");
        if (!IsFocusableWindow() || !autoRequestFocus) {
            ::ShowWindow(hwnd, SW_SHOWNOACTIVATE);
        } else {
            ::ShowWindow(hwnd, SW_RESTORE);
        }
    }
}

void
AwtFrame::SendWindowStateEvent(int oldState, int newState)
{
    SendWindowEvent(java_awt_event_WindowEvent_WINDOW_STATE_CHANGED,
                    NULL, oldState, newState);
}

void
AwtFrame::ClearMaximizedBounds()
{
    m_maxBoundsSet = FALSE;
}

void AwtFrame::AdjustCandidateWindowPos()
{
    // This method should only be called if the current frame
    // is the input method window frame.
    if (!m_isInputMethodWindow) {
        return;
    }

    RECT inputWinRec, focusWinRec;
    AwtComponent *comp = AwtComponent::GetComponent(AwtComponent::sm_focusOwner);
    if (comp == NULL) {
        return;
    }

    ::GetWindowRect(GetHWnd(), &inputWinRec);
    ::GetWindowRect(sm_focusOwner, &focusWinRec);

    LPARAM candType = comp->GetCandidateType();
    HWND defaultIMEWnd = ::ImmGetDefaultIMEWnd(GetHWnd());
    if (defaultIMEWnd == NULL) {
        return;
    }
    UINT bits = 1;
    // adjusts the candidate window position
    for (int iCandType = 0; iCandType < 32; iCandType++, bits<<=1) {
        if (candType & bits) {
            CANDIDATEFORM cf;
            cf.dwIndex = iCandType;
            cf.dwStyle = CFS_CANDIDATEPOS;
            // Since the coordinates are relative to the containing window,
            // we have to calculate the coordinates as below.
            cf.ptCurrentPos.x = inputWinRec.left - focusWinRec.left;
            cf.ptCurrentPos.y = inputWinRec.bottom - focusWinRec.top;

            // sends IMC_SETCANDIDATEPOS to IMM to move the candidate window.
            ::SendMessage(defaultIMEWnd, WM_IME_CONTROL, IMC_SETCANDIDATEPOS, (LPARAM)&cf);
        }
    }
}

void
AwtFrame::SetMaximizedBounds(int x, int y, int w, int h)
{
    m_maxPos.x  = x;
    m_maxPos.y  = y;
    m_maxSize.x = w;
    m_maxSize.y = h;
    m_maxBoundsSet = TRUE;
}

MsgRouting AwtFrame::WmGetMinMaxInfo(LPMINMAXINFO lpmmi)
{
    //Firstly call AwtWindow's function
    MsgRouting r = AwtWindow::WmGetMinMaxInfo(lpmmi);

    //Then replace maxPos & maxSize if necessary
    if (!m_maxBoundsSet) {
        return r;
    }

    if (m_maxPos.x != java_lang_Integer_MAX_VALUE)
        lpmmi->ptMaxPosition.x = m_maxPos.x;
    if (m_maxPos.y != java_lang_Integer_MAX_VALUE)
        lpmmi->ptMaxPosition.y = m_maxPos.y;
    if (m_maxSize.x != java_lang_Integer_MAX_VALUE)
        lpmmi->ptMaxSize.x = m_maxSize.x;
    if (m_maxSize.y != java_lang_Integer_MAX_VALUE)
        lpmmi->ptMaxSize.y = m_maxSize.y;
    return mrConsume;
}

MsgRouting AwtFrame::WmSize(UINT type, int w, int h)
{
    currentWmSizeState = type;
    if (currentWmSizeState == SIZE_MINIMIZED) {
        UpdateSecurityWarningVisibility();
    }

    if (m_ignoreWmSize) {
        return mrDoDefault;
    }

    DTRACE_PRINTLN6("AwtFrame::WmSize: %dx%d,%s visible, state%s%s%s",
                  w, h,
                  ::IsWindowVisible(GetHWnd()) ? "" : " not",
                  m_iconic ? " iconic" : "",
                  m_zoomed ? " zoomed" : "",
                  m_iconic || m_zoomed ? "" : " normal");

    BOOL iconify = type == SIZE_MINIMIZED;

    // Note that zoom may be set to TRUE in several cases:
    //    1. type == SIZE_MAXIMIZED means that either the user or
    //       the developer (via setExtendedState(MAXIMIZED_BOTH)
    //       maximizes the frame.
    //    2. type == SIZE_MINIMIZED && isZoomed() means that a maximized
    //       frame is to be minimized. If the user minimizes a maximized
    //       frame, we need to keep the zoomed property TRUE. However,
    //       if the developer calls setExtendedState(ICONIFIED), i.e.
    //       w/o combining the ICONIFIED state with the MAXIMIZED state,
    //       we MUST RESET the zoomed property.
    //       The flag m_forceResetZoomed identifies the latter case.
    BOOL zoom =
        (
         type == SIZE_MAXIMIZED
         ||
         (type == SIZE_MINIMIZED && isZoomed())
        )
        && !m_forceResetZoomed;

    // Set the new state and send appropriate Java event
    jint oldState = java_awt_Frame_NORMAL;
    if (isIconic()) {
        oldState |= java_awt_Frame_ICONIFIED;
    }
    if (isZoomed()) {
        oldState |= java_awt_Frame_MAXIMIZED_BOTH;
    }

    jint newState = java_awt_Frame_NORMAL;
    if (iconify) {
        newState |= java_awt_Frame_ICONIFIED;
    }
    if (zoom) {
        newState |= java_awt_Frame_MAXIMIZED_BOTH;
    }

    setIconic(iconify);
    setZoomed(zoom);

    jint changed = oldState ^ newState;
    if (changed != 0) {
        DTRACE_PRINTLN2("AwtFrame::WmSize: reporting state change %x -> %x",
                oldState, newState);

        // sync target with peer
        JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
        env->CallVoidMethod(GetPeer(env), AwtFrame::setExtendedStateMID, newState);

        // report (de)iconification to old clients
        if (changed & java_awt_Frame_ICONIFIED) {
            if (newState & java_awt_Frame_ICONIFIED) {
                SendWindowEvent(java_awt_event_WindowEvent_WINDOW_ICONIFIED);
            } else {
                SendWindowEvent(java_awt_event_WindowEvent_WINDOW_DEICONIFIED);
            }
        }

        // New (since 1.4) state change event
        SendWindowStateEvent(oldState, newState);
    }

    // If window is in iconic state, do not send COMPONENT_RESIZED event
    if (isIconic()) {
        return mrDoDefault;
    }

    return AwtWindow::WmSize(type, w, h);
}

MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
{
    jint type;

    if (nState != WA_INACTIVE) {
        if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd())) ||
            CheckActivateActualFocusedWindow(opposite))
        {
            return mrConsume;
        }
        type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS;
        AwtComponent::SetFocusedWindow(GetHWnd());

    } else {
        if (!::IsWindow(AwtWindow::GetModalBlocker(opposite))) {
            // If deactivation happens because of press on grabbing
            // window - this is nonsense, since grabbing window is
            // assumed to have focus and watch for deactivation.  But
            // this can happen - if grabbing window is proxied Window,
            // with Frame keeping real focus for it.
            if (m_grabbedWindow != NULL) {
                if (m_grabbedWindow->GetHWnd() == opposite) {
                    // Do nothing
                } else {
                    // Normally, we would rather check that this ==
                    // grabbed window, and focus is leaving it -
                    // ungrab.  But since we know about proxied
                    // windows, we simply assume this is one of the
                    // known cases.
                    if (!m_grabbedWindow->IsOneOfOwnersOf((AwtWindow*)AwtComponent::GetComponent(opposite))) {
                        m_grabbedWindow->Ungrab();
                    }
                }
            }
            CheckRetainActualFocusedWindow(opposite);

            type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS;
            AwtComponent::SetFocusedWindow(NULL);
            sm_focusOwner = NULL;
        }
    }

    SendWindowEvent(type, opposite);
    return mrConsume;
}

BOOL AwtFrame::CheckActivateActualFocusedWindow(HWND deactivatedOpositeHWnd)
{
    if (m_actualFocusedWindow != NULL) {
        HWND hwnd = m_actualFocusedWindow->GetHWnd();
        if (hwnd != NULL && ::IsWindowVisible(hwnd)) {
            SynthesizeWmActivate(TRUE, hwnd, deactivatedOpositeHWnd);
            return TRUE;
        }
        m_actualFocusedWindow = NULL;
    }
    return FALSE;
}

void AwtFrame::CheckRetainActualFocusedWindow(HWND activatedOpositeHWnd)
{
    // If actual focused window is not this Frame
    if (AwtComponent::GetFocusedWindow() != GetHWnd()) {
        // Make sure the actual focused window is an owned window of this frame
        AwtWindow *focusedWindow = (AwtWindow *)AwtComponent::GetComponent(AwtComponent::GetFocusedWindow());
        if (focusedWindow != NULL && focusedWindow->GetOwningFrameOrDialog() == this) {

            // Check that the opposite window is not this frame, nor an owned window of this frame
            if (activatedOpositeHWnd != NULL) {
                AwtWindow *oppositeWindow = (AwtWindow *)AwtComponent::GetComponent(activatedOpositeHWnd);
                if (oppositeWindow && oppositeWindow != this &&
                    oppositeWindow->GetOwningFrameOrDialog() != this)
                {
                    m_actualFocusedWindow = focusedWindow;
                }
            } else {
                 m_actualFocusedWindow = focusedWindow;
            }
        }
    }
}

BOOL AwtFrame::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest)
{
    if (hittest == HTCLIENT) {
        // Don't let the actualFocusedWindow to steal focus if:
        // a) the frame is clicked in its client area;
        // b) focus is requested to some of the frame's child.
        m_actualFocusedWindow = NULL;
    }
    return AwtWindow::AwtSetActiveWindow(isMouseEventCause);
}

MsgRouting AwtFrame::WmEnterMenuLoop(BOOL isTrackPopupMenu)
{
    if ( !isTrackPopupMenu ) {
        m_isMenuDropped = TRUE;
    }
    return mrDoDefault;
}

MsgRouting AwtFrame::WmExitMenuLoop(BOOL isTrackPopupMenu)
{
    if ( !isTrackPopupMenu ) {
        m_isMenuDropped = FALSE;
    }
    return mrDoDefault;
}

AwtMenuBar* AwtFrame::GetMenuBar()
{
    return menuBar;
}

void AwtFrame::SetMenuBar(AwtMenuBar* mb)
{
    menuBar = mb;
    if (mb == NULL) {
        // Remove existing menu bar, if any.
        ::SetMenu(GetHWnd(), NULL);
    } else {
        if (menuBar->GetHMenu() != NULL) {
            ::SetMenu(GetHWnd(), menuBar->GetHMenu());
        }
    }
}

MsgRouting AwtFrame::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT& drawInfo)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    // if the item to be redrawn is the menu bar, then do it
    AwtMenuBar* awtMenubar = GetMenuBar();
    if (drawInfo.CtlType == ODT_MENU && (awtMenubar != NULL) &&
        (::GetMenu( GetHWnd() ) == (HMENU)drawInfo.hwndItem) )
        {
                awtMenubar->DrawItem(drawInfo);
                return mrConsume;
    }

        return AwtComponent::WmDrawItem(ctrlId, drawInfo);
}

MsgRouting AwtFrame::WmMeasureItem(UINT ctrlId, MEASUREITEMSTRUCT& measureInfo)
{
        JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
        AwtMenuBar* awtMenubar = GetMenuBar();
        if ((measureInfo.CtlType == ODT_MENU) && (awtMenubar != NULL))
        {
                // AwtMenu instance is stored in itemData. Use it to check if this
                // menu is the menu bar.
                AwtMenu * pMenu = (AwtMenu *) measureInfo.itemData;
                DASSERT(pMenu != NULL);
                if ( pMenu == awtMenubar )
                {
                        HWND hWnd = GetHWnd();
                        HDC hDC = ::GetDC(hWnd);
                        DASSERT(hDC != NULL);
                        awtMenubar->MeasureItem(hDC, measureInfo);
                        VERIFY(::ReleaseDC(hWnd, hDC));
                        return mrConsume;
                }
        }

        return AwtComponent::WmMeasureItem(ctrlId, measureInfo);
}

MsgRouting AwtFrame::WmGetIcon(WPARAM iconType, LRESULT& retVal)
{
    //Workaround windows bug:
    //when reseting from specific icon to class icon
    //taskbar is not updated
    if (iconType <= 2 /*ICON_SMALL2*/) {
        retVal = (LRESULT)GetEffectiveIcon(iconType);
        return mrConsume;
    } else {
        return mrDoDefault;
    }
}

void AwtFrame::DoUpdateIcon()
{
    //Workaround windows bug:
    //when reseting from specific icon to class icon
    //taskbar is not updated
    HICON hIcon = GetEffectiveIcon(ICON_BIG);
    HICON hIconSm = GetEffectiveIcon(ICON_SMALL);
    SendMessage(WM_SETICON, ICON_BIG,   (LPARAM)hIcon);
    SendMessage(WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
}

HICON AwtFrame::GetEffectiveIcon(int iconType)
{
    BOOL smallIcon = ((iconType == ICON_SMALL) || (iconType == 2/*ICON_SMALL2*/));
    HICON hIcon = (smallIcon) ? GetHIconSm() : GetHIcon();
    if (hIcon == NULL) {
        hIcon = (smallIcon) ? AwtToolkit::GetInstance().GetAwtIconSm() :
            AwtToolkit::GetInstance().GetAwtIcon();
    }
    return hIcon;
}

static BOOL keepOnMinimize(jobject peer) {
    static BOOL checked = FALSE;
    static BOOL keep = FALSE;
    if (!checked) {
        keep = (JNU_GetStaticFieldByName(AwtToolkit::GetEnv(), NULL,
            "sun/awt/windows/WFramePeer", "keepOnMinimize", "Z").z) == JNI_TRUE;
        checked = TRUE;
    }
    return keep;
}

MsgRouting AwtFrame::WmSysCommand(UINT uCmdType, int xPos, int yPos)
{
    // ignore any WM_SYSCOMMAND if this window is blocked by modal dialog
    if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) {
        return mrConsume;
    }

    if (uCmdType == (SYSCOMMAND_IMM & 0xFFF0)){
        JNIEnv* env = AwtToolkit::GetEnv();
        JNU_CallMethodByName(env, NULL, m_peerObject,
            "notifyIMMOptionChange", "()V");
        DASSERT(!safe_ExceptionOccurred(env));
        return mrConsume;
    }
    if ((uCmdType == SC_MINIMIZE) && keepOnMinimize(m_peerObject)) {
        ::ShowWindow(GetHWnd(),SW_SHOWMINIMIZED);
        return mrConsume;
    }
    return AwtWindow::WmSysCommand(uCmdType, xPos, yPos);
}

LRESULT AwtFrame::WinThreadExecProc(ExecuteArgs * args)
{
    switch( args->cmdId ) {
        case FRAME_SETMENUBAR:
        {
            jobject  mbPeer = (jobject)args->param1;

            // cancel any currently dropped down menus
            if (m_isMenuDropped) {
                SendMessage(WM_CANCELMODE);
            }

            if (mbPeer == NULL) {
                // Remove existing menu bar, if any
                SetMenuBar(NULL);
            } else {
                JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
                AwtMenuBar* menuBar = (AwtMenuBar *)JNI_GET_PDATA(mbPeer);
                SetMenuBar(menuBar);
            }
            DrawMenuBar();
            break;
        }

        default:
            AwtWindow::WinThreadExecProc(args);
            break;
    }

    return 0L;
}

void AwtFrame::_SynthesizeWmActivate(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SynthesizeWmActivateStruct *sas = (SynthesizeWmActivateStruct *)param;
    jobject self = sas->frame;
    jboolean doActivate = sas->doActivate;

    AwtFrame *frame = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    frame = (AwtFrame *)pData;

    SynthesizeWmActivate(doActivate, frame->GetHWnd(), NULL);
ret:
    env->DeleteGlobalRef(self);

    delete sas;
}

jobject AwtFrame::_GetBoundsPrivate(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    jobject result = NULL;
    AwtFrame *f = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    f = (AwtFrame *)pData;
    if (::IsWindow(f->GetHWnd()))
    {
        RECT rect;
        ::GetWindowRect(f->GetHWnd(), &rect);
        HWND parent = ::GetParent(f->GetHWnd());
        if (::IsWindow(parent))
        {
            POINT zero;
            zero.x = 0;
            zero.y = 0;
            ::ClientToScreen(parent, &zero);
            ::OffsetRect(&rect, -zero.x, -zero.y);
        }

        result = JNU_NewObjectByName(env, "java/awt/Rectangle", "(IIII)V",
            rect.left, rect.top, rect.bottom-rect.top, rect.right-rect.left);
    }
ret:
    env->DeleteGlobalRef(self);

    if (result != NULL)
    {
        jobject resultGlobalRef = env->NewGlobalRef(result);
        env->DeleteLocalRef(result);
        return resultGlobalRef;
    }
    else
    {
        return NULL;
    }
}

void AwtFrame::_SetState(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SetStateStruct *sss = (SetStateStruct *)param;
    jobject self = sss->frame;
    jint state = sss->state;

    AwtFrame *f = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    f = (AwtFrame *)pData;
    HWND hwnd = f->GetHWnd();
    if (::IsWindow(hwnd))
    {
        DASSERT(!IsBadReadPtr(f, sizeof(AwtFrame)));

        BOOL iconify = (state & java_awt_Frame_ICONIFIED) != 0;
        BOOL zoom = (state & java_awt_Frame_MAXIMIZED_BOTH)
                        == java_awt_Frame_MAXIMIZED_BOTH;

        DTRACE_PRINTLN4("WFramePeer.setState:%s%s ->%s%s",
                  f->isIconic() ? " iconic" : "",
                  f->isZoomed() ? " zoomed" : "",
                  iconify       ? " iconic" : "",
                  zoom          ? " zoomed" : "");

        if (::IsWindowVisible(hwnd)) {
            BOOL focusable = f->IsFocusableWindow();

            WINDOWPLACEMENT wp;
            ::ZeroMemory(&wp, sizeof(wp));
            wp.length = sizeof(wp);
            ::GetWindowPlacement(hwnd, &wp);

            // Iconify first.
            // If both iconify & zoom are TRUE, handle this case
            // with wp.flags field below.
            if (iconify) {
                wp.showCmd = focusable ? SW_MINIMIZE : SW_SHOWMINNOACTIVE;
            } else if (zoom) {
                wp.showCmd = focusable ? SW_SHOWMAXIMIZED : SW_MAXIMIZE;
            } else { // zoom == iconify == FALSE
                wp.showCmd = focusable ? SW_RESTORE : SW_SHOWNOACTIVATE;
            }

            if (zoom && iconify) {
                wp.flags |= WPF_RESTORETOMAXIMIZED;
            } else {
                wp.flags &= ~WPF_RESTORETOMAXIMIZED;
            }

            if (!zoom) {
                f->m_forceResetZoomed = TRUE;
            }

            // The SetWindowPlacement() causes the WmSize() invocation
            //  which, in turn, actually updates the m_iconic & m_zoomed flags
            //  as well as sends Java event (WINDOW_STATE_CHANGED.)
            ::SetWindowPlacement(hwnd, &wp);

            f->m_forceResetZoomed = FALSE;
        } else {
            DTRACE_PRINTLN("  not visible, just recording the requested state");

            f->setIconic(iconify);
            f->setZoomed(zoom);
        }
    }
ret:
    env->DeleteGlobalRef(self);

    delete sss;
}

jint AwtFrame::_GetState(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    jint result = java_awt_Frame_NORMAL;
    AwtFrame *f = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    f = (AwtFrame *)pData;
    if (::IsWindow(f->GetHWnd()))
    {
        DASSERT(!::IsBadReadPtr(f, sizeof(AwtFrame)));
        if (f->isIconic()) {
            result |= java_awt_Frame_ICONIFIED;
        }
        if (f->isZoomed()) {
            result |= java_awt_Frame_MAXIMIZED_BOTH;
        }

        DTRACE_PRINTLN2("WFramePeer.getState:%s%s",
                  f->isIconic() ? " iconic" : "",
                  f->isZoomed() ? " zoomed" : "");
    }
ret:
    env->DeleteGlobalRef(self);

    return result;
}

void AwtFrame::_SetMaximizedBounds(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SetMaximizedBoundsStruct *smbs = (SetMaximizedBoundsStruct *)param;
    jobject self = smbs->frame;
    int x = smbs->x;
    int y = smbs->y;
    int width = smbs->width;
    int height = smbs->height;

    AwtFrame *f = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    f = (AwtFrame *)pData;
    if (::IsWindow(f->GetHWnd()))
    {
        DASSERT(!::IsBadReadPtr(f, sizeof(AwtFrame)));
        f->SetMaximizedBounds(x, y, width, height);
    }
ret:
    env->DeleteGlobalRef(self);

    delete smbs;
}

void AwtFrame::_ClearMaximizedBounds(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    AwtFrame *f = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    f = (AwtFrame *)pData;
    if (::IsWindow(f->GetHWnd()))
    {
        DASSERT(!::IsBadReadPtr(f, sizeof(AwtFrame)));
        f->ClearMaximizedBounds();
    }
ret:
    env->DeleteGlobalRef(self);
}

void AwtFrame::_SetMenuBar(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SetMenuBarStruct *smbs = (SetMenuBarStruct *)param;
    jobject self = smbs->frame;
    jobject menubar = smbs->menubar;

    AwtFrame *f = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    f = (AwtFrame *)pData;
    if (::IsWindow(f->GetHWnd()))
    {
        ExecuteArgs args;
        args.cmdId = FRAME_SETMENUBAR;
        args.param1 = (LPARAM)menubar;
        f->WinThreadExecProc(&args);
    }
ret:
    env->DeleteGlobalRef(self);
    env->DeleteGlobalRef(menubar);

    delete smbs;
}

void AwtFrame::_SetIMMOption(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    SetIMMOptionStruct *sios = (SetIMMOptionStruct *)param;
    jobject self = sios->frame;
    jstring option = sios->option;

    int badAlloc = 0;
    LPCTSTR coption;
    LPCTSTR empty = TEXT("InputMethod");
    AwtFrame *f = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    JNI_CHECK_NULL_GOTO(option, "IMMOption argument", ret);

    f = (AwtFrame *)pData;
    if (::IsWindow(f->GetHWnd()))
    {
        coption = JNU_GetStringPlatformChars(env, option, NULL);
        if (coption == NULL)
        {
            badAlloc = 1;
        }
        if (!badAlloc)
        {
            HMENU hSysMenu = ::GetSystemMenu(f->GetHWnd(), FALSE);
            ::AppendMenu(hSysMenu,  MF_STRING, SYSCOMMAND_IMM, coption);

            if (coption != empty)
            {
                JNU_ReleaseStringPlatformChars(env, option, coption);
            }
        }
    }
ret:
    env->DeleteGlobalRef(self);
    env->DeleteGlobalRef(option);

    delete sios;

    if (badAlloc)
    {
        throw std::bad_alloc();
    }
}

void AwtFrame::_NotifyModalBlocked(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    NotifyModalBlockedStruct *nmbs = (NotifyModalBlockedStruct *)param;
    jobject self = nmbs->frame;
    jobject peer = nmbs->peer;
    jobject blockerPeer = nmbs->blockerPeer;
    jboolean blocked = nmbs->blocked;

    PDATA pData;

    pData = JNI_GET_PDATA(peer);
    AwtFrame *f = (AwtFrame *)pData;

    // dialog here may be NULL, for example, if the blocker is a native dialog
    // however, we need to install/unistall modal hooks anyway
    pData = JNI_GET_PDATA(blockerPeer);
    AwtDialog *d = (AwtDialog *)pData;

    if ((f != NULL) && ::IsWindow(f->GetHWnd()))
    {
        // get an HWND of the toplevel window this embedded frame is within
        HWND fHWnd = f->GetHWnd();
        while (::GetParent(fHWnd) != NULL) {
            fHWnd = ::GetParent(fHWnd);
        }
        // we must get a toplevel hwnd here, however due to some strange
        // behaviour of Java Plugin (a bug?) when running in IE at
        // this moment the embedded frame hasn't been placed into the
        // browser yet and fHWnd is not a toplevel, so we shouldn't install
        // the hook here
        if ((::GetWindowLong(fHWnd, GWL_STYLE) & WS_CHILD) == 0) {
            // if this toplevel is created in another thread, we should install
            // the modal hook into it to track window activation and mouse events
            DWORD fThread = ::GetWindowThreadProcessId(fHWnd, NULL);
            if (fThread != AwtToolkit::GetInstance().MainThread()) {
                // check if this thread has been already blocked
                BlockedThreadStruct *blockedThread = (BlockedThreadStruct *)sm_BlockedThreads.get((void *)fThread);
                if (blocked) {
                    if (blockedThread == NULL) {
                        blockedThread = new BlockedThreadStruct;
                        blockedThread->framesCount = 1;
                        blockedThread->modalHook = ::SetWindowsHookEx(WH_CBT, (HOOKPROC)AwtDialog::ModalFilterProc,
                                                                      0, fThread);
                        blockedThread->mouseHook = ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)AwtDialog::MouseHookProc_NonTT,
                                                                      0, fThread);
                        sm_BlockedThreads.put((void *)fThread, blockedThread);
                    } else {
                        blockedThread->framesCount++;
                    }
                } else {
                    // see the comment above: if Java Plugin behaviour when running in IE
                    // was right, blockedThread would be always not NULL here
                    if (blockedThread != NULL) {
                        DASSERT(blockedThread->framesCount > 0);
                        if ((blockedThread->framesCount) == 1) {
                            ::UnhookWindowsHookEx(blockedThread->modalHook);
                            ::UnhookWindowsHookEx(blockedThread->mouseHook);
                            sm_BlockedThreads.remove((void *)fThread);
                            delete blockedThread;
                        } else {
                            blockedThread->framesCount--;
                        }
                    }
                }
            }
        }
    }

    env->DeleteGlobalRef(self);
    env->DeleteGlobalRef(peer);
    env->DeleteGlobalRef(blockerPeer);

    delete nmbs;
}

/************************************************************************
 * WFramePeer native methods
 */

extern "C" {

/*
 * Class:     java_awt_Frame
 * Method:    initIDs
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_java_awt_Frame_initIDs(JNIEnv *env, jclass cls)
{
    TRY;

    AwtFrame::undecoratedID = env->GetFieldID(cls,"undecorated","Z");
    DASSERT(AwtFrame::undecoratedID != NULL);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    initIDs
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WFramePeer_initIDs(JNIEnv *env, jclass cls)
{
    TRY;

    AwtFrame::setExtendedStateMID = env->GetMethodID(cls, "setExtendedState", "(I)V");
    AwtFrame::getExtendedStateMID = env->GetMethodID(cls, "getExtendedState", "()I");

    DASSERT(AwtFrame::setExtendedStateMID);
    DASSERT(AwtFrame::getExtendedStateMID);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    setState
 * Signature: (I)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WFramePeer_setState(JNIEnv *env, jobject self,
    jint state)
{
    TRY;

    SetStateStruct *sss = new SetStateStruct;
    sss->frame = env->NewGlobalRef(self);
    sss->state = state;

    AwtToolkit::GetInstance().SyncCall(AwtFrame::_SetState, sss);
    // global ref and sss are deleted in _SetState()

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    getState
 * Signature: ()I
 */
JNIEXPORT jint JNICALL
Java_sun_awt_windows_WFramePeer_getState(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    return static_cast<jint>(reinterpret_cast<INT_PTR>(AwtToolkit::GetInstance().SyncCall(
        (void*(*)(void*))AwtFrame::_GetState,
        (void *)selfGlobalRef)));
    // selfGlobalRef is deleted in _GetState()

    CATCH_BAD_ALLOC_RET(java_awt_Frame_NORMAL);
}


/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    setMaximizedBounds
 * Signature: (IIII)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WFramePeer_setMaximizedBounds(JNIEnv *env, jobject self,
    jint x, jint y, jint width, jint height)
{
    TRY;

    SetMaximizedBoundsStruct *smbs = new SetMaximizedBoundsStruct;
    smbs->frame = env->NewGlobalRef(self);
    smbs->x = x;
    smbs->y = y;
    smbs->width = width;
    smbs->height = height;

    AwtToolkit::GetInstance().SyncCall(AwtFrame::_SetMaximizedBounds, smbs);
    // global ref and smbs are deleted in _SetMaximizedBounds()

    CATCH_BAD_ALLOC;
}


/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    clearMaximizedBounds
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WFramePeer_clearMaximizedBounds(JNIEnv *env, jobject self)
{
    TRY;

    jobject selfGlobalRef = env->NewGlobalRef(self);

    AwtToolkit::GetInstance().SyncCall(AwtFrame::_ClearMaximizedBounds,
        (void *)selfGlobalRef);
    // selfGlobalRef is deleted in _ClearMaximizedBounds()

    CATCH_BAD_ALLOC;
}


/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    setMenuBar0
 * Signature: (Lsun/awt/windows/WMenuBarPeer;)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WFramePeer_setMenuBar0(JNIEnv *env, jobject self,
                                            jobject mbPeer)
{
    TRY;

    SetMenuBarStruct *smbs = new SetMenuBarStruct;
    smbs->frame = env->NewGlobalRef(self);
    smbs->menubar = env->NewGlobalRef(mbPeer);

    AwtToolkit::GetInstance().SyncCall(AwtFrame::_SetMenuBar, smbs);
    // global refs ans smbs are deleted in _SetMenuBar()

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    create
 * Signature: (Lsun/awt/windows/WComponentPeer;)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WFramePeer_createAwtFrame(JNIEnv *env, jobject self,
                                               jobject parent)
{
    TRY;

    AwtToolkit::CreateComponent(self, parent,
                                (AwtToolkit::ComponentFactory)
                                AwtFrame::Create);
    PDATA pData;
    JNI_CHECK_PEER_CREATION_RETURN(self);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    getSysMenuHeight
 * Signature: ()I
 */
JNIEXPORT jint JNICALL
Java_sun_awt_windows_WFramePeer_getSysMenuHeight(JNIEnv *env, jclass self)
{
    TRY;

    return ::GetSystemMetrics(SM_CYMENUSIZE);

    CATCH_BAD_ALLOC_RET(0);
}

/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    pSetIMMOption
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WFramePeer_pSetIMMOption(JNIEnv *env, jobject self,
                                               jstring option)
{
    TRY;

    SetIMMOptionStruct *sios = new SetIMMOptionStruct;
    sios->frame = env->NewGlobalRef(self);
    sios->option = (jstring)env->NewGlobalRef(option);

    AwtToolkit::GetInstance().SyncCall(AwtFrame::_SetIMMOption, sios);
    // global refs and sios are deleted in _SetIMMOption()

    CATCH_BAD_ALLOC;
}

} /* extern "C" */


/************************************************************************
 * EmbeddedFrame native methods
 */

extern "C" {

/*
 * Class:     sun_awt_EmbeddedFrame
 * Method:    setPeer
 * Signature: (Ljava/awt/peer/ComponentPeer;)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_EmbeddedFrame_setPeer(JNIEnv *env, jobject self, jobject lpeer)
{
    TRY;

    jclass cls;
    jfieldID fid;

    cls = env->GetObjectClass(self);
    fid = env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;");
    env->SetObjectField(self, fid, lpeer);

    CATCH_BAD_ALLOC;
}

} /* extern "C" */


/************************************************************************
 * WEmbeddedFrame native methods
 */

extern "C" {

/*
 * Class:     sun_awt_windows_WFramePeer
 * Method:    initIDs
 * Signature: (Lsun/awt/windows/WMenuBarPeer;)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WEmbeddedFrame_initIDs(JNIEnv *env, jclass cls)
{
    TRY;

    AwtFrame::handleID = env->GetFieldID(cls, "handle", "J");
    DASSERT(AwtFrame::handleID != NULL);

    AwtFrame::activateEmbeddingTopLevelMID = env->GetMethodID(cls, "activateEmbeddingTopLevel", "()V");
    DASSERT(AwtFrame::activateEmbeddingTopLevelMID != NULL);

    CATCH_BAD_ALLOC;
}

JNIEXPORT void JNICALL
Java_sun_awt_windows_WEmbeddedFrame_notifyModalBlockedImpl(JNIEnv *env,
                                                           jobject self,
                                                           jobject peer,
                                                           jobject blockerPeer,
                                                           jboolean blocked)
{
    TRY;

    NotifyModalBlockedStruct *nmbs = new NotifyModalBlockedStruct;
    nmbs->frame = env->NewGlobalRef(self);
    nmbs->peer = env->NewGlobalRef(peer);
    nmbs->blockerPeer = env->NewGlobalRef(blockerPeer);
    nmbs->blocked = blocked;

    AwtToolkit::GetInstance().SyncCall(AwtFrame::_NotifyModalBlocked, nmbs);
    // global refs and nmbs are deleted in _NotifyModalBlocked()

    CATCH_BAD_ALLOC;
}

} /* extern "C" */


/************************************************************************
 * WEmbeddedFramePeer native methods
 */

extern "C" {

JNIEXPORT void JNICALL
Java_sun_awt_windows_WEmbeddedFramePeer_create(JNIEnv *env, jobject self,
                                               jobject parent)
{
    TRY;

    JNI_CHECK_NULL_RETURN(self, "peer");
    AwtToolkit::CreateComponent(self, parent,
                                (AwtToolkit::ComponentFactory)
                                AwtFrame::Create);
    PDATA pData;
    JNI_CHECK_PEER_CREATION_RETURN(self);

    CATCH_BAD_ALLOC;
}

JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WEmbeddedFramePeer_getBoundsPrivate(JNIEnv *env, jobject self)
{
    TRY;

    jobject result = (jobject)AwtToolkit::GetInstance().SyncCall(
        (void *(*)(void *))AwtFrame::_GetBoundsPrivate,
        env->NewGlobalRef(self));
    // global ref is deleted in _GetBoundsPrivate

    if (result != NULL)
    {
        jobject resultLocalRef = env->NewLocalRef(result);
        env->DeleteGlobalRef(result);
        return resultLocalRef;
    }
    else
    {
        return NULL;
    }

    CATCH_BAD_ALLOC_RET(NULL);
}

JNIEXPORT void JNICALL
Java_sun_awt_windows_WEmbeddedFramePeer_synthesizeWmActivate(JNIEnv *env, jobject self, jboolean doActivate)
{
    TRY;

    SynthesizeWmActivateStruct *sas = new SynthesizeWmActivateStruct;
    sas->frame = env->NewGlobalRef(self);
    sas->doActivate = doActivate;

    /*
     * WARNING: invoking this function without synchronization by m_Sync CriticalSection.
     * Taking this lock results in a deadlock.
     */
    AwtToolkit::GetInstance().InvokeFunction(AwtFrame::_SynthesizeWmActivate, sas);
    // global ref and sas are deleted in _SynthesizeWmActivate()

    CATCH_BAD_ALLOC;
}

} /* extern "C" */
