/*
 * Copyright (c) 1996, 2014, 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.
 */

/*
 * The Toolkit class has two functions: it instantiates the AWT
 * ToolkitPeer's native methods, and provides the DLL's core functions.
 *
 * There are two ways this DLL can be used: either as a dynamically-
 * loaded Java native library from the interpreter, or by a Windows-
 * specific app.  The first manner requires that the Toolkit provide
 * all support needed so the app can function as a first-class Windows
 * app, while the second assumes that the app will provide that
 * functionality.  Which mode this DLL functions in is determined by
 * which initialization paradigm is used. If the Toolkit is constructed
 * normally, then the Toolkit will have its own pump. If it is explicitly
 * initialized for an embedded environment (via a static method on
 * sun.awt.windows.WToolkit), then it will rely on an external message
 * pump.
 *
 * The most basic functionality needed is a Windows message pump (also
 * known as a message loop).  When an Java app is started as a console
 * app by the interpreter, the Toolkit needs to provide that message
 * pump if the AWT is dynamically loaded.
 */

#ifndef AWT_TOOLKIT_H
#define AWT_TOOLKIT_H

#include "awt.h"
#include "awtmsg.h"
#include "Trace.h"

#include "sun_awt_windows_WToolkit.h"

class AwtObject;
class AwtDialog;
class AwtDropTarget;

typedef VOID (CALLBACK* IDLEPROC)(VOID);
typedef BOOL (CALLBACK* PEEKMESSAGEPROC)(MSG&);

// Struct for _WInputMethod_enable|disableNativeIME method
struct EnableNativeIMEStruct {
    jobject self;
    jobject peer;
    jint context;
    jboolean useNativeCompWindow;
};

/*
 * class JNILocalFrame
 * Push/PopLocalFrame helper
 */
class JNILocalFrame {
  public:
    INLINE JNILocalFrame(JNIEnv *env, int size) {
        m_env = env;
        int result = m_env->PushLocalFrame(size);
        if (result < 0) {
            DASSERT(FALSE);
            throw std::bad_alloc();
        }
    }
    INLINE ~JNILocalFrame() { m_env->PopLocalFrame(NULL); }
  private:
    JNIEnv* m_env;
};

/*
 * class CriticalSection
 * ~~~~~ ~~~~~~~~~~~~~~~~
 * Lightweight intra-process thread synchronization. Can only be used with
 * other critical sections, and only within the same process.
 */
class CriticalSection {
  public:
    INLINE  CriticalSection() { ::InitializeCriticalSection(&rep); }
    INLINE ~CriticalSection() { ::DeleteCriticalSection(&rep); }

    class Lock {
      public:
        INLINE Lock(const CriticalSection& cs) : critSec(cs) {
            (const_cast<CriticalSection &>(critSec)).Enter();
        }
        INLINE ~Lock() {
            (const_cast<CriticalSection &>(critSec)).Leave();
        }
      private:
        const CriticalSection& critSec;
    };
    friend class Lock;

  private:
    CRITICAL_SECTION rep;

    CriticalSection(const CriticalSection&);
    const CriticalSection& operator =(const CriticalSection&);

  public:
    virtual void Enter() {
        ::EnterCriticalSection(&rep);
    }
    virtual BOOL TryEnter() {
        return ::TryEnterCriticalSection(&rep);
    }
    virtual void Leave() {
        ::LeaveCriticalSection(&rep);
    }
};

// Macros for using CriticalSection objects that help trace
// lock/unlock actions

/* Use THIS_FILE when it is available. */
#ifndef THIS_FILE
    #define THIS_FILE __FILE__
#endif

