Ignore:
Timestamp:
Aug 6, 2009, 2:24:58 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: Implemented widget show/hide functions. Added widget mask (clip region) helpers.

File:
1 edited

Legend:

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

    r99 r100  
    5151
    5252#include "private/qapplication_p.h"
     53#include "private/qbackingstore_p.h"
    5354
    5455#include <qdebug.h>
    5556
    5657#define QT_DEBUGWINCREATEDESTROY
     58#define QT_DEBUGWIDGETMASK
    5759
    5860QT_BEGIN_NAMESPACE
     
    105107}
    106108
     109// returns the human readable widget id in the form "name/class".
     110// used for debugging.
     111static QString widgetName(HWND hwnd)
     112{
     113    char buf[10];
     114    if (WinQueryClassName(hwnd, sizeof(buf), buf)) {
     115        if (!strcmp(buf, "#1")) // WC_FRAME
     116            hwnd = WinWindowFromID(hwnd, FID_CLIENT);
     117        QWidget *w = QWidget::find(hwnd);
     118        if (w)
     119            return QString().sprintf("%s/%s",
     120                                     w->metaObject()->className(),
     121                                     w->objectName().toLocal8Bit().constData());
     122    }
     123    return QLatin1String("<non-Qt-widget>");
     124}
     125
     126/*!
     127    \internal
     128
     129    Extended version of WinQueryClipRegion(). If the given window has a clip
     130    region, the given region will receive a copy of the clip region clipped to
     131    the current window rectangle. If there is no clip region, the given region
     132    will contain only the window rectangle on return.
     133 */
     134static void qt_WinQueryClipRegionOrRect(HWND hwnd, HRGN hrgn)
     135{
     136    RECTL rcl;
     137    WinQueryWindowRect(hwnd, &rcl);
     138
     139    HPS hps = qt_display_ps();
     140    GpiSetRegion(hps, hrgn, 1, &rcl);
     141    if (WinQueryClipRegion(hwnd, 0) != QCRGN_NO_CLIP_REGION) {
     142        HRGN hrgnTemp = GpiCreateRegion(hps, 0, NULL);
     143        WinQueryClipRegion(hwnd, hrgnTemp);
     144        GpiCombineRegion(hps, hrgn, hrgnTemp, hrgn, CRGN_AND);
     145        GpiDestroyRegion(hps, hrgnTemp);
     146    }
     147}
     148
     149/*!
     150    \internal
     151
     152    Extended version of WinInvalidateRegion(): invalidates the specified region
     153    of the given window and regions of children from \a hwndFrom to \a hwndTo
     154    if they intersect with the invalid region. If either of child window
     155    handles is NULLHANDLE, children are not invalidated at all. Also, HWND_TOP
     156    can be used as \a hwndFrom, HWND_BOTTOM \a can be used as \a hwndTo.
     157 */
     158static BOOL qt_WinInvalidateRegionEx(HWND hwnd, HRGN hrgn,
     159                                      HWND hwndFrom, HWND hwndTo)
     160{
     161#if defined(QT_DEBUGWIDGETMASK)
     162    qDebug("qt_WinInvalidateRegionEx: hwnd=%08lX (%s) "
     163           "hwndFrom=%08lX hwndTo=%08lX", hwnd,
     164           widgetName(hwnd).toLocal8Bit().constData(),
     165           hwndFrom, hwndTo);
     166#endif
     167
     168    if (hwndFrom == HWND_TOP)
     169        hwndFrom = WinQueryWindow(hwnd, QW_TOP);
     170    if (hwndTo == HWND_BOTTOM)
     171        hwndTo = WinQueryWindow(hwnd, QW_BOTTOM);
     172
     173    if (hwndFrom == 0 || hwndTo == 0)
     174        return WinInvalidateRegion(hwnd, hrgn, FALSE);
     175
     176    if (WinQueryWindow(hwndFrom, QW_PARENT) != hwnd ||
     177        WinQueryWindow(hwndTo, QW_PARENT) != hwnd)
     178        return FALSE;
     179
     180    HPS hps = qt_display_ps();
     181
     182    SWP swp;
     183    HWND child = hwndFrom;
     184    HRGN hrgnChild = GpiCreateRegion(hps, 0, NULL);
     185    HRGN hrgnInv = GpiCreateRegion(hps, 0, NULL);
     186    GpiCombineRegion(hps, hrgnInv, hrgn, 0, CRGN_COPY);
     187
     188    LONG cmplx = RGN_RECT;
     189
     190    while (child) {
     191        WinQueryWindowPos(child, &swp);
     192#if defined(QT_DEBUGWIDGETMASK)
     193        qDebug(" child=%08lX [fl=%08lX] (%s)", child, swp.fl,
     194               widgetName(child).toLocal8Bit().constData());
     195#endif
     196        // proceed only if not hidden
     197        if (swp.fl & SWP_SHOW) {
     198            // get sibling's bounds (clip region or rect)
     199            qt_WinQueryClipRegionOrRect(child, hrgnChild);
     200            // translate the region to the parent's coordinate system
     201            POINTL ptl = { swp.x, swp.y };
     202            GpiOffsetRegion(hps, hrgnChild, &ptl);
     203            // intersect the child's region with the invalid one
     204            // and invalidate if not NULL
     205            cmplx = GpiCombineRegion(hps, hrgnChild, hrgnChild, hrgnInv,
     206                                      CRGN_AND);
     207            if (cmplx != RGN_NULL) {
     208                POINTL ptl2 = { -swp.x, -swp.y };
     209                GpiOffsetRegion(hps, hrgnChild, &ptl2);
     210                WinInvalidateRegion(child, hrgnChild, TRUE);
     211                GpiOffsetRegion(hps, hrgnChild, &ptl);
     212                // substract the invalidated area from the widget's region
     213                // (no need to invalidate it any more)
     214                cmplx = GpiCombineRegion(hps, hrgnInv, hrgnInv, hrgnChild,
     215                                          CRGN_DIFF);
     216#if defined(QT_DEBUGWIDGETMASK)
     217                qDebug("  processed");
     218#endif
     219                // finish if nothing left
     220                if (cmplx == RGN_NULL)
     221                    break;
     222            }
     223        }
     224        // iterate to the next window (below)
     225        if (child == hwndTo)
     226            break;
     227        child = WinQueryWindow(child, QW_NEXT);
     228    }
     229
     230    BOOL ok = (cmplx == RGN_NULL) || (child == hwndTo);
     231
     232    if (ok) {
     233        // invalidate what's left invalid after substracting children
     234        WinInvalidateRegion(hwnd, hrgnInv, FALSE);
     235    }
     236
     237    GpiDestroyRegion(hps, hrgnInv);
     238    GpiDestroyRegion(hps, hrgnChild);
     239
     240    return ok;
     241}
     242
     243/** \internal flags for qt_WinProcessWindowObstacles() */
     244enum {
     245    PWO_Children = 0x01,
     246    PWO_Sibings = 0x02,
     247    PWO_Ancestors = 0x04,
     248    PWO_Screen = 0x08,
     249    PWO_TopLevel = 0x80000000,
     250    // PWO_Default is suitable in most cases (for simple paint operations)
     251    PWO_Default = PWO_Children | PWO_Sibings | PWO_Ancestors | PWO_Screen,
     252};
     253
     254/*!
     255    \internal
     256
     257    Helper function to collect all relative windows intersecting with the
     258    given window and placed above it in z-order.
     259
     260    \param hwnd  window in question
     261    \param prcl  rectangle (in window coordinates) to limit processing to
     262                 (if null, the whole window rectange is used)
     263    \param hrgn  region where to combine all obstacles
     264                 (if 0, obstacles are directly validated instead of collecting)
     265    \param op    region operation perfomed when combining obstacles (CRGN_*)
     266    \param flags flags defining the scope (PWO_* ORed together)
     267
     268    \return complexity of the combined region (only when \a hrgn is not 0)
     269 */
     270static LONG qt_WinProcessWindowObstacles(HWND hwnd, PRECTL prcl, HRGN hrgn,
     271                                         LONG op, LONG flags = PWO_Default)
     272{
     273    Q_ASSERT(hwnd);
     274
     275    HPS displayPS = qt_display_ps();
     276
     277#if defined(QT_DEBUGWIDGETMASK)
     278    qDebug("qt_WinProcessWindowObstacles: hwnd=%08lX (%s), prcl=%p "
     279           "hrgn=%08lX, op=%ld flags=%08lX", hwnd,
     280           widgetName(hwnd).toLocal8Bit().constData(),
     281           prcl, hrgn, op, flags);
     282#endif
     283
     284    SWP swpSelf;
     285    WinQueryWindowPos(hwnd, &swpSelf);
     286
     287    RECTL rclSelf = { 0, 0, swpSelf.cx, swpSelf.cy };
     288    if (prcl)
     289        rclSelf = *prcl;
     290
     291    HRGN whrgn = GpiCreateRegion(displayPS, 0, NULL);
     292
     293    LONG cmplx = RGN_NULL;
     294    HWND relative;
     295    SWP swp;
     296
     297    // first, process areas placed outside the screen bounds
     298    if (flags & PWO_Screen) {
     299        RECTL rclScr = { 0, 0, QApplication::desktop()->width(),
     300                               QApplication::desktop()->height() };
     301        WinMapWindowPoints(HWND_DESKTOP, hwnd, (PPOINTL) &rclScr, 2);
     302        // rough check of whether some window part is outside bounds
     303        if (rclSelf.xLeft < rclScr.xLeft ||
     304            rclSelf.yBottom < rclScr.yBottom ||
     305            rclSelf.xRight > rclScr.xRight ||
     306            rclSelf.yTop > rclScr.yTop) {
     307            GpiSetRegion(displayPS, whrgn, 1, &rclSelf);
     308            HRGN hrgnScr = GpiCreateRegion(displayPS, 1, &rclScr);
     309            // substract the screen region from this window's region
     310            // to get parts placed outside
     311            GpiCombineRegion(displayPS, whrgn, whrgn, hrgnScr, CRGN_DIFF);
     312            GpiDestroyRegion(displayPS, hrgnScr);
     313            // process the region
     314            if (hrgn != NULLHANDLE) {
     315                cmplx = GpiCombineRegion(displayPS, hrgn, hrgn, whrgn, op);
     316            } else {
     317                WinValidateRegion(hwnd, whrgn, FALSE);
     318            }
     319#if defined(QT_DEBUGWIDGETMASK)
     320            qDebug(" collected areas outside screen bounds");
     321#endif
     322         }
     323    }
     324
     325    // next, go through all children (in z-order)
     326    if (flags & PWO_Children) {
     327        relative = WinQueryWindow(hwnd, QW_BOTTOM);
     328        if (relative != NULLHANDLE) {
     329            for (; relative != HWND_TOP; relative = swp.hwndInsertBehind) {
     330                WinQueryWindowPos(relative, &swp);
     331#if defined(QT_DEBUGWIDGETMASK)
     332                qDebug(" child=%08lX [fl=%08lX] (%s)", relative, swp.fl,
     333                       widgetName(relative).toLocal8Bit().constData());
     334#endif
     335                // skip if hidden
     336                if (!(swp.fl & SWP_SHOW))
     337                    continue;
     338                // rough check for intersection
     339                if (swp.x >= rclSelf.xRight || swp.y >= rclSelf.yTop ||
     340                    swp.x + swp.cx <= rclSelf.xLeft ||
     341                    swp.y + swp.cy <= rclSelf.yBottom)
     342                    continue;
     343                // get the bounds (clip region or rect)
     344                qt_WinQueryClipRegionOrRect(relative, whrgn);
     345                // translate the region to this window's coordinate system
     346                POINTL ptl = { swp.x, swp.y };
     347                GpiOffsetRegion(displayPS, whrgn, &ptl);
     348                // process the region
     349                if (hrgn != NULLHANDLE) {
     350                    cmplx = GpiCombineRegion(displayPS, hrgn, hrgn, whrgn, op);
     351                } else {
     352                    WinValidateRegion(hwnd, whrgn, FALSE);
     353                }
     354#if defined(QT_DEBUGWIDGETMASK)
     355                qDebug("  collected");
     356#endif
     357            }
     358        }
     359    }
     360
     361    HWND desktop = WinQueryDesktopWindow(0, 0);
     362    HWND parent = WinQueryWindow(hwnd, QW_PARENT);
     363
     364    // next, go through all siblings placed above (in z-order),
     365    // but only if they are not top-level windows (that cannot be
     366    // non-rectangular and thus are always correctly clipped by the system)
     367    if ((flags & PWO_Sibings) && parent != desktop) {
     368        for (relative = swpSelf.hwndInsertBehind;
     369              relative != HWND_TOP; relative = swp.hwndInsertBehind) {
     370            WinQueryWindowPos(relative, &swp);
     371#if defined(QT_DEBUGWIDGETMASK)
     372            qDebug(" sibling=%08lX [fl=%08lX] (%s)", relative, swp.fl,
     373                   widgetName(relative).toLocal8Bit().constData());
     374#endif
     375            // skip if hidden
     376            if (!(swp.fl & SWP_SHOW))
     377                continue;
     378            // rough check for intersection
     379            if (swp.x >= swpSelf.x + rclSelf.xRight ||
     380                swp.y >= swpSelf.y + rclSelf.yTop ||
     381                swp.x + swp.cx <= swpSelf.x + rclSelf.xLeft ||
     382                swp.y + swp.cy <= swpSelf.y + rclSelf.yBottom)
     383                continue;
     384            // get the bounds (clip region or rect)
     385            qt_WinQueryClipRegionOrRect(relative, whrgn);
     386            // translate the region to this window's coordinate system
     387            POINTL ptl = { swp.x - swpSelf.x, swp.y - swpSelf.y };
     388            GpiOffsetRegion(displayPS, whrgn, &ptl);
     389            // process the region
     390            if (hrgn != NULLHANDLE) {
     391                cmplx = GpiCombineRegion(displayPS, hrgn, hrgn, whrgn, op);
     392            } else {
     393                WinValidateRegion(hwnd, whrgn, FALSE);
     394            }
     395#if defined(QT_DEBUGWIDGETMASK)
     396            qDebug("  collected");
     397#endif
     398        }
     399    }
     400
     401    // last, go through all siblings of our parent and its ancestors
     402    // placed above (in z-order)
     403    if (flags & PWO_Ancestors) {
     404        POINTL delta = { swpSelf.x, swpSelf.y };
     405        while (parent != desktop) {
     406            HWND grandParent = WinQueryWindow(parent, QW_PARENT);
     407            if (!(flags & PWO_TopLevel)) {
     408                // When PWO_TopLevel is not specified, top-level windows
     409                // (children of the desktop) are not processed. It makes sense
     410                // when qt_WinProcessWindowObstacles() is used to clip out
     411                // overlying windows during regular paint operations (WM_PAINT
     412                // processing or drawing in a window directly through
     413                // WinGetPS()): in this case, top-level windows are always
     414                // correctly clipped out by the system (because they cannot be
     415                // non-rectangular).
     416                if (grandParent == desktop)
     417                    break;
     418            }
     419
     420            WinQueryWindowPos(parent, &swp);
     421#if defined(QT_DEBUGWIDGETMASK)
     422            qDebug(" parent=%08lX [fl=%08lX] (%s)", parent, swp.fl,
     423                   widgetName(parent).toLocal8Bit().constData());
     424#endif
     425            delta.x += swp.x;
     426            delta.y += swp.y;
     427            for (relative = swp.hwndInsertBehind;
     428                 relative != HWND_TOP; relative = swp.hwndInsertBehind) {
     429                WinQueryWindowPos(relative, &swp);
     430#if defined(QT_DEBUGWIDGETMASK)
     431                qDebug(" ancestor=%08lX [fl=%08lX] (%s)", relative, swp.fl,
     432                       widgetName(parent).toLocal8Bit().constData());
     433#endif
     434                // skip if hidden
     435                if (!(swp.fl & SWP_SHOW))
     436                    continue;
     437                // rough check for intersection
     438                if (swp.x - delta.x >= rclSelf.xRight ||
     439                    swp.y - delta.y >= rclSelf.yTop ||
     440                    swp.x - delta.x + swp.cx <= rclSelf.xLeft ||
     441                    swp.y - delta.y + swp.cy <= rclSelf.yBottom)
     442                    continue;
     443                // get the bounds (clip region or rect)
     444                qt_WinQueryClipRegionOrRect(relative, whrgn);
     445                // translate the region to this window's coordinate system
     446                POINTL ptl = { swp.x - delta.x, swp.y - delta.y };
     447                GpiOffsetRegion(displayPS, whrgn, &ptl);
     448                // process the region
     449                if (hrgn != NULLHANDLE) {
     450                    cmplx = GpiCombineRegion(displayPS, hrgn, hrgn, whrgn, op);
     451                } else {
     452                    WinValidateRegion(hwnd, whrgn, FALSE);
     453                }
     454#if defined(QT_DEBUGWIDGETMASK)
     455                qDebug("  collected");
     456#endif
     457            }
     458            parent = grandParent;
     459        }
     460    }
     461
     462    GpiDestroyRegion(displayPS, whrgn);
     463
     464    return cmplx;
     465}
     466
     467/*!
     468    \internal
     469
     470    Partial reimplementation of the WinSetWindowPos() API that obeys window clip
     471    regions. Currently supported flags are SWP_ZORDER, SWP_SHOW, SWP_HIDE and
     472    SWP_ACTIVATE. Other flags should not be used. Note that if any other flag is
     473    specified (alone or in addition to the supported ones), or if the given
     474    window is a top-level window, this function acts exactly like the original
     475    WinSetWindowPos() function.
     476 */
     477static BOOL qt_WinSetWindowPos(HWND hwnd, HWND hwndInsertBehind,
     478                               LONG x, LONG y, LONG cx, LONG cy,
     479                               ULONG fl)
     480{
     481#if defined(QT_DEBUGWIDGETMASK)
     482    qDebug("qt_WinSetWindowPos: hwnd=%08lX (%s) fl=%08lX", hwnd,
     483           widgetName(hwnd).toLocal8Bit().constData(), fl);
     484#endif
     485
     486    HWND desktop = WinQueryDesktopWindow(0, 0);
     487
     488    Q_ASSERT(((fl & ~(SWP_ZORDER | SWP_SHOW | SWP_HIDE)) == 0) ||
     489             hwnd == desktop || WinQueryWindow(hwnd, QW_PARENT) == desktop);
     490
     491    if ((fl & ~(SWP_ZORDER | SWP_SHOW | SWP_HIDE)) != 0 ||
     492         hwnd == desktop || WinQueryWindow(hwnd, QW_PARENT) == desktop) {
     493        return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
     494    }
     495
     496    SWP swpOld;
     497    WinQueryWindowPos(hwnd, &swpOld);
     498
     499    // do some checks
     500    if ((fl & SWP_ZORDER) && swpOld.hwndInsertBehind == hwndInsertBehind)
     501        fl &= ~SWP_ZORDER;
     502    if ((fl & SWP_SHOW) && (swpOld.fl & SWP_SHOW))
     503        fl &= ~SWP_SHOW;
     504    if ((fl & SWP_HIDE) && (swpOld.fl & SWP_HIDE))
     505        fl &= ~SWP_HIDE;
     506    if ((fl & (SWP_SHOW | SWP_HIDE)) == (SWP_SHOW | SWP_HIDE))
     507        fl &= ~SWP_HIDE;
     508
     509    BOOL rc = WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy,
     510                              fl | SWP_NOREDRAW);
     511    if (rc == FALSE || (fl & SWP_NOREDRAW))
     512        return rc;
     513
     514    SWP swpNew;
     515    WinQueryWindowPos(hwnd, &swpNew);
     516
     517    if (swpOld.hwndInsertBehind == swpNew.hwndInsertBehind)
     518        fl &= ~SWP_ZORDER;
     519
     520    if ((fl & (SWP_ZORDER | SWP_SHOW | SWP_HIDE)) == 0)
     521        return rc;
     522
     523    HPS hps = qt_display_ps();
     524    HWND hwndParent = WinQueryWindow(hwnd, QW_PARENT);
     525
     526    // get window bounds
     527    HRGN hrgnSelf = GpiCreateRegion(hps, 0, NULL);
     528    qt_WinQueryClipRegionOrRect(hwnd, hrgnSelf);
     529
     530    if (fl & SWP_SHOW) {
     531        WinInvalidateRegion(hwnd, hrgnSelf, TRUE);
     532    } else if (fl & SWP_HIDE) {
     533        // translate the region to the parent coordinate system
     534        POINTL ptl = { swpNew.x, swpNew.y };
     535        GpiOffsetRegion(hps, hrgnSelf, &ptl);
     536        // invalidate the parent and children below this window
     537        qt_WinInvalidateRegionEx(hwndParent, hrgnSelf,
     538                                  WinQueryWindow(hwnd, QW_NEXT), HWND_BOTTOM);
     539    } else { // fl & SWP_ZORDER
     540        // below we assume that WinSetWindowPos() returns FALSE if
     541        // an incorrect (unrelated) hwndInsertBehind is passed when SWP_ZORDER
     542        // is set
     543
     544        // first, detect whether we are moving up or down
     545        BOOL up;
     546        HWND hwndFrom, hwndTo;
     547        if (swpOld.hwndInsertBehind == HWND_TOP) {
     548            up = FALSE;
     549            hwndFrom = WinQueryWindow(hwndParent, QW_TOP);
     550            hwndTo = swpNew.hwndInsertBehind;
     551        } else {
     552            up = TRUE;
     553            for (HWND hwndAbove = hwnd;
     554                  (hwndAbove = WinQueryWindow(hwndAbove, QW_PREV)) != 0;) {
     555                if (hwndAbove == swpOld.hwndInsertBehind) {
     556                    up = FALSE;
     557                    break;
     558                }
     559            }
     560            if (up) {
     561                hwndFrom = swpOld.hwndInsertBehind;
     562                hwndTo = WinQueryWindow(hwnd, QW_NEXT);
     563            } else {
     564                hwndFrom = WinQueryWindow(swpOld.hwndInsertBehind, QW_NEXT);
     565                hwndTo = swpNew.hwndInsertBehind;
     566            }
     567        }
     568#if defined(QT_DEBUGWIDGETMASK)
     569        qDebug(" moving up? %ld", up);
     570        qDebug(" hwndFrom=%08lX (%s)", hwndFrom,
     571               widgetName(hwndFrom).toLocal8Bit().constData());
     572        qDebug(" hwndTo=%08lX (%s)", hwndTo,
     573               widgetName(hwndTo).toLocal8Bit().constData());
     574#endif
     575
     576        SWP swp;
     577        HWND sibling = hwndFrom;
     578        HRGN hrgn = GpiCreateRegion(hps, 0, NULL);
     579        HRGN hrgnUpd = GpiCreateRegion(hps, 0, NULL);
     580
     581        if (up) {
     582            // go upwards in z-order
     583            while (1) {
     584                WinQueryWindowPos(sibling, &swp);
     585#if defined(QT_DEBUGWIDGETMASK)
     586                qDebug(" sibling=%08lX [fl=%08lX] (%s)", sibling, swp.fl,
     587                       widgetName(sibling).toLocal8Bit().constData());
     588#endif
     589                // proceed only if not hidden
     590                if (swp.fl & SWP_SHOW) {
     591                    // get sibling's bounds (clip region or rect)
     592                    qt_WinQueryClipRegionOrRect(sibling, hrgn);
     593                    // translate the region to this window's coordinate system
     594                    POINTL ptl = { swp.x - swpNew.x, swp.y - swpNew.y };
     595                    GpiOffsetRegion(hps, hrgn, &ptl);
     596                    // add to the region of siblings we're moving on top of
     597                    GpiCombineRegion(hps, hrgnUpd, hrgnUpd, hrgn, CRGN_OR);
     598#if defined(QT_DEBUGWIDGETMASK)
     599                    qDebug("  processed");
     600#endif
     601                }
     602                // iterate to the prev window (above)
     603                if (sibling == hwndTo)
     604                    break;
     605                sibling = swp.hwndInsertBehind;
     606            }
     607            // intersect the resulting region with the widget region and
     608            // invalidate
     609            GpiCombineRegion(hps, hrgnUpd, hrgnSelf, hrgnUpd, CRGN_AND);
     610            WinInvalidateRegion(hwnd, hrgnUpd, TRUE);
     611        } else {
     612            // go downwards in reverse z-order
     613            POINTL ptl = { 0, 0 };
     614            while (1) {
     615                WinQueryWindowPos(sibling, &swp);
     616#if defined(QT_DEBUGWIDGETMASK)
     617                qDebug(" sibling=%08lX [fl=%08lX] (%s)", sibling, swp.fl,
     618                       widgetName(sibling).toLocal8Bit().constData());
     619#endif
     620                // proceed only if not hidden
     621                if (swp.fl & SWP_SHOW) {
     622                    // get sibling's bounds (clip region or rect)
     623                    qt_WinQueryClipRegionOrRect(sibling, hrgn);
     624                    // undo the previous translation and translate this window's
     625                    // region to the siblings's coordinate system
     626                    ptl.x += swpNew.x - swp.x;
     627                    ptl.y += swpNew.y - swp.y;
     628                    GpiOffsetRegion(hps, hrgnSelf, &ptl);
     629                    // intersect the sibling's region with the translated one
     630                    // and invalidate the sibling
     631                    GpiCombineRegion(hps, hrgnUpd, hrgnSelf, hrgn, CRGN_AND);
     632                    WinInvalidateRegion(sibling, hrgnUpd, TRUE);
     633                    // substract the invalidated area from the widget's region
     634                    // (no need to invalidate it any more)
     635                    GpiCombineRegion(hps, hrgnSelf, hrgnSelf, hrgnUpd, CRGN_DIFF);
     636                    // prepare the translation from the sibling's
     637                    // coordinates back to this window's coordinates
     638                    ptl.x = swp.x - swpNew.x;
     639                    ptl.y = swp.y - swpNew.y;
     640#if defined(QT_DEBUGWIDGETMASK)
     641                    qDebug("  processed");
     642#endif
     643                }
     644                // iterate to the next window (below)
     645                if (sibling == hwndTo)
     646                    break;
     647                sibling = WinQueryWindow(sibling, QW_NEXT);
     648            }
     649        }
     650
     651        GpiDestroyRegion(hps, hrgnUpd);
     652        GpiDestroyRegion(hps, hrgn);
     653    }
     654
     655    GpiDestroyRegion(hps, hrgnSelf);
     656
     657    return TRUE;
     658}
     659
    107660/*!
    108661 * \internal
     
    115668static BOOL qt_WinDestroyWindow(HWND hwnd)
    116669{
    117 #if !defined (QT_NO_SESSIONMANAGER)
     670#if !defined(QT_NO_SESSIONMANAGER)
    118671    qt_about_to_destroy_wnd = true;
    119672#endif
    120673    BOOL rc = WinDestroyWindow(hwnd);
    121 #if !defined (QT_NO_SESSIONMANAGER)
     674#if !defined(QT_NO_SESSIONMANAGER)
    122675    qt_about_to_destroy_wnd = false;
    123676#endif
     
    321874            QWidget *parent = q->parentWidget();
    322875
    323 QWidgetPrivate *ppp;
    324 ppp->frameWinId();
    325876            if (parent && !(parent->windowType() == Qt::Desktop))
    326877                ownerw = parent->window()->d_func()->frameWinId();
     
    6821233void QWidgetPrivate::hide_sys()
    6831234{
    684     // @todo implement
     1235    Q_Q(QWidget);
     1236    deactivateWidgetCleanup();
     1237    Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
     1238    if (q->windowFlags() != Qt::Desktop) {
     1239        ULONG fl = SWP_HIDE;
     1240        if (q->isWindow() && frameWinId() != NULLHANDLE) {
     1241            if (!(q->windowFlags() & Qt::Popup))
     1242                fl |= SWP_DEACTIVATE;
     1243        }
     1244        qt_WinSetWindowPos(frameWinId(), 0, 0, 0, 0, 0, fl);
     1245        HSWITCH swEntry = maybeTopData() ? maybeTopData()->swEntry : NULLHANDLE;
     1246        if (swEntry != NULLHANDLE) {
     1247            SWCNTRL swc;
     1248            WinQuerySwitchEntry(swEntry, &swc);
     1249            swc.uchVisibility = SWL_INVISIBLE;
     1250            WinChangeSwitchEntry(swEntry, &swc);
     1251        }
     1252    }
     1253    if (q->isWindow()) {
     1254        if (QWidgetBackingStore *bs = maybeBackingStore())
     1255            bs->releaseBuffer();
     1256    } else {
     1257        invalidateBuffer(q->rect());
     1258    }
     1259    q->setAttribute(Qt::WA_Mapped, false);
    6851260}
    6861261
    6871262void QWidgetPrivate::show_sys()
    6881263{
    689     // @todo implement
     1264    Q_Q(QWidget);
     1265#if defined(QT_NON_COMMERCIAL)
     1266    QT_NC_SHOW_WINDOW
     1267#endif
     1268    if (q->testAttribute(Qt::WA_OutsideWSRange))
     1269        return;
     1270    q->setAttribute(Qt::WA_Mapped);
     1271    Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
     1272
     1273    if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
     1274        invalidateBuffer(q->rect());
     1275        return;
     1276    }
     1277
     1278    if (frameWinId() != NULLHANDLE) {
     1279        ULONG fl = SWP_SHOW;
     1280        if (q->isWindow()) {
     1281            if (q->isMinimized()) {
     1282                fl = SWP_MINIMIZE;
     1283            } else if (q->isMaximized()) {
     1284                fl |= SWP_MAXIMIZE;
     1285            } else {
     1286                fl |= SWP_RESTORE;
     1287            }
     1288
     1289            if (!(q->testAttribute(Qt::WA_ShowWithoutActivating)
     1290                  || (q->windowType() == Qt::Popup)
     1291                  || (q->windowType() == Qt::ToolTip)
     1292                  || (q->windowType() == Qt::Tool))) {
     1293                fl |= SWP_ACTIVATE;
     1294            }
     1295        }
     1296
     1297        qt_WinSetWindowPos(frameWinId(), 0, 0, 0, 0, 0, fl);
     1298
     1299        if (q->isWindow()) {
     1300            if (q->windowType() != Qt::Popup &&
     1301                q->windowType() != Qt::Tool &&
     1302                (q->windowType() != Qt::Dialog || !q->parentWidget())
     1303            ) {
     1304                HSWITCH &swEntry = topData()->swEntry;
     1305                if (!swEntry) {
     1306                    // lazily create a new window list entry
     1307                    HWND id = frameWinId();
     1308                    PID pid;
     1309                    WinQueryWindowProcess(id, &pid, NULL);
     1310                    SWCNTRL swc;
     1311                    memset(&swc, 0, sizeof(SWCNTRL));
     1312                    swc.hwnd = id;
     1313                    swc.idProcess = pid;
     1314                    swc.uchVisibility = SWL_VISIBLE;
     1315                    swc.fbJump = SWL_JUMPABLE;
     1316                    WinQueryWindowText(id, sizeof(swc.szSwtitle), swc.szSwtitle);
     1317                    swEntry = WinAddSwitchEntry(&swc);
     1318                } else {
     1319                    SWCNTRL swc;
     1320                    WinQuerySwitchEntry(swEntry, &swc);
     1321                    swc.uchVisibility = SWL_VISIBLE;
     1322                    WinChangeSwitchEntry(swEntry, &swc);
     1323                }
     1324            }
     1325
     1326            ULONG wstyle = WinQueryWindowULong(frameWinId(), QWL_STYLE);
     1327            if (wstyle & WS_MINIMIZED)
     1328                data.window_state |= Qt::WindowMinimized;
     1329            if (wstyle & WS_MAXIMIZED)
     1330                data.window_state |= Qt::WindowMaximized;
     1331        }
     1332    }
     1333
     1334    invalidateBuffer(q->rect());
    6901335}
    6911336
     
    7641409{
    7651410    extra->topextra->fId = NULLHANDLE;
     1411    extra->topextra->swEntry = NULLHANDLE;
    7661412}
    7671413
    7681414void QWidgetPrivate::deleteTLSysExtra()
    7691415{
     1416    if (extra->topextra->swEntry != NULLHANDLE)
     1417        WinRemoveSwitchEntry(extra->topextra->swEntry);
    7701418    // Note: extra->topextra->fId is cleaned up in QWidget::destroy()
    7711419}
Note: See TracChangeset for help on using the changeset viewer.