// -----------------------------------------------------------------------------------
// Large chunks of this file are taken straight from the qwidget_p.h file in Qt4
//
// Specifically, these structures and classes must be kept in sync with Qt4:
// QWidgetBackingStoreTracker
// QTLWExtra
// QWExtra
// The same applies to the implementations defined in tqwidget.cpp
//
// Enjoy!
// -----------------------------------------------------------------------------------

#ifndef QWIDGET_P_H
#define QWIDGET_P_H

#include <Qt/qpointer.h>
#include <Qt/qset.h>

// Extra QWidget data
//  - to minimize memory usage for members that are seldom used.
//  - top-level widgets have extra extra data to reduce cost further
#if defined(Q_WS_QWS)
class QWSManager;
#endif
#if defined(Q_WS_MAC)
class QCoreGraphicsPaintEnginePrivate;
#endif
class QPaintEngine;
class QPixmap;
class QWidgetBackingStore;
class QGraphicsProxyWidget;
class QWidgetItemV2;

class Q_AUTOTEST_EXPORT QWidgetBackingStoreTracker
{

public:
    QWidgetBackingStoreTracker();
    ~QWidgetBackingStoreTracker();

    void create(QWidget *tlw);
    void destroy();

    void registerWidget(QWidget *w);
    void unregisterWidget(QWidget *w);

    inline QWidgetBackingStore* data()
    {
        return m_ptr;
    }

    inline QWidgetBackingStore* operator->()
    {
        return m_ptr;
    }

    inline QWidgetBackingStore& operator*()
    {
        return *m_ptr;
    }

    inline operator bool() const
    {
        return (0 != m_ptr);
    }

private:
    Q_DISABLE_COPY(QWidgetBackingStoreTracker)

private:
    QWidgetBackingStore* m_ptr;
    QSet<QWidget *> m_widgets;
};

struct QTLWExtra {
    // *************************** Cross-platform variables *****************************

    // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
    QIcon *icon; // widget icon
    QPixmap *iconPixmap;
    QWidgetBackingStoreTracker backingStore;
    QWindowSurface *windowSurface;
    QPainter *sharedPainter;

    // Implicit pointers (shared_null).
    QString caption; // widget caption
    QString iconText; // widget icon text
    QString role; // widget role
    QString filePath; // widget file path

    // Other variables.
    short incw, inch; // size increments
    short basew, baseh; // base sizes
     // frame strut, don't use these directly, use QWidgetPrivate::frameStrut() instead.
    QRect frameStrut;
    QRect normalGeometry; // used by showMin/maximized/FullScreen
    Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen

    // *************************** Cross-platform bit fields ****************************
    uint opacity : 8;
    uint posFromMove : 1;
    uint sizeAdjusted : 1;
    uint inTopLevelResize : 1;
    uint inRepaint : 1;
    uint embedded : 1;

    // *************************** Platform specific values (bit fields first) **********
#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
    uint spont_unmapped: 1; // window was spontaneously unmapped
    uint dnd : 1; // DND properties installed
    uint validWMState : 1; // is WM_STATE valid?
    uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet
    WId parentWinId; // parent window Id (valid after reparenting)
    WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom
    QPoint fullScreenOffset;
#ifndef QT_NO_XSYNC
    WId syncUpdateCounter;
    ulong syncRequestTimestamp;
    qint32 newCounterValueHi;
    quint32 newCounterValueLo;
#endif
#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
    uint hotkeyRegistered: 1; // Hot key from the STARTUPINFO has been registered.
    HICON winIconBig; // internal big Windows icon
    HICON winIconSmall; // internal small Windows icon
#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
    uint resizer : 4;
    uint isSetGeometry : 1;
    uint isMove : 1;
    quint32 wattr;
    quint32 wclass;
    WindowGroupRef group;
    IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys.
    quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys()
#ifdef QT_MAC_USE_COCOA
    // This value is just to make sure we maximize and restore to the right location, yet we allow apps to be maximized and
    // manually resized.
    // The name is misleading, since this is set when maximizing the window. It is a hint to saveGeometry(..) to record the
    // starting position as 0,0 instead of the normal starting position.
    bool wasMaximized;
#endif // QT_MAC_USE_COCOA

#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
#ifndef QT_NO_QWS_MANAGER
    QWSManager *qwsManager;
#endif
#elif defined(Q_OS_SYMBIAN)
    uint inExpose : 1; // Prevents drawing recursion
#endif
};

struct QWExtra {
    // *************************** Cross-platform variables *****************************

    // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
    void *glContext; // if the widget is hijacked by QGLWindowSurface
    QTLWExtra *topextra; // only useful for TLWs
#ifndef QT_NO_GRAPHICSVIEW
    QGraphicsProxyWidget *proxyWidget; // if the widget is embedded
#endif
#ifndef QT_NO_CURSOR
    QCursor *curs;
#endif
    QPointer<QStyle> style;
    QPointer<QWidget> focus_proxy;

    // Implicit pointers (shared_empty/shared_null).
    QRegion mask; // widget mask
    QString styleSheet;