#define CRITICAL_SECTION_ENTER(cs) { \
    J2dTraceLn4(J2D_TRACE_VERBOSE2, \
                "CS.Wait:  tid, cs, file, line = 0x%x, 0x%x, %s, %d", \
                GetCurrentThreadId(), &(cs), THIS_FILE, __LINE__); \
    (cs).Enter(); \
    J2dTraceLn4(J2D_TRACE_VERBOSE2, \
                "CS.Enter: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \
                GetCurrentThreadId(), &(cs), THIS_FILE, __LINE__); \
}

#define CRITICAL_SECTION_LEAVE(cs) { \
    J2dTraceLn4(J2D_TRACE_VERBOSE2, \
                "CS.Leave: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \
                GetCurrentThreadId(), &(cs), THIS_FILE, __LINE__); \
    (cs).Leave(); \
    J2dTraceLn4(J2D_TRACE_VERBOSE2, \
                "CS.Left:  tid, cs, file, line = 0x%x, 0x%x, %s, %d", \
                GetCurrentThreadId(), &(cs), THIS_FILE, __LINE__); \
}

/************************************************************************
 * AwtToolkit class
 */

class AwtToolkit {
public:
    enum {
        KB_STATE_SIZE = 256
    };

    /* java.awt.Toolkit method ids */
    static jmethodID getDefaultToolkitMID;
    static jmethodID getFontMetricsMID;
        static jmethodID insetsMID;

    /* sun.awt.windows.WToolkit ids */
    static jmethodID windowsSettingChangeMID;
    static jmethodID displayChangeMID;

    BOOL m_isDynamicLayoutSet;

    AwtToolkit();
    ~AwtToolkit();

    BOOL Initialize(BOOL localPump);
    BOOL Dispose();

    void SetDynamicLayout(BOOL dynamic);
    BOOL IsDynamicLayoutSet();
    BOOL IsDynamicLayoutSupported();
    BOOL IsDynamicLayoutActive();
    BOOL areExtraMouseButtonsEnabled();
    void setExtraMouseButtonsEnabled(BOOL enable);
    static UINT GetNumberOfButtons();

    INLINE BOOL localPump() { return m_localPump; }
    INLINE BOOL VerifyComponents() { return FALSE; } // TODO: Use new DebugHelper class to set this flag
    INLINE HWND GetHWnd() { return m_toolkitHWnd; }

    INLINE HMODULE GetModuleHandle() { return m_dllHandle; }
    INLINE void SetModuleHandle(HMODULE h) { m_dllHandle = h; }

    INLINE static DWORD MainThread() { return GetInstance().m_mainThreadId; }
    INLINE void VerifyActive() throw (awt_toolkit_shutdown) {
        if (!m_isActive && m_mainThreadId != ::GetCurrentThreadId()) {
            throw awt_toolkit_shutdown();
        }
    }
    INLINE BOOL IsDisposed() { return m_isDisposed; }
    static UINT GetMouseKeyState();
    static void GetKeyboardState(PBYTE keyboardState);

    static ATOM RegisterClass();
    static void UnregisterClass();
    INLINE LRESULT SendMessage(UINT msg, WPARAM wParam=0, LPARAM lParam=0) {
        if (!m_isDisposed) {
            return ::SendMessage(GetHWnd(), msg, wParam, lParam);
        } else {
            return NULL;
        }
    }
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
                                    LPARAM lParam);
    static LRESULT CALLBACK GetMessageFilter(int code, WPARAM wParam,
                                             LPARAM lParam);
    static LRESULT CALLBACK ForegroundIdleFilter(int code, WPARAM wParam,
                                                 LPARAM lParam);
    static LRESULT CALLBACK MouseLowLevelHook(int code, WPARAM wParam,
            LPARAM lParam);

    INLINE static AwtToolkit& GetInstance() { return theInstance; }
    INLINE void SetPeer(JNIEnv *env, jobject wToolkit) {
        AwtToolkit &tk = AwtToolkit::GetInstance();
        if (tk.m_peer != NULL) {
            env->DeleteGlobalRef(tk.m_peer);
        }
        tk.m_peer = (wToolkit != NULL) ? env->NewGlobalRef(wToolkit) : NULL;
    }

    INLINE jobject GetPeer() {
        return m_peer;
    }

    // is this thread the main thread?

    INLINE static BOOL IsMainThread() {
        return GetInstance().m_mainThreadId == ::GetCurrentThreadId();
    }

    // post a message to the message pump thread

    INLINE BOOL PostMessage(UINT msg, WPARAM wp=0, LPARAM lp=0) {
        return ::PostMessage(GetHWnd(), msg, wp, lp);
    }

    // cause the message pump thread to call the function synchronously now!

    INLINE void * InvokeFunction(void*(*ftn)(void)) {
        return (void *)SendMessage(WM_AWT_INVOKE_VOID_METHOD, (WPARAM)ftn, 0);
    }
    INLINE void InvokeFunction(void (*ftn)(void)) {
        InvokeFunction((void*(*)(void))ftn);
    }
    INLINE void * InvokeFunction(void*(*ftn)(void *), void* param) {
        return (void *)SendMessage(WM_AWT_INVOKE_METHOD, (WPARAM)ftn,
                                   (LPARAM)param);
    }
    INLINE void InvokeFunction(void (*ftn)(void *), void* param) {
        InvokeFunction((void*(*)(void*))ftn, param);
    }

    INLINE CriticalSection &GetSyncCS() { return m_Sync; }

    void *SyncCall(void*(*ftn)(void *), void* param);
    void SyncCall(void (*ftn)(void *), void *param);
    void *SyncCall(void *(*ftn)(void));
    void SyncCall(void (*ftn)(void));

    // cause the message pump thread to call the function later ...

    INLINE void InvokeFunctionLater(void (*ftn)(void *), void* param) {
        if (!PostMessage(WM_AWT_INVOKE_METHOD, (WPARAM)ftn, (LPARAM)param)) {
            JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
            JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
        }
    }

   // cause the message pump thread to synchronously synchronize on the handle

    INLINE void WaitForSingleObject(HANDLE handle) {
        SendMessage(WM_AWT_WAIT_FOR_SINGLE_OBJECT, 0, (LPARAM)handle);
    }

    /*
     * Create an AwtXxxx C++ component using a given factory
     */
    typedef void (*ComponentFactory)(void*, void*);
    static void CreateComponent(void* hComponent, void* hParent,
                                ComponentFactory compFactory, BOOL isParentALocalReference=TRUE);

    static void DestroyComponentHWND(HWND hwnd);

    // constants used to PostQuitMessage

    static const int EXIT_ENCLOSING_LOOP;
    static const int EXIT_ALL_ENCLOSING_LOOPS;

    // ...

    void QuitMessageLoop(int status);

    UINT MessageLoop(IDLEPROC lpIdleFunc, PEEKMESSAGEPROC lpPeekMessageFunc);
    BOOL PumpWaitingMessages(PEEKMESSAGEPROC lpPeekMessageFunc);
    void PumpToDestroy(class AwtComponent* p);
    void ProcessMsg(MSG& msg);
    BOOL PreProcessMsg(MSG& msg);
    BOOL PreProcessMouseMsg(class AwtComponent* p, MSG& msg);
    BOOL PreProcessKeyMsg(class AwtComponent* p, MSG& msg);

    /* Create an ID which maps to an AwtObject pointer, such as a menu. */
    UINT CreateCmdID(AwtObject* object);

    // removes cmd id mapping
    void RemoveCmdID(UINT id);

    /* Return the AwtObject associated with its ID. */
    AwtObject* LookupCmdID(UINT id);

    /* Return the current application icon. */
    HICON GetAwtIcon();
    HICON GetAwtIconSm();

    // Calculate a wave-like value out of the integer 'value' and
    // the specified period.
    // The argument 'value' is an integer 0, 1, 2, ... *infinity*.
    //
    // Examples:
    //    Period == 3
    //    Generated sequence: 0 1 2 1 0 .....
    //
    //    Period == 4
    //    Generated sequence: 0 1 2 3 2 1 0 .....
    static inline UINT CalculateWave(UINT value, const UINT period) {
        if (period < 2) {
            return 0;
        }
        // -2 is necessary to avoid repeating extreme values (0 and period-1)
        value %= period * 2 -2;
        if (value >= period) {
            value = period * 2 -2 - value;
        }
        return value;
    }

    HICON GetSecurityWarningIcon(UINT index, UINT w, UINT h);

    /* Turns on/off dialog modality for the system. */
    INLINE AwtDialog* SetModal(AwtDialog* frame) {
        AwtDialog* previousDialog = m_pModalDialog;
        m_pModalDialog = frame;
        return previousDialog;
    };
    INLINE void ResetModal(AwtDialog* oldFrame) { m_pModalDialog = oldFrame; };
    INLINE BOOL IsModal() { return (m_pModalDialog != NULL); };
    INLINE AwtDialog* GetModalDialog(void) { return m_pModalDialog; };

    /* Stops the current message pump (normally a modal dialog pump) */
    INLINE void StopMessagePump() { m_breakOnError = TRUE; }

    /* Debug settings */
    INLINE void SetVerbose(long flag)   { m_verbose = (flag != 0); }
    INLINE void SetVerify(long flag)    { m_verifyComponents = (flag != 0); }
    INLINE void SetBreak(long flag)     { m_breakOnError = (flag != 0); }
    INLINE void SetHeapCheck(long flag);

    static void SetBusy(BOOL busy);

    /* Set and get the default input method Window handler. */
    INLINE void SetInputMethodWindow(HWND inputMethodHWnd) { m_inputMethodHWnd = inputMethodHWnd; }
    INLINE HWND GetInputMethodWindow() { return m_inputMethodHWnd; }

    static VOID CALLBACK PrimaryIdleFunc();
    static VOID CALLBACK SecondaryIdleFunc();
    static BOOL CALLBACK CommonPeekMessageFunc(MSG& msg);
    static BOOL activateKeyboardLayout(HKL hkl);

    HANDLE m_waitEvent;
    DWORD eventNumber;
private:
    HWND CreateToolkitWnd(LPCTSTR name);

    BOOL m_localPump;
    DWORD m_mainThreadId;
    HWND m_toolkitHWnd;
    HWND m_inputMethodHWnd;
    BOOL m_verbose;
    BOOL m_isActive; // set to FALSE at beginning of Dispose
    BOOL m_isDisposed; // set to TRUE at end of Dispose
    BOOL m_areExtraMouseButtonsEnabled;

    BOOL m_vmSignalled; // set to TRUE if QUERYENDSESSION has successfully
                        // raised SIGTERM

    BOOL m_verifyComponents;
    BOOL m_breakOnError;

    BOOL  m_breakMessageLoop;
    UINT  m_messageLoopResult;

    class AwtComponent* m_lastMouseOver;
    BOOL                m_mouseDown;

    HHOOK m_hGetMessageHook;
    HHOOK m_hMouseLLHook;
    UINT_PTR  m_timer;

    class AwtCmdIDList* m_cmdIDs;
    BYTE                m_lastKeyboardState[KB_STATE_SIZE];
    CriticalSection     m_lockKB;

    static AwtToolkit theInstance;

    /* The current modal dialog frame (normally NULL). */
    AwtDialog* m_pModalDialog;

    /* The WToolkit peer instance */
    jobject m_peer;

    HMODULE m_dllHandle;  /* The module handle. */

    CriticalSection m_Sync;

/* track display changes - used by palette-updating code.
   This is a workaround for a windows bug that prevents
   WM_PALETTECHANGED event from occurring immediately after
   a WM_DISPLAYCHANGED event.
  */
private:
    BOOL m_displayChanged;  /* Tracks displayChanged events */
    // 0 means we are not embedded.
    DWORD m_embedderProcessID;

public:
    BOOL HasDisplayChanged() { return m_displayChanged; }
    void ResetDisplayChanged() { m_displayChanged = FALSE; }
    void RegisterEmbedderProcessId(HWND);
    BOOL IsEmbedderProcessId(const DWORD processID) const
    {
        return m_embedderProcessID && (processID == m_embedderProcessID);
    }

 private:
    static JNIEnv *m_env;
    static DWORD m_threadId;
 public:
    static void SetEnv(JNIEnv *env);
    static JNIEnv* GetEnv();

    static BOOL GetScreenInsets(int screenNum, RECT * rect);

    // If the DWM is active, this function uses
    // DwmGetWindowAttribute()/DWMWA_EXTENDED_FRAME_BOUNDS.
    // Otherwise, fall back to regular ::GetWindowRect().
    // See 6711576 for more details.
    static void GetWindowRect(HWND hWnd, LPRECT lpRect);

 private:
    // The window handle of a toplevel window last seen under the mouse cursor.
    // See MouseLowLevelHook() for details.
    HWND m_lastWindowUnderMouse;
 public:
    HWND GetWindowUnderMouse() { return m_lastWindowUnderMouse; }

    void InstallMouseLowLevelHook();
    void UninstallMouseLowLevelHook();


/* AWT preloading (early Toolkit thread start)
 */
public:
    /* Toolkit preload action class.
     * Preload actions should be registered with
     * AwtToolkit::getInstance().GetPreloadThread().AddAction().
     * AwtToolkit thread calls InitImpl method at the beghining
     * and CleanImpl(false) before exiting for all registered actions.
     * If an application provides own Toolkit thread
     * (sun.awt.windows.WToolkit.embeddedInit), the thread calls Clean(true)
     * for each action.
     */
    class PreloadThread;    // forward declaration
    class PreloadAction {
        friend class PreloadThread;
    public:
        PreloadAction() : initThreadId(0), pNext(NULL) {}
        virtual ~PreloadAction() {}

    protected:
        // called by PreloadThread or as result
        // of EnsureInited() call (on Toolkit thread!).
        virtual void InitImpl() = 0;

        // called by PreloadThread (before exiting).
        // reInit == false: normal shutdown;
        // reInit == true: PreloadThread is shutting down due external
        //   Toolkit thread was provided.
        virtual void CleanImpl(bool reInit) = 0;

    public:
        // Initialized the action on the Toolkit thread if not yet initialized.
        bool EnsureInited();

        // returns thread ID which the action was inited on (0 if not inited)
        DWORD GetInitThreadID();

        // Allows to deinitialize action earlier.
        // The method must be called on the Toolkit thread only.
        // returns true on success,
        //         false if the action was inited on other thread.
        bool Clean();

    private:
        unsigned initThreadId;
        // lock for Init/Clean
        CriticalSection initLock;

        // Chain support (for PreloadThread)
        PreloadAction *pNext;   // for action chain used by PreloadThread
        void SetNext(PreloadAction *pNext) { this->pNext = pNext; }
        PreloadAction *GetNext() { return pNext; }

        // wrapper for AwtToolkit::InvokeFunction
        static void InitWrapper(void *param);

        void Init();
        void Clean(bool reInit);

    };

    /** Toolkit preload thread class.
     */
    class PreloadThread {
    public:
        PreloadThread();
        ~PreloadThread();

        // adds action & start the thread if not yet started
        bool AddAction(PreloadAction *pAction);

        // sets termination flag; returns true if the thread is running.
        // wrongThread specifies cause of the termination:
        //   false means termination on the application shutdown;
        // wrongThread is used as reInit parameter for action cleanup.
        bool Terminate(bool wrongThread);
        bool InvokeAndTerminate(void(_cdecl *fn)(void *), void *param);

        // waits for the the thread completion;
        // use the method after Terminate() only if Terminate() returned true
        INLINE void Wait4Finish() {
            ::WaitForSingleObject(hFinished, INFINITE);
        }

        INLINE unsigned GetThreadId() {
            CriticalSection::Lock lock(threadLock);
            return threadId;
        }
        INLINE bool IsWrongThread() {
            CriticalSection::Lock lock(threadLock);
            return wrongThread;
        }
        // returns true if the current thread is "preload" thread
        bool OnPreloadThread();

    private:
        // data access lock
        CriticalSection threadLock;

        // the thread status
        enum Status {
            None = -1,      // initial
            Preloading = 0, // preloading in progress
            RunningToolkit, // Running as Toolkit thread
            Cleaning,       // exited from Toolkit thread proc, cleaning
            Finished        //
        } status;

        // "wrong thread" flag
        bool wrongThread;

        // thread proc (calls (this)param->ThreadProc())
        static unsigned WINAPI StaticThreadProc(void *param);
        unsigned ThreadProc();

        INLINE void AwakeThread() {
            ::SetEvent(hAwake);
        }

        // if threadId != 0 -> we are running
        unsigned threadId;
        // ThreadProc sets the event on exit
        HANDLE hFinished;
        // ThreadProc waits on the event for NewAction/Terminate/InvokeAndTerminate
        HANDLE hAwake;

        // function/param to invoke (InvokeAndTerminate)
        // if execFunc == NULL => just terminate
        void(_cdecl *execFunc)(void *);
        void *execParam;

        // action chain
        PreloadAction *pActionChain;
        PreloadAction *pLastProcessedAction;

        // returns next action in the list (NULL if no more actions)
        PreloadAction* GetNextAction();

    };

    INLINE PreloadThread& GetPreloadThread() { return preloadThread; }

private:
    PreloadThread preloadThread;

};


/*  creates an instance of T and assigns it to the argument, but only if
    the argument is initially NULL. Supposed to be thread-safe.
    returns the new value of the argument. I'm not using volatile here
    as InterlockedCompareExchange ensures volatile semantics
    and acquire/release.
    The function is useful when used with static POD NULL-initialized
    pointers, as they are guaranteed to be NULL before any dynamic
    initialization takes place. This function turns such a pointer
    into a thread-safe singleton, working regardless of dynamic
    initialization order. Destruction problem is not solved,
    we don't need it here.
*/

template<typename T> inline T* SafeCreate(T* &pArg) {
    /*  this implementation has no locks, it just destroys the object if it
        fails to be the first to init. another way would be using a special
        flag pointer value to mark the pointer as "being initialized". */
    T* pTemp = (T*)InterlockedCompareExchangePointer((void**)&pArg, NULL, NULL);
    if (pTemp != NULL) return pTemp;
    T* pNew = new T;
    pTemp = (T*)InterlockedCompareExchangePointer((void**)&pArg, pNew, NULL);
    if (pTemp != NULL) {
        // we failed it - another thread has already initialized pArg
        delete pNew;
        return pTemp;
    } else {
        return pNew;
    }
}

#endif /* AWT_TOOLKIT_H */
