Changeset 99 for trunk/src


Ignore:
Timestamp:
Aug 5, 2009, 3:19:05 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: Implemented widget creation/destruction functions.

Location:
trunk/src/gui/kernel
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/kernel/qapplication_pm.cpp

    r98 r99  
    9191static void releaseAutoCapture();
    9292
    93 static void unregWinClasses();
    94 
    9593extern QCursor *qt_grab_cursor();
    9694
    97 extern "C" MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
     95MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
    9896
    9997class QETWidget : public QWidget                // event translator widget
     
    189187void qt_cleanup()
    190188{
    191     unregWinClasses();
    192189    QPixmapCache::clear();
    193190
     
    224221    return false;
    225222#endif
    226 }
    227 
    228 typedef QSet<QString> WinClassNameHash;
    229 Q_GLOBAL_STATIC(WinClassNameHash, winclassNames)
    230 
    231 // register window class
    232 const QString qt_reg_winclass(QWidget *w)
    233 {
    234     int flags = w->windowFlags();
    235     int type = flags & Qt::WindowType_Mask;
    236 
    237     QString cname;
    238     ULONG style = 0;
    239 
    240     if (type == Qt::Window) {
    241         // this class is for frame window clients when WC_FRAME is used.
    242         cname = QLatin1String("QWindow");
    243         style |= CS_MOVENOTIFY;
    244     } else if (type == Qt::Popup || type == Qt::Tool || type == Qt::ToolTip) {
    245         cname = QLatin1String("QPopup");
    246         // @todo do we really want SAVEBITS here?
    247         style |= CS_SAVEBITS;
    248     } else {
    249         cname = QLatin1String("QWidget");
    250     }
    251 
    252     if (winclassNames()->contains(cname)) // already registered in our list
    253         return cname;
    254 
    255     // QT_EXTRAWINDATASIZE is defined in qwindowdefs_pm.h
    256     WinRegisterClass(0, cname.toLatin1(), QtWndProc, style, QT_EXTRAWINDATASIZE);
    257 
    258     winclassNames()->insert(cname);
    259     return cname;
    260 }
    261 
    262 static void unregWinClasses()
    263 {
    264     // there is no need to unregister private window classes -- it is done
    265     // automatically upon process termination.
    266     winclassNames()->clear();
    267223}
    268224
     
    466422// QtWndProc() receives all messages from the main event loop
    467423
    468 extern "C"
    469424MRESULT EXPENTRY QtWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
     425{
     426    // @todo implement
     427    return FALSE;
     428}
     429
     430PFNWP QtOldFrameProc = 0;
     431
     432MRESULT EXPENTRY QtFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
    470433{
    471434    // @todo implement
  • trunk/src/gui/kernel/qwidget_p.h

    r95 r99  
    6767#endif // Q_WS_WIN
    6868
     69#ifdef Q_WS_PM
     70#include "QtCore/qt_os2.h"
     71#endif
     72
    6973#ifdef Q_WS_X11
    7074#include "QtGui/qx11info_x11.h"
     
    150154    HICON winIconSmall; // internal small Windows icon
    151155#endif
     156#if defined(Q_WS_PM)
     157    HWND fId;
     158#endif
    152159    QRect normalGeometry; // used by showMin/maximized/FullScreen
    153160    QWindowSurface *windowSurface;
     
    460467
    461468    QInputContext *inputContext() const;
     469
     470#if defined(Q_WS_PM)
     471    HWND frameWinId() const
     472    { return maybeTopData() && maybeTopData()->fId != NULLHANDLE ?
     473             maybeTopData()->fId : data.winid; }
     474#endif
    462475
    463476#if defined(Q_WS_QWS)
  • trunk/src/gui/kernel/qwidget_pm.cpp

    r95 r99  
    4848
    4949#include "qapplication.h"
     50#include "qdesktopwidget.h"
    5051
    5152#include "private/qapplication_p.h"
     
    5354#include <qdebug.h>
    5455
     56#define QT_DEBUGWINCREATEDESTROY
     57
    5558QT_BEGIN_NAMESPACE
     59
     60static QWidget *mouseGrb    = 0;
     61static QCursor *mouseGrbCur = 0;
     62static QWidget *keyboardGrb = 0;
    5663
    5764// defined in qapplication_pm.cpp
    5865extern bool qt_nograb();
    59 extern const QString qt_reg_winclass(QWidget *w);
    60 extern "C" MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
     66extern MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
     67extern PFNWP QtOldFrameProc;
     68extern MRESULT EXPENTRY QtFrameProc(HWND, ULONG, MPARAM, MPARAM);
     69
     70typedef QSet<QString> WinClassNameHash;
     71Q_GLOBAL_STATIC(WinClassNameHash, winclassNames)
     72
     73// register window class
     74static const QString qt_reg_winclass(QWidget *w)
     75{
     76    int flags = w->windowFlags();
     77    int type = flags & Qt::WindowType_Mask;
     78
     79    QString cname;
     80    ULONG style = 0;
     81
     82    if (type == Qt::Popup || type == Qt::ToolTip) {
     83        cname = QLatin1String("QPopup");
     84        style |= CS_SAVEBITS;
     85    } else if (w->isWindow()) {
     86        // this class is for top level widgets which are client HWNDs of a
     87        // WC_FRAME parent HWND internally maintaned for them
     88        cname = QLatin1String("QWindow");
     89        style |= CS_MOVENOTIFY;
     90    } else {
     91        cname = QLatin1String("QWidget");
     92    }
     93
     94    if (winclassNames()->contains(cname)) // already registered in our list
     95        return cname;
     96
     97    // QT_EXTRAWINDATASIZE is defined in qwindowdefs_pm.h
     98    WinRegisterClass(0, cname.toLatin1(), QtWndProc, style, QT_EXTRAWINDATASIZE);
     99
     100    winclassNames()->insert(cname);
     101    return cname;
     102
     103    // Note: there is no need to unregister private window classes registered by
     104    // this function -- it is done automatically upon process termination.
     105}
     106
     107/*!
     108 * \internal
     109 * For some unknown reason, PM sends WM_SAVEAPPLICATION to every window
     110 * being destroyed, which makes it indistinguishable from WM_SAVEAPPLICATION
     111 * sent to top level windows during system shutdown. We use our own version of
     112 * WinDestroyWindow() and a special flag (qt_about_to_destroy_wnd) to
     113 * distinguish it in qapplication_pm.cpp.
     114 */
     115static BOOL qt_WinDestroyWindow(HWND hwnd)
     116{
     117#if !defined (QT_NO_SESSIONMANAGER)
     118    qt_about_to_destroy_wnd = true;
     119#endif
     120    BOOL rc = WinDestroyWindow(hwnd);
     121#if !defined (QT_NO_SESSIONMANAGER)
     122    qt_about_to_destroy_wnd = false;
     123#endif
     124    return rc;
     125}
     126
     127static PFNWP QtOldSysMenuProc;
     128static MRESULT EXPENTRY QtSysMenuProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
     129{
     130    if (msg == WM_MENUEND) {
     131        // the pull-down menu is closed, always dismiss the system menu itself
     132        WinPostMsg(hwnd, MM_ENDMENUMODE, MPFROMSHORT(TRUE), 0);
     133    }
     134    return QtOldSysMenuProc(hwnd, msg, mp1, mp2);
     135}
     136
     137static void removeSysMenuAccels(HWND frame)
     138{
     139    HWND sysMenu = WinWindowFromID(frame, FID_SYSMENU);
     140    if (!sysMenu)
     141        return;
     142
     143    SHORT subId = SHORT1FROMMR(WinSendMsg(sysMenu, MM_ITEMIDFROMPOSITION, 0, 0));
     144    if (subId != MIT_ERROR) {
     145        MENUITEM item;
     146        WinSendMsg(sysMenu, MM_QUERYITEM, MPFROM2SHORT(subId, FALSE), MPFROMP(&item));
     147        HWND subMenu = item.hwndSubMenu;
     148        if (subMenu) {
     149            USHORT cnt = SHORT1FROMMR(WinSendMsg(subMenu, MM_QUERYITEMCOUNT, 0, 0));
     150            for (int i = 0; i < cnt; i++) {
     151                USHORT id = SHORT1FROMMR(
     152                    WinSendMsg(subMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(i), 0));
     153                if (id == SC_TASKMANAGER || id == SC_CLOSE) {
     154                    // accels for these entries always work in Qt, skip them
     155                    continue;
     156                }
     157                USHORT len = SHORT1FROMMR(
     158                    WinSendMsg(subMenu, MM_QUERYITEMTEXTLENGTH, MPFROMSHORT(id), 0));
     159                if (len++) {
     160                    char *text = new char[len];
     161                    WinSendMsg(subMenu, MM_QUERYITEMTEXT,
     162                        MPFROM2SHORT(id, len), MPFROMP(text));
     163                    char *tab = strrchr(text, '\t');
     164                    if (tab) {
     165                        *tab = 0;
     166                        WinSendMsg(subMenu, MM_SETITEMTEXT,
     167                            MPFROMSHORT(id), MPFROMP(text));
     168                    }
     169                    delete[] text;
     170                }
     171            }
     172            // sublclass the system menu to leave the menu mode completely
     173            // when the user presses the ESC key. by default, pressing ESC
     174            // while the pull-down menu is showing brings us to the menu bar,
     175            // which is confusing in the case of the system menu, because
     176            // there is only one item on the menu bar, and we cannot see
     177            // that it is active when the frame window has an icon.
     178            PFNWP oldProc = WinSubclassWindow(sysMenu, QtSysMenuProc);
     179            // set QtOldSysMenuProc only once: it must be the same for
     180            // all FID_SYSMENU windows.
     181            if (!QtOldSysMenuProc)
     182                QtOldSysMenuProc = oldProc;
     183        }
     184    }
     185}
    61186
    62187/*****************************************************************************
     
    66191void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
    67192{
    68     // @todo implement
     193    // @todo when window is not zero, it represents an existing (external)
     194    // window handle we should create a QWidget "wrapper" for to incorporate it
     195    // to the Qt widget hierarchy. This functionality isn't really necessary on
     196    // OS/2 at the moment, so it is not currently supported (and the window
     197    // argument is simply ignored). Note that destroyOldWindow only makes
     198    //  sense when window is != 0 so it is also ignored.
     199
     200    Q_ASSERT(window == 0);
     201    Q_UNUSED(destroyOldWindow);
     202
     203    Q_Q(QWidget);
     204    static int sw = -1, sh = -1;
     205
     206    Qt::WindowType type = q->windowType();
     207    Qt::WindowFlags flags = data.window_flags;
     208
     209    bool topLevel = q->isWindow();
     210    bool popup = (type == Qt::Popup);
     211    bool dialog = (type == Qt::Dialog
     212                   || type == Qt::Sheet
     213                   || (flags & Qt::MSWindowsFixedSizeDialogHint));
     214    bool desktop = (type == Qt::Desktop);
     215    bool tool = (type == Qt::Tool || type == Qt::Drawer);
     216
     217    WId id;
     218
     219    QByteArray className = qt_reg_winclass(q).toLatin1();
     220
     221    // @todo WindowStaysOnTopHint is ignored for now (does nothing)
     222    if (popup)
     223        flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
     224
     225    if (sw < 0) { // get the screen size
     226        sw = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
     227        sh = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
     228    }
     229
     230    if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget
     231        popup = false; // force this flags off
     232        // @todo use WinGetMaxPositionto take into account such things as XCenter?
     233        data.crect.setRect(0, 0, sw, sh);
     234    }
     235
     236    QByteArray title;
     237    ULONG style = 0;
     238    ULONG fId = 0, fStyle = 0, fcFlags = 0;
     239
     240    if (!desktop) {
     241        // @todo testing for Qt::WA_PaintUnclipped is commented out because it
     242        // is said that it causes some problems on Win32 and we also saw the
     243        // problems with this line enabled in Qt3 on OS/2 in QT_PM_NO_WIDGETMASK
     244        // mode (terrible flicker in QFileDialog because QSplitter used there
     245        // sets WA_PaintUnclipped). This however doesn't make a big difference
     246        // now since we don't support QT_PM_NO_WIDGETMASK anymore (read below
     247        // about clipping) and is left here just to show where WA_PaintUnclipped
     248        // was originally intended to be used.
     249#if 0
     250        if (!testAttribute(Qt::WA_PaintUnclipped))
     251#endif
     252        {
     253            // We don't use WS_CLIPSIBLINGS and WS_CLIPCHILDREN because when these
     254            // styles are set and the child (sibling) window has a non-NULL clip region,
     255            // PM still continues to exclude the entire child's rectangle from the
     256            // parent window's update region, ignoring its clip region. As a result,
     257            // areas outside the clip region are left unpainted. Instead, we correct
     258            // the update region of the window ourselves, on every WM_PAINT event.
     259            // Note: for top-level widgets, we specify WS_CLIPSIBLINGS anyway to let
     260            // the system do correct clipping for us (qt_WinProcessWindowObstacles()
     261            // relies on this). It's ok because top-level widgets cannot be non-
     262            // rectangular and therefore don't require our magic clipping procedure.
     263            if (topLevel)
     264                style |= WS_CLIPSIBLINGS;
     265        }
     266
     267        // for all top-level windows except popups we create a WC_FRAME
     268        // as a parent and owner.
     269        if (topLevel && !popup) {
     270            if ((type == Qt::Window || dialog || tool)) {
     271                if (!(flags & Qt::FramelessWindowHint)) {
     272                    if (flags & Qt::MSWindowsFixedSizeDialogHint) {
     273                        fcFlags |= FCF_DLGBORDER;
     274                    } else if (tool) {
     275                        fcFlags |= FCF_BORDER;
     276                    } else {
     277                        fcFlags |= FCF_SIZEBORDER;
     278                    }
     279                }
     280                if (flags & Qt::WindowTitleHint)
     281                    fcFlags |= FCF_TITLEBAR;
     282                if (flags & Qt::WindowSystemMenuHint)
     283                    fcFlags |= FCF_SYSMENU | FCF_CLOSEBUTTON;
     284                if (flags & Qt::WindowMinimizeButtonHint)
     285                    fcFlags |= FCF_MINBUTTON;
     286                if (flags & Qt::WindowMaximizeButtonHint)
     287                    fcFlags |= FCF_MAXBUTTON;
     288            } else {
     289                fcFlags |= FCF_BORDER;
     290            }
     291
     292            fStyle |= FS_NOMOVEWITHOWNER | FS_NOBYTEALIGN;
     293            fStyle |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
     294        }
     295    }
     296
     297    if (flags & Qt::WindowTitleHint) {
     298        title = topLevel ? qAppName().toLocal8Bit() : q->objectName().toLocal8Bit();
     299    }
     300
     301    // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
     302    // qapplication_pm.cpp. We switch it off temporarily to avoid move
     303    // and resize events during creation
     304    q->setAttribute(Qt::WA_WState_Created, false);
     305
     306    if (desktop) { // desktop widget
     307        id = WinQueryDesktopWindow(0, 0);
     308        // @todo commented out on Win32 too
     309//      QWidget *otherDesktop = QWidget::find(id); // is there another desktop?
     310//      if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
     311//          otherDesktop->d_func()->setWinId(0); // remove id from widget mapper
     312//          setWinId(id); // make sure otherDesktop is found first
     313//          otherDesktop->d_func()->setWinId(id);
     314//      } else {
     315            setWinId(id);
     316//      }
     317    } else if (topLevel) {
     318        // create top-level widget
     319        if (!popup) {
     320            HWND ownerw = NULLHANDLE;
     321            QWidget *parent = q->parentWidget();
     322
     323QWidgetPrivate *ppp;
     324ppp->frameWinId();
     325            if (parent && !(parent->windowType() == Qt::Desktop))
     326                ownerw = parent->window()->d_func()->frameWinId();
     327            // create WC_FRAME
     328            FRAMECDATA fcData;
     329            fcData.cb = sizeof(FRAMECDATA);
     330            fcData.flCreateFlags = fcFlags;
     331            fcData.hmodResources = NULL;
     332            fcData.idResources = 0;
     333            // check whether a default icon is present in .EXE and use it if so
     334            ULONG sz = 0;
     335            if (DosQueryResourceSize(NULL, RT_POINTER, 1, &sz) == 0) {
     336                fcData.flCreateFlags |= FCF_ICON;
     337                fcData.idResources = 1;
     338            }
     339#if defined(QT_DEBUGWINCREATEDESTROY)
     340            qDebug("|Creating top level window (frame) [%s/%s]:\n"
     341                   "|  owner = %08lX\n"
     342                   "|  title = '%s'\n"
     343                   "|  style = %08lX\n"
     344                   "|  fcFlags = %08lX",
     345                   q->objectName().toLocal8Bit().constData(),
     346                   q->metaObject()->className(),
     347                   ownerw, title.constData(), fStyle, fcFlags);
     348#endif
     349            fId = WinCreateWindow(HWND_DESKTOP, WC_FRAME, title, fStyle,
     350                                  0, 0, 0, 0, ownerw, HWND_TOP, 0,
     351                                  &fcData, NULL);
     352#if defined(QT_DEBUGWINCREATEDESTROY)
     353            qDebug("|  hwnd = %08lX", fId);
     354#endif
     355            if (fId == NULLHANDLE)
     356                qWarning("QWidget::create(): WinCreateWindow(WC_FRAME) "
     357                         "failed with 0x%08lX", WinGetLastError(0));
     358
     359            PFNWP oldProc = WinSubclassWindow(fId, QtFrameProc);
     360            // remember QtOldFrameProc only once: it's the same for
     361            // all WC_FRAME windows.
     362            if (!QtOldFrameProc)
     363                QtOldFrameProc = oldProc;
     364
     365            removeSysMenuAccels(fId);
     366
     367            // create client window
     368#if defined(QT_DEBUGWINCREATEDESTROY)
     369            qDebug("|Creating top level window (client) [%s/%s]:\n"
     370                   "|  owner & parent = %08lX\n"
     371                   "|  class = '%s'\n"
     372                   "|  title = '%s'\n"
     373                   "|  style = %08lX",
     374                   q->objectName().toLocal8Bit().constData(),
     375                   q->metaObject()->className(),
     376                   fId, className.constData(), title.constData(), style);
     377#endif
     378            // note that we place the client on top (HWND_TOP) to exclude other
     379            // frame controls from being analyzed in qt_WinProcessWindowObstacles
     380            id = WinCreateWindow(fId, className, title, style, 0, 0, 0, 0,
     381                                 fId, HWND_TOP, FID_CLIENT, NULL, NULL);
     382        } else {
     383#if defined(QT_DEBUGWINCREATEDESTROY)
     384            qDebug("|Creating top level window (popup) [%s/%s]:\n"
     385                   "|  class = '%s'\n"
     386                   "|  title = '%s'\n"
     387                   "|  style = %08lX",
     388                   q->objectName().toLocal8Bit().constData(),
     389                   q->metaObject()->className(),
     390                   className.constData(), title.constData(), style);
     391#endif
     392            id = WinCreateWindow(HWND_DESKTOP, className, title, style,
     393                                 0, 0, 0, 0, NULLHANDLE, HWND_TOP, 0, NULL, NULL);
     394        }
     395#if defined(QT_DEBUGWINCREATEDESTROY)
     396        qDebug("|  hwnd = %08lX", id);
     397#endif
     398        if (id == NULLHANDLE)
     399            qWarning("QWidget::create(): WinCreateWindow "
     400                     "failed with 0x%08lX", WinGetLastError(0));
     401        setWinId(id);
     402
     403        // it isn't mentioned in PMREF that PM is obliged to initialize window
     404        // data with zeroes (although seems to), so do it ourselves
     405        for (LONG i = 0; i <= (LONG) (QT_EXTRAWINDATASIZE - 4); i += 4)
     406            WinSetWindowULong(id, i, 0);
     407
     408        SWP swp;
     409        // Get the default window position and size. Note that when the
     410        // FS_SHELLPOSITION flag is specified during WC_FRAME window
     411        // creation its size and position remains zero until it is shown
     412        // for the first time. So, we don't use FS_SHELLPOSITION but emulate
     413        // its functionality here.
     414        WinQueryTaskSizePos(0, 0, &swp);
     415
     416        //update position & initial size of POPUP window
     417        const bool wasMoved = q->testAttribute(Qt::WA_Moved);
     418        const bool wasResized = q->testAttribute(Qt::WA_Resized);
     419        const bool isVisibleOnScreen = !q->testAttribute(Qt::WA_DontShowOnScreen);
     420        if (popup && initializeWindow && isVisibleOnScreen) {
     421            if (!q->testAttribute(Qt::WA_Resized)) {
     422                swp.cx = sw / 2;
     423                swp.cy = 4 * sh / 10;
     424            }
     425            if (!wasMoved) {
     426                swp.x = sw / 2 - swp.cx / 2;
     427                swp.y = sh / 2 - swp.cy / 2;
     428            }
     429        }
     430
     431        ULONG fl = SWP_SIZE | SWP_MOVE;
     432        HWND insertBehind = NULLHANDLE;
     433        if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) {
     434            insertBehind = HWND_TOP;
     435            fl |= SWP_ZORDER;
     436            if (flags & Qt::WindowStaysOnBottomHint)
     437                qWarning() << "QWidget: Incompatible window flags: the window "
     438                              "can't be on top and on bottom at the same time";
     439        } else if (flags & Qt::WindowStaysOnBottomHint) {
     440            insertBehind = HWND_BOTTOM;
     441            fl |= SWP_ZORDER;
     442        }
     443        WinSetWindowPos(popup ? id : fId, insertBehind,
     444                        swp.x, swp.y, swp.cx, swp.cy, fl);
     445
     446        if (!popup) {
     447            QTLWExtra *top = topData();
     448            top->fId = fId;
     449            WinQueryWindowPos(fId, &swp);
     450            SWP cswp;
     451            WinQueryWindowPos(id, &cswp);
     452            // flip y coordinates
     453            swp.y = sh - (swp.y + swp.cy);
     454            cswp.y = swp.cy - (cswp.y + cswp.cy);
     455            // store frame dimensions
     456            QRect &fs = top->frameStrut;
     457            fs.setCoords(cswp.x, cswp.y, swp.cx - cswp.x - cswp.cx,
     458                                         swp.cy - cswp.y - cswp.cy);
     459            data.fstrut_dirty = false;
     460            if (wasMoved || wasResized) {
     461                // resize & move if necessary (we couldn't do it earlier
     462                // because we didn't know the frame dimensions yet)
     463                if (wasMoved) {
     464                    swp.x = data.crect.left() - fs.left();
     465                    swp.y = data.crect.top() - fs.top();
     466                }
     467                if (wasResized) {
     468                    swp.cx = data.crect.width() + fs.left() + fs.right();
     469                    swp.cy = data.crect.height() + fs.top() + fs.bottom();
     470                }
     471                // flip y coordinate
     472                swp.y = sh - (swp.y + swp.cy);
     473                WinSetWindowPos(fId, NULLHANDLE, swp.x, swp.y, swp.cx, swp.cy,
     474                                SWP_SIZE | SWP_MOVE);
     475            }
     476        }
     477
     478        if (!popup || (initializeWindow && isVisibleOnScreen)) {
     479            // fetch the actual geometry
     480            WinQueryWindowPos(popup ? id : fId, &swp);
     481            // flip y coordinate
     482            swp.y = sh - (swp.y + swp.cy);
     483            if (popup) {
     484                data.crect.setRect(swp.x, swp.y, swp.cx, swp.cy);
     485            } else {
     486                const QRect &fs = topData()->frameStrut;
     487                data.crect.setRect(swp.x + fs.left(), swp.y + fs.top(),
     488                                   swp.cx - fs.left() - fs.right(),
     489                                   swp.cy - fs.top() - fs.bottom());
     490            }
     491        }
     492    } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) {
     493        // create child widget
     494        Q_ASSERT(q->parentWidget());
     495        HWND parentw = q->parentWidget()->effectiveWinId();
     496
     497#if defined(QT_DEBUGWINCREATEDESTROY)
     498        qDebug("|Creating child window [%s/%s]:\n"
     499               "|  owner & parent = %08lX\n"
     500               "|  class = '%s'\n"
     501               "|  title = '%s'\n"
     502               "|  style = %08lX",
     503               q->objectName().toLocal8Bit().constData(),
     504               q->metaObject()->className(),
     505               parentw, className.constData(), title.constData(), style);
     506#endif
     507        id = WinCreateWindow(parentw, className, title, style,
     508                             data.crect.left(),
     509                             // flip y coordinate
     510                             q->parentWidget()->height() - data.crect.bottom() - 1,
     511                             data.crect.width(), data.crect.height(),
     512                             parentw, HWND_TOP, 0, NULL, NULL);
     513#if defined(QT_DEBUGWINCREATEDESTROY)
     514        qDebug("|  hwnd = %08lX", id);
     515#endif
     516        if (id == NULLHANDLE)
     517            qWarning("QWidget::create(): WinCreateWindow "
     518                     "failed with 0x%08lX", WinGetLastError(0));
     519        setWinId(id);
     520    }
     521
     522    if (desktop) {
     523        q->setAttribute(Qt::WA_WState_Visible);
     524    }
     525
     526    q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
     527
     528    hd = 0; // no presentation space
     529
     530    if (extra && !extra->mask.isEmpty())
     531        setMask_sys(extra->mask);
     532
     533    if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0)) {
     534        q->setAttribute(Qt::WA_OutsideWSRange, true);
     535    }
     536
     537    if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
     538        Q_ASSERT(q->internalWinId() != NULLHANDLE);
     539        WinShowWindow(q->internalWinId(), TRUE);
     540    }
    69541}
    70542
    71543void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
    72544{
    73     // @todo implement
     545    Q_D(QWidget);
     546    if (!isWindow() && parentWidget())
     547        parentWidget()->d_func()->invalidateBuffer(geometry());
     548    d->deactivateWidgetCleanup();
     549    if (testAttribute(Qt::WA_WState_Created)) {
     550        setAttribute(Qt::WA_WState_Created, false);
     551        for(int i = 0; i < d->children.size(); ++i) { // destroy all widget children
     552            register QObject *obj = d->children.at(i);
     553            if (obj->isWidgetType())
     554                ((QWidget*)obj)->destroy(destroySubWindows,
     555                                         destroySubWindows);
     556        }
     557        if (mouseGrb == this)
     558            releaseMouse();
     559        if (keyboardGrb == this)
     560            releaseKeyboard();
     561        if (testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal
     562            QApplicationPrivate::leaveModal(this);
     563        else if ((windowType() == Qt::Popup))
     564            qApp->d_func()->closePopup(this);
     565        if (destroyWindow && !(windowType() == Qt::Desktop) &&
     566            internalWinId() != NULLHANDLE) {
     567            HWND id = internalWinId();
     568            if (isWindow() && !(windowType() == Qt::Popup)) {
     569                // extra data including extra->topextra has been already
     570                // deleted at this point by deleteExtra() and therefore
     571                // calling frameWinId() is useless -- it will return the
     572                // client window handle. Use WinQueryWindow() instead.
     573                id = WinQueryWindow(id, QW_PARENT);
     574                Q_ASSERT(id != NULLHANDLE);
     575            }
     576#if defined(QT_DEBUGWINCREATEDESTROY)
     577            qDebug("|Destroying window [%s/%s]:\n"
     578                   "|  hwnd = %08lX",
     579                   objectName().toLocal8Bit().constData(),
     580                   metaObject()->className(), id);
     581#endif
     582
     583            qt_WinDestroyWindow(id);
     584        }
     585        d->setWinId(0);
     586    }
    74587}
    75588
     
    250763void QWidgetPrivate::createTLSysExtra()
    251764{
    252     // @todo implement
     765    extra->topextra->fId = NULLHANDLE;
    253766}
    254767
    255768void QWidgetPrivate::deleteTLSysExtra()
    256769{
    257     // @todo implement
     770    // Note: extra->topextra->fId is cleaned up in QWidget::destroy()
    258771}
    259772
     
    270783void QWidgetPrivate::updateFrameStrut()
    271784{
    272     // @todo implement
     785    Q_Q(QWidget);
     786
     787    if (!q->testAttribute(Qt::WA_WState_Created))
     788        return;
     789
     790    if (q->internalWinId() == NULLHANDLE) {
     791        data.fstrut_dirty = false;
     792        return;
     793    }
     794
     795    QTLWExtra *top = maybeTopData();
     796    if (!top || top->fId == NULLHANDLE) {
     797        data.fstrut_dirty = false;
     798        return;
     799    }
     800
     801    // this widget has WC_FRAME
     802    SWP swp;
     803    WinQueryWindowPos(top->fId, &swp);
     804    SWP cswp;
     805    WinQueryWindowPos(data.winid, &cswp);
     806    // flip y coordinates
     807    swp.y = QApplication::desktop()->height() - (swp.y + swp.cy);
     808    cswp.y = swp.cy - (cswp.y + cswp.cy);
     809    QRect &fs = top->frameStrut;
     810    fs.setCoords(cswp.x, cswp.y, swp.cx - cswp.x - cswp.cx,
     811                                 swp.cy - cswp.y - cswp.cy);
     812    // @todo need this??
     813    //data.crect.setRect(swp.x + cswp.x, swp.y + cswp.y, cswp.cx, cswp.cy);
     814
     815    data.fstrut_dirty = false;
    273816}
    274817
Note: See TracChangeset for help on using the changeset viewer.