QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c) : shape(c.shape()), bitmapCacheKey(0), maskCacheKey(0) { if (shape == Qt::BitmapCursor) { const qint64 pixmapCacheKey = c.pixmap().cacheKey(); if (pixmapCacheKey) { bitmapCacheKey = pixmapCacheKey; } else { Q_ASSERT(c.bitmap()); Q_ASSERT(c.mask()); bitmapCacheKey = c.bitmap()->cacheKey(); maskCacheKey = c.mask()->cacheKey(); } } }
static HCURSOR qt_createPixmapCursor( const QCursor &cursor, const QPixmap &pixmap, const QPoint &hotspot ) { QSize size; /* calculate size of cursor */ QPoint pt = hotspot - cursor.hotSpot(); QPoint pixmap_point( 0, 0 ); QPoint cursor_point( 0, 0 ); if ( qWinVersion() <= Qt::WV_95 ) { /* Win95 can only fixed size */ size.setWidth( GetSystemMetrics ( SM_CXCURSOR ) ); size.setHeight ( GetSystemMetrics ( SM_CYCURSOR ) ); } else { /* calculate size (enlarge if needed) */ const QBitmap *tmp = cursor.bitmap(); /* Only bitmap cursors allowed... */ if ( tmp ) { QPoint point; // curent size size = pixmap.size(); // calc position of lower right cursor pos point.setX( pt.x() + tmp->size().width() ); point.setY( pt.y() + tmp->size().height() ); // resize when cursor to large if ( point.x() > pixmap.width() ) size.setWidth( point.x() ); if ( point.y() > pixmap.height() ) size.setHeight( point.y() ); // calc upper left corner where both pixmaps have to be drawn if ( pt.x() >= 0 ) { cursor_point.setX( pt.x() ); } else { pixmap_point.setX( -pt.x() ); // negative position -> resize size.setWidth( size.width() - pt.x() ); } if ( pt.y() >= 0 ) { cursor_point.setX( pt.x() ); } else { pixmap_point.setY( -pt.y() ); // negative position -> resize size.setHeight( size.height() - pt.y() ); } } } /* Mask */ QBitmap andMask( size ); BitBlt( andMask.handle(), 0, 0, size.width(), size.height(), NULL, 0, 0, WHITENESS ); if ( pixmap.mask() ) BitBlt( andMask.handle(), pixmap_point.x(), pixmap_point.y(), pixmap.width(), pixmap.height(), pixmap.mask() ->handle(), 0, 0, SRCAND ); else BitBlt( andMask.handle(), pixmap_point.x(), pixmap_point.y(), pixmap.width(), pixmap.height(), NULL, 0, 0, BLACKNESS ); const QBitmap *curMsk = cursor.mask(); if ( curMsk ) BitBlt( andMask.handle(), cursor_point.x(), cursor_point.y(), curMsk->width(), curMsk->height(), curMsk->handle(), 0, 0, SRCAND ); /* create Pixmap */ QPixmap xorMask( size ); xorMask.fill ( Qt::color1 ); QPainter paint2( &xorMask ); paint2.drawPixmap( pixmap_point, pixmap ); QPixmap pm; pm.convertFromImage( cursor.bitmap() ->convertToImage().convertDepth( 8 ) ); pm.setMask( *cursor.mask() ); paint2.drawPixmap ( cursor_point, pm ); paint2.end(); #ifdef DEBUG_QDND_SRC andMask.save ( "pand.png", "PNG" ); xorMask.save ( "pxor.png", "PNG" ); #endif HCURSOR cur = qt_createPixmapCursor ( qt_display_dc(), xorMask, andMask, hotspot, size ); if ( !cur ) { qWarning( "Error creating cursor: %d", GetLastError() ); } return cur; }
HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c) { int hx = c.hotSpot().x(); int hy = c.hotSpot().y(); const Qt::CursorShape cshape = c.shape(); if (cshape == Qt::BitmapCursor) { const QPixmap pixmap = c.pixmap(); if (!pixmap.isNull()) if (const HCURSOR hc = createPixmapCursor(pixmap, hx, hy)) return hc; } // Non-standard Windows cursors are created from bitmaps static const uchar vsplit_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uchar vsplitm_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uchar hsplit_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03, 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uchar hsplitm_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00, 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07, 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uchar openhand_bits[] = { 0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92, 0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20, 0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00}; static const uchar openhandm_bits[] = { 0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff, 0xf6,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f, 0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00}; static const uchar closedhand_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50, 0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10, 0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00}; static const uchar closedhandm_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f, 0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f, 0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00}; wchar_t *sh = 0; switch (c.shape()) { // map to windows cursor case Qt::ArrowCursor: sh = IDC_ARROW; break; case Qt::UpArrowCursor: sh = IDC_UPARROW; break; case Qt::CrossCursor: sh = IDC_CROSS; break; case Qt::WaitCursor: sh = IDC_WAIT; break; case Qt::IBeamCursor: sh = IDC_IBEAM; break; case Qt::SizeVerCursor: sh = IDC_SIZENS; break; case Qt::SizeHorCursor: sh = IDC_SIZEWE; break; case Qt::SizeBDiagCursor: sh = IDC_SIZENESW; break; case Qt::SizeFDiagCursor: sh = IDC_SIZENWSE; break; case Qt::SizeAllCursor: sh = IDC_SIZEALL; break; case Qt::ForbiddenCursor: sh = IDC_NO; break; case Qt::WhatsThisCursor: sh = IDC_HELP; break; case Qt::BusyCursor: sh = IDC_APPSTARTING; break; case Qt::PointingHandCursor: sh = IDC_HAND; break; case Qt::BlankCursor: case Qt::SplitVCursor: case Qt::SplitHCursor: case Qt::OpenHandCursor: case Qt::ClosedHandCursor: case Qt::BitmapCursor: { QImage bbits, mbits; bool invb, invm; if (cshape == Qt::BlankCursor) { bbits = QImage(32, 32, QImage::Format_Mono); bbits.fill(0); // ignore color table mbits = bbits.copy(); hx = hy = 16; invb = invm = false; } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) { bool open = cshape == Qt::OpenHandCursor; QBitmap cb = QBitmap::fromData(QSize(16, 16), open ? openhand_bits : closedhand_bits); QBitmap cm = QBitmap::fromData(QSize(16, 16), open ? openhandm_bits : closedhandm_bits); bbits = cb.toImage().convertToFormat(QImage::Format_Mono); mbits = cm.toImage().convertToFormat(QImage::Format_Mono); hx = hy = 8; invb = invm = false; } else if (cshape == Qt::BitmapCursor) { bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono); mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono); invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); } else { // Qt::SplitVCursor, Qt::SplitHCursor const QBitmap cb = QBitmap::fromData(QSize(32, 32), cshape == Qt::SplitVCursor ? vsplit_bits : hsplit_bits); const QBitmap cm = QBitmap::fromData(QSize(32, 32), cshape == Qt::SplitVCursor ? vsplitm_bits : hsplitm_bits); bbits = cb.toImage().convertToFormat(QImage::Format_Mono); mbits = cm.toImage().convertToFormat(QImage::Format_Mono); hx = hy = 16; invb = invm = false; } const int n = qMax(1, bbits.width() / 8); const int h = bbits.height(); #if !defined(Q_OS_WINCE) QScopedArrayPointer<uchar> xBits(new uchar[h * n]); QScopedArrayPointer<uchar> xMask(new uchar[h * n]); int x = 0; for (int i = 0; i < h; ++i) { uchar *bits = bbits.scanLine(i); uchar *mask = mbits.scanLine(i); for (int j = 0; j < n; ++j) { uchar b = bits[j]; uchar m = mask[j]; if (invb) b ^= 0xff; if (invm) m ^= 0xff; xBits[x] = ~m; xMask[x] = b ^ m; ++x; } } return CreateCursor(GetModuleHandle(0), hx, hy, bbits.width(), bbits.height(), xBits.data(), xMask.data()); #elif defined(GWES_ICONCURS) // Q_WS_WINCE // Windows CE only supports fixed cursor size. int sysW = GetSystemMetrics(SM_CXCURSOR); int sysH = GetSystemMetrics(SM_CYCURSOR); int sysN = qMax(1, sysW / 8); uchar* xBits = new uchar[sysH * sysN]; uchar* xMask = new uchar[sysH * sysN]; int x = 0; for (int i = 0; i < sysH; ++i) { if (i >= h) { memset(&xBits[x] , 255, sysN); memset(&xMask[x] , 0, sysN); x += sysN; } else { int fillWidth = n > sysN ? sysN : n; uchar *bits = bbits.scanLine(i); uchar *mask = mbits.scanLine(i); for (int j = 0; j < fillWidth; ++j) { uchar b = bits[j]; uchar m = mask[j]; if (invb) b ^= 0xFF; if (invm) m ^= 0xFF; xBits[x] = ~m; xMask[x] = b ^ m; ++x; } for (int j = fillWidth; j < sysN; ++j ) { xBits[x] = 255; xMask[x] = 0; ++x; } } } HCURSOR hcurs = CreateCursor(qWinAppInst(), hx, hy, sysW, sysH, xBits, xMask); delete [] xBits; delete [] xMask; return hcurs; #else Q_UNUSED(n); Q_UNUSED(h); return 0; #endif } case Qt::DragCopyCursor: case Qt::DragMoveCursor: case Qt::DragLinkCursor: { const QPixmap pixmap = QGuiApplicationPrivate::instance()->getPixmapCursor(cshape); return createPixmapCursor(pixmap, hx, hy); } default: qWarning("%s: Invalid cursor shape %d", __FUNCTION__, cshape); return 0; } #ifdef Q_OS_WINCE return LoadCursor(0, sh); #else return (HCURSOR)LoadImage(0, sh, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); #endif }