Changeset 102


Ignore:
Timestamp:
Jul 24, 2006, 11:11:03 PM (19 years ago)
Author:
dmik
Message:

Widgets: Improved min/max/fullscreen handling:

  • Layout management now works correctly when the window is minimized;
  • Fixed duplicate WindowStateChange events;
  • WindowMinimized, WindowMaximized, WindowFullScreen are mutually exclusive (note: this fetaure is experimental, since it is partly incompatible with the weird non-exclusive Qt behavior on other platforms).
Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/qwidget.h

    r75 r102  
    985985    HSWITCH  swEntry;                           // window list entry handle
    986986    HPOINTER pmIcon;                            // internal OS/2 icon
     987    uint     in_sendWindowState : 1;            // used by QWidget::setWindowState()
     988    uint     reserved : 7;                      // reserved for future binary compatibility
    987989#endif
    988990    QRect    normalGeometry;                    // used by showMin/maximized/FullScreen
  • trunk/src/kernel/qapplication_pm.cpp

    r97 r102  
    326326    void        markFrameStrutDirty()   { QWidget::fstrut_dirty = 1; }
    327327#endif
     328    void        updateFrameStrut()      { QWidget::updateFrameStrut(); }
    328329    bool        translateMouseEvent( const QMSG &qmsg );
    329330    bool        translateKeyEvent( const QMSG &qmsg, bool grab );
     
    13621363//#endif
    13631364
    1364         case WM_MINMAXFRAME: {
    1365             bool window_state_change = FALSE;
    1366             PSWP pswp = (PSWP) mp1;
    1367             if ( pswp->fl & SWP_MAXIMIZE ) {
    1368                 window_state_change = TRUE;
    1369                 widget->setWState( Qt::WState_Maximized );
    1370                 if ( widget->isMinimized() ) {
    1371                     widget->clearWState( Qt::WState_Minimized );
    1372                     widget->showChildren( TRUE );
    1373                     QShowEvent e;
    1374                     qt_sendSpontaneousEvent( widget, &e );
    1375                 }
    1376             } else if ( pswp->fl & SWP_MINIMIZE ) {
    1377                 window_state_change = TRUE;
    1378                 widget->setWState( Qt::WState_Minimized );
    1379                 if ( widget->isVisible() ) {
    1380                     QHideEvent e;
    1381                     qt_sendSpontaneousEvent( widget, &e );
    1382                     widget->hideChildren( TRUE );
    1383                 }
    1384             } else if ( pswp->fl & SWP_RESTORE ) {
    1385                 window_state_change = TRUE;
    1386                 if ( widget->isMinimized() ) {
    1387                     widget->clearWState( Qt::WState_Minimized );
    1388                     widget->showChildren( TRUE );
    1389                     QShowEvent e;
    1390                     qt_sendSpontaneousEvent( widget, &e );
    1391                 } else {
    1392                     widget->clearWState( Qt::WState_Maximized );
    1393                 }
    1394             }
    1395             if ( window_state_change ) {
    1396                 QEvent e( QEvent::WindowStateChange );
    1397                 qt_sendSpontaneousEvent( widget, &e );
    1398             }
    1399             result = FALSE;
    1400             break;
    1401         }
    1402 
    14031365/// @todo (dmik) later
    14041366//      case WM_SETTINGCHANGE:
     
    17901752                }
    17911753            }
     1754            if ( (swp.fl & SWP_RESTORE) &&
     1755                 !(swp.fl & (SWP_MOVE | SWP_SIZE)) ) {
     1756                QRect r = widget->top()->normalGeometry;
     1757                if ( r.isValid() ) {
     1758                    // store normal geometry in window words
     1759                    USHORT x = r.x();
     1760                    USHORT y = r.y();
     1761                    USHORT w = r.width();
     1762                    USHORT h = r.height();
     1763                    // flip y coordinate
     1764                    y = QApplication::desktop()->height() - (y + h);
     1765                    WinSetWindowUShort( hwnd, QWS_XRESTORE, x );
     1766                    WinSetWindowUShort( hwnd, QWS_YRESTORE, y );
     1767                    WinSetWindowUShort( hwnd, QWS_CXRESTORE, w );
     1768                    WinSetWindowUShort( hwnd, QWS_CYRESTORE, h );
     1769                    widget->top()->normalGeometry.setWidth( 0 );
     1770                }
     1771            }
    17921772            if ( swp.fl & (SWP_ACTIVATE | SWP_ZORDER) ) {
    17931773                // get the modal widget that made this window blocked
     
    18531833                while ( (popup=QApplication::activePopupWidget()) && maxiter-- )
    18541834                    popup->close();
     1835            }
     1836            break;
     1837        }
     1838
     1839        case WM_WINDOWPOSCHANGED: {
     1840            // We detect spontaneous min/max/restore events here instead of
     1841            // WM_MINMAXFRAME, because WM_MINMAXFRAME is a pre-process message
     1842            // (i.e. no actual changes have been made) We need actual changes
     1843            // in order to update the frame strut and send WindowStateChange.
     1844            result = TRUE;
     1845            rc = QtOldFrameProc( hwnd, msg, mp1, mp2 );
     1846            ULONG awp = LONGFROMMP( mp2 );
     1847            bool window_state_change = FALSE;
     1848            if ( awp & AWP_MAXIMIZED ) {
     1849                window_state_change = TRUE;
     1850                widget->setWState( Qt::WState_Maximized );
     1851                widget->clearWState( Qt::WState_FullScreen );
     1852                if ( widget->isMinimized() ) {
     1853                    widget->clearWState( Qt::WState_Minimized );
     1854                    widget->showChildren( TRUE );
     1855                    QShowEvent e;
     1856                    qt_sendSpontaneousEvent( widget, &e );
     1857                }
     1858            } else if ( awp & AWP_MINIMIZED ) {
     1859                window_state_change = TRUE;
     1860                widget->setWState( Qt::WState_Minimized );
     1861                widget->clearWState( Qt::WState_Maximized );
     1862                widget->clearWState( Qt::WState_FullScreen );
     1863                if ( widget->isVisible() ) {
     1864                    QHideEvent e;
     1865                    qt_sendSpontaneousEvent( widget, &e );
     1866                    widget->hideChildren( TRUE );
     1867                }
     1868            } else if ( awp & AWP_RESTORED ) {
     1869                window_state_change = TRUE;
     1870                if ( widget->isMinimized() ) {
     1871                    widget->showChildren( TRUE );
     1872                    QShowEvent e;
     1873                    qt_sendSpontaneousEvent( widget, &e );
     1874                }
     1875                widget->clearWState( Qt::WState_Minimized );
     1876                widget->clearWState( Qt::WState_Maximized );
     1877            }
     1878            if ( window_state_change ) {
     1879                widget->updateFrameStrut();
     1880                if ( !widget->top()->in_sendWindowState ) {
     1881                    // send WindowStateChange event if this message is NOT
     1882                    // originated from QWidget::setWindowState().
     1883                    QEvent e( QEvent::WindowStateChange );
     1884                    qt_sendSpontaneousEvent( widget, &e );
     1885                }
    18551886            }
    18561887            break;
     
    32583289        QSize newSize( SHORT1FROMMP(qmsg.mp2), SHORT2FROMMP(qmsg.mp2) );
    32593290        if ( qmsg.msg == WM_SIZE && size() != newSize ) {
    3260             if ( !(fStyle & WS_MINIMIZED) )
    3261                 crect.setSize( newSize );
     3291            crect.setSize( newSize );
    32623292        }
    32633293        return TRUE;
     
    32693299        QSize newSize( SHORT1FROMMP(qmsg.mp2), SHORT2FROMMP(qmsg.mp2) );
    32703300        cr.setSize( newSize );
    3271         if ( !(fStyle & WS_MINIMIZED) )
    3272             crect = cr;
     3301        crect = cr;
    32733302        if ( isTopLevel() ) {                   // update caption/icon text
    32743303            createTLExtra();
     
    32843313            }
    32853314        }
    3286         if ( !(fStyle & WS_MINIMIZED) && oldSize != newSize) {
     3315        if ( oldSize != newSize) {
    32873316#if !defined (QT_PM_NO_WIDGETMASK)
    32883317            // Spontaneous (external to Qt) WM_SIZE messages should occur only
  • trunk/src/kernel/qwidget.cpp

    r57 r102  
    14711471    if (isMinimized()) return;
    14721472
     1473#ifdef Q_WS_PM
     1474    setWindowState(WindowMinimized);
     1475#else
    14731476    setWindowState((windowState() & ~WindowActive) | WindowMinimized);
     1477#endif   
    14741478    show();
    14751479    if (!isTopLevel())
     
    15871591    if (isFullScreen()) return;
    15881592
     1593#ifdef Q_WS_PM
     1594    setWindowState(WindowFullScreen);
     1595#else
    15891596    setWindowState(windowState() | WindowFullScreen);
     1597#endif   
    15901598    show();
    15911599    if (!isTopLevel())
     
    16101618    if (isMaximized()) return;
    16111619
     1620#ifdef Q_WS_PM
     1621    setWindowState(WindowMaximized);
     1622#else
    16121623    setWindowState((windowState() & ~WindowMinimized) | WindowMaximized);
     1624#endif   
    16131625    show();
    16141626    if (!isTopLevel())
  • trunk/src/kernel/qwidget_pm.cpp

    r101 r102  
    15771577}
    15781578
    1579 void QWidget::setWindowState(uint newstate)
     1579void QWidget::setWindowState( uint newstate )
    15801580{
    15811581    uint oldstate = windowState();
    15821582
    1583     //@@TODO (dmik): should we deactivate the widget when no WindowActive
    1584     //  is specified? Guess no, because such behavior can be seen in Win32
    1585     //  (the only exception is when WindowMinimized is set w/o WindowActive).
    1586     //  As well as nothing is done in Win32 when only WindowActive is
    1587     //  specified.
    1588     ULONG fl = (newstate & WindowActive) ?
    1589         SWP_ACTIVATE :
    1590         // mimic Win32 behavior
    1591         (newstate & WindowMinimized) ? SWP_DEACTIVATE :
    1592         // mimic Win32 behavior
    1593         ((oldstate & WindowMinimized) &&
    1594             (newstate & WindowMaximized)) ? SWP_ACTIVATE :
    1595         0;
    1596 
    1597     if (isTopLevel()) {
     1583    if ( newstate == oldstate )
     1584        return;
     1585   
     1586    ULONG fl = (newstate & WindowActive) ? SWP_ACTIVATE : 0;
     1587
     1588    /// @todo (dmik):
     1589    //  Ugrh. I cannot see any good logic in those weird window state
     1590    //  manipulations (see setWindowState() dox, original showMinimized(),
     1591    //  showMaximized(). showFullScreen() and showNormal() implementations).
     1592    //  So, treat all of three flags as exclusive for now (note: the below
     1593    //  code relies on this).
     1594    uint op = 0;
     1595    if ( newstate & WindowFullScreen ) op = WindowFullScreen;
     1596    else if ( newstate & WindowMinimized ) op = WindowMinimized;
     1597    else if ( newstate & WindowMaximized ) op = WindowMaximized;
     1598
     1599    if ( op == WindowMinimized )
     1600        fl = SWP_DEACTIVATE;
     1601   
     1602    if ( isTopLevel() && isVisible() ) {
    15981603        WId id = winFId();
    15991604        QTLWExtra *top = topData();
    16001605
    1601         if ((oldstate & WindowMaximized) != (newstate & WindowMaximized)) {
    1602             if (isVisible() && !(newstate & WindowMinimized)) {
    1603                 ULONG f = (newstate & WindowMaximized) ? SWP_MAXIMIZE : SWP_RESTORE;
    1604                 WinSetWindowPos( id, 0, 0, 0, 0, 0, fl | f );
    1605                 QRect r = topData()->normalGeometry;
    1606                 if (!(newstate & WindowMaximized) && r.width() >= 0) {
    1607                     if (pos() != r.topLeft() || size() !=r.size()) {
    1608                         top->normalGeometry = QRect( 0, 0, -1, -1 );
    1609                         r.addCoords( top->fleft, top->ftop, top->fleft, top->ftop);
    1610                         setGeometry( r );
    1611                     }
    1612                 }
    1613             }
    1614         }
    1615 
    1616         if ((oldstate & WindowFullScreen) != (newstate & WindowFullScreen)) {
    1617             if (newstate & WindowFullScreen) {
    1618                 if ( top->normalGeometry.width() < 0 && !(oldstate & WindowMaximized) )
    1619                     top->normalGeometry = QRect( pos(), size() );
    1620                 QRect r = QApplication::desktop()->screenGeometry(this);
    1621                 r.addCoords( -top->fleft, -top->fbottom, top->fright, top->ftop );
    1622                 WinSetWindowPos(
    1623                         id, 0, r.x(), r.y(), r.width(), r.height(),
    1624                         fl | SWP_SIZE | SWP_MOVE
    1625                 );
    1626 //@@TODO (dmik): we do not need to call updateFrameStrut() because the frame
    1627 //  is not changed, but who will update our crect?..
    1628 //              updateFrameStrut();
    1629             } else {
    1630                 ULONG f = fl;
    1631                 // the widget is still maximized
    1632                 if ( newstate & WindowMaximized ) {
    1633                     if (isVisible())
    1634                         f |= SWP_MAXIMIZE;
     1606        // set flag for the WM_WINDOWPOSCHANGED handler in QtFrameProc
     1607        top->in_sendWindowState = 1;
     1608       
     1609        if ( op == WindowMinimized || op == WindowMaximized ) {
     1610            fl |= op == WindowMinimized ? SWP_MINIMIZE : SWP_MAXIMIZE;
     1611            WinSetWindowPos( id, 0, 0, 0, 0, 0, fl );
     1612        } else if ( op == WindowFullScreen ) {
     1613            if ( !(oldstate & (WindowMinimized | WindowMaximized)) ) {
     1614                top->normalGeometry = frameGeometry();
     1615            } else {
     1616                // extract normal geometry from window words
     1617                USHORT x = WinQueryWindowUShort( id, QWS_XRESTORE );
     1618                USHORT y = WinQueryWindowUShort( id, QWS_YRESTORE );
     1619                USHORT w = WinQueryWindowUShort( id, QWS_CXRESTORE );
     1620                USHORT h = WinQueryWindowUShort( id, QWS_CYRESTORE );
     1621                // restore first to update the frame strut
     1622                if ( oldstate & WindowMinimized )
     1623                    WinSetWindowPos( id, 0, 0, 0, 0, 0, SWP_RESTORE );
     1624                // flip y coordinate
     1625                y = QApplication::desktop()->height() - (y + h);
     1626                top->normalGeometry = QRect( x, y, w, h );
     1627            }
     1628            QRect r = QApplication::desktop()->screenGeometry( this );
     1629            r.addCoords( -top->fleft, -top->fbottom, top->fright, top->ftop );
     1630            WinSetWindowPos( id, 0, r.x(), r.y(), r.width(), r.height(),
     1631                             fl | SWP_SIZE | SWP_MOVE );
     1632        } else {
     1633            if ( oldstate & WindowFullScreen ) {
     1634                QRect r = top->normalGeometry;
     1635                if ( r != frameGeometry() ) {
     1636                    r.addCoords( top->fleft, top->ftop, -top->fright, -top->fbottom );
     1637                    setGeometry( r );
    16351638                }
    1636                 if ( f ) WinSetWindowPos( id, 0, 0, 0, 0, 0, f );
    1637                 if ( !(newstate & WindowMaximized) ) {
    1638                     QRect r = top->normalGeometry;
    1639                     top->normalGeometry = QRect( 0, 0, -1, -1 );
    1640                     r.addCoords( top->fleft, top->ftop, top->fleft, top->ftop);
    1641                     setGeometry( r );
    1642                 }
    1643 //@@TODO (dmik): we do not need to call updateFrameStrut() because the frame
    1644 //  is not changed, but who will update our crect?..
    1645 //              else {
    1646 //                    updateFrameStrut();
    1647 //                }
    1648             }
    1649         }
    1650 
    1651         if ((oldstate & WindowMinimized) != (newstate & WindowMinimized)) {
    1652             if (isVisible()) {
    1653                 ULONG f =
    1654                     (newstate & WindowMinimized) ? SWP_MINIMIZE :
    1655                     (newstate & WindowMaximized) ? SWP_MAXIMIZE : SWP_RESTORE;
    1656                 WinSetWindowPos( id, 0, 0, 0, 0, 0, fl | f );
     1639                top->normalGeometry.setWidth( 0 );
     1640            } else {
     1641                QRect r = top->normalGeometry;
     1642                if ( r.isValid() ) {
     1643                    // store normal geometry in window words
     1644                    USHORT x = r.x();
     1645                    USHORT y = r.y();
     1646                    USHORT w = r.width();
     1647                    USHORT h = r.height();
     1648                    // flip y coordinate
     1649                    y = QApplication::desktop()->height() - (y + h);
     1650                    WinSetWindowUShort( id, QWS_XRESTORE, x );
     1651                    WinSetWindowUShort( id, QWS_YRESTORE, y );
     1652                    WinSetWindowUShort( id, QWS_CXRESTORE, w );
     1653                    WinSetWindowUShort( id, QWS_CYRESTORE, h );
     1654                    top->normalGeometry.setWidth( 0 );
     1655                }
     1656                WinSetWindowPos( id, 0, 0, 0, 0, 0, fl | SWP_RESTORE );
    16571657            }
    1658         }
     1658        }
     1659       
     1660        top->in_sendWindowState = 0;
    16591661    }
    16601662
    16611663    widget_state &= ~(WState_Minimized | WState_Maximized | WState_FullScreen);
    16621664    if (newstate & WindowMinimized)
    1663         widget_state |= WState_Minimized;
     1665        widget_state |= WState_Minimized;
    16641666    if (newstate & WindowMaximized)
    1665         widget_state |= WState_Maximized;
     1667        widget_state |= WState_Maximized;
    16661668    if (newstate & WindowFullScreen)
    1667         widget_state |= WState_FullScreen;
    1668 
     1669        widget_state |= WState_FullScreen;
     1670       
    16691671    QEvent e(QEvent::WindowStateChange);
    16701672    QApplication::sendEvent(this, &e);
     
    17161718    ULONG fl = 0;
    17171719    if ( isTopLevel() ) {
    1718         // we do this check here bevause setWindowState() does not actually
     1720        // we do this check here because setWindowState() does not actually
    17191721        // change the window state when the window is not visible, assuming
    17201722        // it will be done here.
     
    17231725        else if (testWState(WState_Maximized))
    17241726            fl |= SWP_MAXIMIZE;
     1727        else if (testWState(WState_FullScreen)) {
     1728            QTLWExtra *top = topData();
     1729            topData()->normalGeometry = QRect( pos(), size() );
     1730            QRect r = QApplication::desktop()->screenGeometry( this );
     1731            r.addCoords( -top->fleft, -top->fbottom, top->fright, top->ftop );
     1732            WinSetWindowPos( winFId(), 0, r.x(), r.y(), r.width(), r.height(),
     1733                             fl | SWP_SIZE | SWP_MOVE );
     1734        }
    17251735
    17261736        if (
     
    18301840    clearWState(WState_Maximized);
    18311841    clearWState(WState_FullScreen);
    1832     if (isTopLevel())
    1833         topData()->normalGeometry = QRect(0, 0, -1, -1);
    18341842    if ( testWState(WState_ConfigPending) ) {   // processing config event
    18351843        qPMRequestConfig( winId(), isMove ? 2 : 1, x, y, w, h );
     
    25572565    extra->topextra->swEntry = 0;
    25582566    extra->topextra->pmIcon = 0;
     2567    extra->topextra->in_sendWindowState = 0;
    25592568}
    25602569
Note: See TracChangeset for help on using the changeset viewer.