Changeset 116 for trunk/src/gui/kernel


Ignore:
Timestamp:
Aug 17, 2009, 7:09:10 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: Implemented size/move event translation.

File:
1 edited

Legend:

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

    r114 r116  
    5656
    5757#include "private/qeventdispatcher_pm_p.h"
     58
    5859
    5960#include "qwidget_p.h"
     
    105106
    106107extern void qt_WinQueryClipRegionOrRect(HWND hwnd, HRGN hrgn); // qwidget_pm.cpp
     108
     109
    107110
    108111MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
     
    132135//  inline void showChildren(bool spontaneous) { d_func()->showChildren(spontaneous); }
    133136//  inline void hideChildren(bool spontaneous) { d_func()->hideChildren(spontaneous); }
    134     inline void validateObstacles() { d_func()->validateObstacles(); }
     137  inline void validateObstacles() { d_func()->validateObstacles(); }
    135138//  inline uint testWindowState(uint teststate){ return dataPtr()->window_state & teststate; }
    136139//  inline void forceUpdate() {
     
    14471450    // qwidget_pm.cpp), we have to validate areas that intersect with our
    14481451    // children and siblings, taking their clip regions into account.
    1449     validateObstacles();
     1452    validateObstacles();
    14501453
    14511454    Q_ASSERT(testAttribute(Qt::WA_WState_Created));
     
    14631466
    14641467    // @todo not sure we need it
    1465 //  const QRegion dirtyInBackingStore(qt_dirtyRegion(this));
    1466 //  // Make sure the invalidated region contains the region we're about to repaint.
    1467 //  // BeginPaint will set the clip to the invalidated region and it is impossible
    1468 //  // to enlarge it afterwards (only shrink it). Using GetDCEx is not suffient
    1469 //  // as it may return an invalid context (especially on Windows Vista).
    1470 //  if (!dirtyInBackingStore.isEmpty())
    1471 //      InvalidateRgn(internalWinId(), dirtyInBackingStore.handle(), false);
     1468    const QRegion dirtyInBackingStore(qt_dirtyRegion(this));
     1469    // Make sure the invalidated region contains the region we're about to repaint.
     1470    // BeginPaint will set the clip to the invalidated region and it is impossible
     1471    // to enlarge it afterwards (only shrink it).
     1472    if (!dirtyInBackingStore.isEmpty())
     1473      WinInvalidateRegion(internalWinId(), dirtyInBackingStore.handle(), FALSE);
    14721474
    14731475    RECTL rcl;
     
    14751477
    14761478#if 1
    1477     qDebug("WM_PAINT: [%s] %ld,%ld:%ld,%ld",
     1479    qDebug("WM_PAINT: [%s] ",
    14781480           QWidgetPrivate::name(this).constData(),
    1479            rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop);
     1481           rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop);
    14801482#endif
    14811483
     
    14891491    }
    14901492
    1491     if (WinQueryClipRegion( internalWinId(), 0) != QCRGN_NO_CLIP_REGION) {
    1492         // Correct the update region by intersecting it with the clip
    1493         // region (PM doesn't do that itself). It is necessary
    1494         // to have a correct QRegion in QPaintEvent.
    1495         HRGN hcrgn = GpiCreateRegion(displayPS, 0, NULL);
    1496         WinQueryClipRegion(internalWinId(), hcrgn);
    1497         GpiCombineRegion(displayPS, hrgn, hrgn, hcrgn, CRGN_AND);
    1498         GpiDestroyRegion(displayPS, hcrgn);
    1499     }
    1500 
    15011493    // flip y coordinate
    15021494    rcl.yBottom = height() - (rcl.yBottom + 1);
    15031495    rcl.yTop = height() - (rcl.yTop + 1);
    15041496
    1505     const QRect updateRect(QPoint(rcl.xLeft, rcl.yBottom),
    1506                            QPoint(rcl.xRight, rcl.yTop));
     1497    // note: right top point is exlusive in rcl
     1498    QRect updRect(QPoint(rcl.xLeft, rcl.yTop + 1),
     1499                  QPoint(rcl.xRight - 1, rcl.yBottom));
    15071500
    15081501    // Mapping region from system to qt (32 bit) coordinate system.
    1509     // @todo use hrgn here once we implement QRegion<->HRGN relationship
    1510     d_func()->syncBackingStore(updateRect.translated(data->wrect.topLeft()));
     1502    updRect.translate(data->wrect.topLeft());
     1503#if 1
     1504    qDebug("WM_PAINT: [%s] update=%d,%d/%d,%d",
     1505           QWidgetPrivate::name(this).constData(),
     1506           updRect.x(), updRect.y(), updRect.width(), updRect.height());
     1507#endif
     1508    // @todo use hrgn here converted to QRegion?
     1509    d_func()->syncBackingStore(updRect);
    15111510
    15121511    WinEndPaint(d_func()->hd);
    15131512    d_func()->hd = NULLHANDLE;
     1513
     1514
     1515
     1516
    15141517
    15151518    return true;
     
    15221525bool QETWidget::translateConfigEvent(const QMSG &qmsg)
    15231526{
    1524     // @todo implement
    1525     return false;
     1527    if (!testAttribute(Qt::WA_WState_Created)) // in QWidget::create()
     1528        return true;
     1529
     1530    if (testAttribute(Qt::WA_WState_ConfigPending)) {
     1531        // it's possible that we're trying to set the frame size smaller
     1532        // than it possible for WC_FRAME in QWidget::setGeometry_sys().
     1533        // here we correct this (crect there is set before WinSetWindowPos()
     1534        // that sends WM_SIZE).
     1535        QSize newSize(SHORT1FROMMP(qmsg.mp2), SHORT2FROMMP(qmsg.mp2));
     1536        if (qmsg.msg == WM_SIZE && size() != newSize)
     1537            data->crect.setSize(newSize);
     1538        return true;
     1539    }
     1540
     1541    if (testAttribute(Qt::WA_DontShowOnScreen))
     1542        return true;
     1543    // @todo check if this is actually called for !isWindow() widget
     1544//  if (!isWindow())
     1545//      return true;
     1546
     1547    setAttribute(Qt::WA_WState_ConfigPending); // set config flag
     1548
     1549    HWND fId = NULLHANDLE;
     1550    ULONG fStyle = 0;
     1551    if (isWindow()) {
     1552        fId = d_func()->frameWinId();
     1553        fStyle = WinQueryWindowULong(fId, QWL_STYLE);
     1554    }
     1555
     1556    QRect cr = geometry();
     1557    if (qmsg.msg == WM_SIZE) { // resize event
     1558        QSize oldSize = size();
     1559        QSize newSize(SHORT1FROMMP(qmsg.mp2), SHORT2FROMMP(qmsg.mp2));
     1560        cr.setSize(newSize);
     1561        data->crect = cr;
     1562        if (isWindow()) {                        // update title/icon text
     1563            d_func()->createTLExtra();
     1564            QString title;
     1565            if ((fStyle & WS_MINIMIZED))
     1566                title = windowIconText();
     1567            if (title.isEmpty())
     1568                title = windowTitle();
     1569            if (!title.isEmpty())
     1570                d_func()->setWindowTitle_helper(title);
     1571        }
     1572        if (oldSize != newSize) {
     1573            // Spontaneous (external to Qt) WM_SIZE messages should occur only
     1574            // on top-level widgets. If we get them for a non top-level widget,
     1575            // the result will most likely be incorrect because widget masks will
     1576            // not be properly processed (i.e. in the way it is done in
     1577            // QWidget::setGeometry_sys() when the geometry is changed from
     1578            // within Qt). So far, I see no need to support this (who will ever
     1579            // need to move a non top-level window of a foreign process?).
     1580            Q_ASSERT(isWindow());
     1581            if (isVisible()) {
     1582                QTLWExtra *tlwExtra = d_func()->maybeTopData();
     1583                static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
     1584                const bool hasStaticContents = tlwExtra && tlwExtra->backingStore
     1585                                               && tlwExtra->backingStore->hasStaticContents();
     1586                // If we have a backing store with static contents, we have to disable the top-level
     1587                // resize optimization in order to get invalidated regions for resized widgets.
     1588                // The optimization discards all invalidateBuffer() calls since we're going to
     1589                // repaint everything anyways, but that's not the case with static contents.
     1590                if (!slowResize && tlwExtra && !hasStaticContents)
     1591                    tlwExtra->inTopLevelResize = true;
     1592                QResizeEvent e(newSize, oldSize);
     1593                QApplication::sendSpontaneousEvent(this, &e);
     1594                if (d_func()->paintOnScreen()) {
     1595                    QRegion updateRegion(rect());
     1596                    if (testAttribute(Qt::WA_StaticContents))
     1597                        updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height());
     1598                    // syncBackingStore() should have already flushed the widget
     1599                    // contents to the screen, so no need to redraw the exposed
     1600                    // areas in WM_PAINT once more
     1601                    d_func()->syncBackingStore(updateRegion);
     1602                    WinValidateRect(internalWinId(),
     1603                                    updateRegion.handle(newSize.height()), FALSE);
     1604                } else {
     1605                    d_func()->syncBackingStore();
     1606                    // see above
     1607                    RECTL rcl = { 0, 0, newSize.width(), newSize.height() };
     1608                    WinValidateRect(internalWinId(), &rcl, FALSE);
     1609                }
     1610                if (!slowResize && tlwExtra)
     1611                    tlwExtra->inTopLevelResize = false;
     1612            } else {
     1613                QResizeEvent *e = new QResizeEvent(newSize, oldSize);
     1614                QApplication::postEvent(this, e);
     1615            }
     1616        }
     1617    } else if (qmsg.msg == WM_MOVE) { // move event
     1618        QPoint oldPos = geometry().topLeft();
     1619        SWP swp;
     1620        if (isWindow()) {
     1621            WinQueryWindowPos(fId, &swp);
     1622            // flip y coordinate
     1623            swp.y = QApplication::desktop()->height() - (swp.y + swp.cy);
     1624            QTLWExtra *top = d_func()->topData();
     1625            swp.x += top->frameStrut.left();
     1626            swp.y += top->frameStrut.top();
     1627        } else {
     1628            WinQueryWindowPos(internalWinId(), &swp);
     1629            // flip y coordinate
     1630            swp.y = parentWidget()->height() - (swp.y + swp.cy);
     1631        }
     1632        QPoint newCPos(swp.x, swp.y);
     1633        if (newCPos != oldPos) {
     1634            cr.moveTopLeft(newCPos);
     1635            data->crect = cr;
     1636            if (isVisible()) {
     1637                QMoveEvent e(newCPos, oldPos); // cpos (client position)
     1638                QApplication::sendSpontaneousEvent(this, &e);
     1639            } else {
     1640                QMoveEvent *e = new QMoveEvent(newCPos, oldPos);
     1641                QApplication::postEvent(this, e);
     1642            }
     1643        }
     1644    }
     1645    setAttribute(Qt::WA_WState_ConfigPending, false);                // clear config flag
     1646    return true;
    15261647}
    15271648
Note: See TracChangeset for help on using the changeset viewer.