    // Other variables.
    qint32 minw;
    qint32 minh; // minimum size
    qint32 maxw;
    qint32 maxh; // maximum size
    quint16 customDpiX;
    quint16 customDpiY;
    QSize staticContentsSize;

    // *************************** Cross-platform bit fields ****************************
    uint explicitMinSize : 2;
    uint explicitMaxSize : 2;
    uint autoFillBackground : 1;
    uint nativeChildrenForced : 1;
    uint inRenderWithPainter : 1;
    uint hasMask : 1;

    // *************************** Platform specific values (bit fields first) **********
#if defined(Q_WS_WIN) // <----------------------------------------------------------- WIN
#ifndef QT_NO_DRAGANDDROP
    QOleDropTarget *dropTarget; // drop target
    QList<QPointer<QWidget> > oleDropWidgets;
#endif
#elif defined(Q_WS_X11) // <--------------------------------------------------------- X11
    uint compress_events : 1;
    WId xDndProxy; // XDND forwarding to embedded windows
#elif defined(Q_WS_MAC) // <------------------------------------------------------ MAC
#ifdef QT_MAC_USE_COCOA
    // Cocoa Mask stuff
    QImage maskBits;
    CGImageRef imageMask;
#endif
#elif defined(Q_OS_SYMBIAN) // <----------------------------------------------------- Symbian
    uint activated : 1; // RWindowBase::Activated has been called

    /**
     * If this bit is set, each native widget receives the Q_SIGNALS from the
     * Symbian control immediately before and immediately after draw ops are
     * sent to the window server for this control:
     *      void beginNativePaintEvent(const QRect &paintRect);
     *      void endNativePaintEvent(const QRect &paintRect);
     */
    uint receiveNativePaintEvents : 1;

    /**
     * Defines the behaviour of QSymbianControl::Draw.
     */
    enum NativePaintMode {
        /**
         * Normal drawing mode: blits the required region of the backing store
         * via WSERV.
         */
        Blit,

        /**
         * Disable drawing for this widget.
         */
        Disable,

        /**
         * Paint zeros into the WSERV framebuffer, using BitGDI APIs.  For windows
         * with an EColor16MU display mode, zero is written only into the R, G and B
         * channels of the pixel.
         */
        ZeroFill,

        Default = Blit
    };

    NativePaintMode nativePaintMode;

#endif
};

class Q_GUI_EXPORT QWidgetPrivate
{
//     Q_DECLARE_PUBLIC(QWidget)

public:
    // *************************** Cross-platform ***************************************
    enum DrawWidgetFlags {
        DrawAsRoot = 0x01,
        DrawPaintOnScreen = 0x02,
        DrawRecursive = 0x04,
        DrawInvisible = 0x08,
        DontSubtractOpaqueChildren = 0x10,
        DontSetCompositionMode = 0x20,
        DontDrawOpaqueChildren = 0x40
    };

    enum CloseMode {
        CloseNoEvent,
        CloseWithEvent,
        CloseWithSpontaneousEvent
    };

    enum Direction {
        DirectionNorth = 0x01,
        DirectionEast = 0x10,
        DirectionSouth = 0x02,
        DirectionWest = 0x20
    };

    // Functions.
    explicit QWidgetPrivate(int version);
    ~QWidgetPrivate();

    QWExtra *extraData() const;
    QTLWExtra *topData() const;
    QTLWExtra *maybeTopData() const;
    QPainter *sharedPainter() const;
    void setSharedPainter(QPainter *painter);
    QWidgetBackingStore *maybeBackingStore() const;
    void init(QWidget *desktopWidget, Qt::WindowFlags f);
    void create_sys(WId window, bool initializeWindow, bool destroyOldWindow);
    void createRecursively();
    void createWinId(WId id = 0);

    void createTLExtra();
    void createExtra();
    void deleteExtra();
    void createSysExtra();
    void deleteSysExtra();
    void createTLSysExtra();
    void deleteTLSysExtra();
    void updateSystemBackground();
    void propagatePaletteChange();

    // Variables.
    // Regular pointers (keep them together to avoid gaps on 64 bit architectures).
    QWExtra *extra;
    QWidget *focus_next;
    QWidget *focus_prev;
    QWidget *focus_child;
    QLayout *layout;
    QRegion *needsFlush;
    QPaintDevice *redirectDev;
    QWidgetItemV2 *widgetItem;
    QPaintEngine *extraPaintEngine;
    mutable const QMetaObject *polished;
    QGraphicsEffect *graphicsEffect;
    // All widgets are added into the allWidgets set. Once
    // they receive a window id they are also added to the mapper.
    // This should just ensure that all widgets are deleted by QApplication
    static QWidgetMapper *mapper;
};

inline QWExtra *QWidgetPrivate::extraData() const
{
    return extra;
}

inline QTLWExtra *QWidgetPrivate::topData() const
{
    const_cast<QWidgetPrivate *>(this)->createTLExtra();
    return extra->topextra;
}

inline QTLWExtra *QWidgetPrivate::maybeTopData() const
{
    return extra ? extra->topextra : 0;
}

#endif // QWIDGET_P_H