VirtualBox

Ignore:
Timestamp:
May 18, 2016 7:01:02 AM (9 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:7303: UISession::setPointerShape Qt5 fixes for Windows host.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp

    r60362 r61021  
    2222/* Qt includes: */
    2323# include <QApplication>
     24# include <QBitmap>
    2425# include <QDesktopWidget>
    2526# include <QWidget>
     
    15781579    }
    15791580}
     1581
     1582static bool isPointer1bpp(const uint8_t *pu8XorMask,
     1583                          uint uWidth,
     1584                          uint uHeight)
     1585{
     1586    /* Check if the pointer has only 0 and 0xFFFFFF pixels, ignoring the alpha channel. */
     1587    const uint32_t *pu32Src = (uint32_t *)pu8XorMask;
     1588
     1589    uint y;
     1590    for (y = 0; y < uHeight ; ++y)
     1591    {
     1592        uint x;
     1593        for (x = 0; x < uWidth; ++x)
     1594        {
     1595            const uint32_t u32Pixel = pu32Src[x] & UINT32_C(0xFFFFFF);
     1596            if (u32Pixel != 0 && u32Pixel != UINT32_C(0xFFFFFF))
     1597                return false;
     1598        }
     1599
     1600        pu32Src += uWidth;
     1601    }
     1602
     1603    return true;
     1604}
     1605
    15801606void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
    15811607                                uint uXHot, uint uYHot, uint uWidth, uint uHeight)
     
    15911617#if defined (VBOX_WS_WIN)
    15921618
     1619# if QT_VERSION < 0x050000
    15931620    BITMAPV5HEADER bi;
    15941621    HBITMAP hBitmap;
     
    17021729        {
    17031730            /* Set the new cursor: */
    1704 # if QT_VERSION < 0x050000
    17051731            m_cursor = QCursor(hAlphaCursor);
    1706 # else /* QT_VERSION >= 0x050000 */
    1707             m_cursor = QCursor(QtWin::fromHBITMAP(hBitmap, QtWin::HBitmapAlpha), uXHot, uYHot);
    1708 # endif /* QT_VERSION >= 0x050000 */
    17091732            if (m_alphaCursor)
    17101733                DestroyIcon(m_alphaCursor);
     
    17181741    if (hBitmap)
    17191742        DeleteObject(hBitmap);
     1743# else /* QT_VERSION >= 0x050000 */
     1744    /* Create a ARGB image out of the shape data: */
     1745    QImage image(uWidth, uHeight, QImage::Format_ARGB32);
     1746    memcpy(image.bits(), srcShapePtr, uHeight * uWidth * 4);
     1747
     1748    if (fHasAlpha)
     1749        m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
     1750    else
     1751    {
     1752        if (isPointer1bpp(srcShapePtr, uWidth, uHeight))
     1753        {
     1754            /* Incoming data consist of 32 bit BGR XOR mask and 1 bit AND mask.
     1755             * XOR pixels contain either 0x00000000 or 0x00FFFFFF.
     1756             * image.convertToFormat(QImage::Format_Mono) converts them:
     1757             * 0x00000000 -> 1, 0x00FFFFFF -> 0.
     1758             *
     1759             * XOR AND originally intended result (F denotes 0x00FFFFFF):
     1760             *   0   0 black
     1761             *   F   0 white
     1762             *   0   1 transparent
     1763             *   F   1 xor'd
     1764             *
     1765             * XOR AND converted bitmap intended result:
     1766             *   1   0 black
     1767             *   0   0 white
     1768             *   1   1 transparent
     1769             *   0   1 xor'd
     1770             *
     1771             * Bitmap Mask actual Qt5 result (tested on Windows 7 64 bit host):
     1772             *   1   0 black
     1773             *   0   0 white
     1774             *   0   1 transparent
     1775             *   1   1 xor'd
     1776             *
     1777             * Converted bitmap to the Qt5 mask and bitmap:
     1778             * Mask = AND;
     1779             * Bitmap = ConvBitmap ^ Mask;
     1780             */
     1781            QImage bitmap = image.convertToFormat(QImage::Format_Mono);
     1782            QImage mask(uWidth, uHeight, QImage::Format_Mono);
     1783            memcpy(mask.bits(), srcAndMaskPtr, uHeight * ((uWidth + 7) / 8));
     1784
     1785            const uint8_t *pu8Mask = mask.bits();
     1786            uint8_t *pu8Bitmap = bitmap.bits();
     1787            uint i;
     1788            for (i = 0; i < uHeight * ((uWidth + 7) / 8); ++i)
     1789                pu8Bitmap[i] ^= pu8Mask[i];
     1790
     1791            m_cursor = QCursor(QBitmap::fromImage(bitmap), QBitmap::fromImage(mask), uXHot, uYHot);
     1792        }
     1793        else
     1794        {
     1795            /* Assign alpha channel values according to the AND mask: 1 -> 0x00, 0 -> 0xFF: */
     1796            const uint8_t *pu8And = srcAndMaskPtr;
     1797            uint32_t *pu32Pixel = (uint32_t *)image.bits();
     1798            uint y;
     1799            for (y = 0; y < uHeight; ++y)
     1800            {
     1801                uint x;
     1802                for (x = 0; x < (uWidth + 7) / 8; ++x)
     1803                {
     1804                    const uint8_t b = *pu8And;
     1805                    uint k;
     1806                    for (k = 0; k < 8; ++k)
     1807                    {
     1808                        if (b & (1 << (7 - k)))
     1809                            *pu32Pixel &= UINT32_C(0x00FFFFFF);
     1810                        else
     1811                            *pu32Pixel |= UINT32_C(0xFF000000);
     1812                        ++pu32Pixel;
     1813                    }
     1814
     1815                    ++pu8And;
     1816                }
     1817            }
     1818
     1819            m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
     1820        }
     1821    }
     1822
     1823    m_fIsValidPointerShapePresent = true;
     1824# endif /* QT_VERSION >= 0x050000 */
    17201825
    17211826#elif defined(VBOX_WS_X11) || defined(VBOX_WS_MAC)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette