Mac: Add support for WindowMasks platform capability

Also brings back a working QWidgetPrivate::setMask_sys().

Change-Id: Idde9eea15d28bb0299258df81322a5a3ff0b9493
Reviewed-by: Liang Qi <liang.qi@digia.com>
Reviewed-by: Jens Bache-Wiig <jens.bache-wiig@digia.com>
This commit is contained in:
Gabriel de Dietrich 2012-10-24 16:09:52 +02:00 committed by The Qt Project
parent 733ac1f6e6
commit 30542304f1
5 changed files with 100 additions and 32 deletions

View File

@ -302,11 +302,14 @@ void QCocoaIntegration::updateScreens()
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
case ThreadedPixmaps: return true;
case OpenGL : return true;
case ThreadedOpenGL : return true;
case BufferQueueingOpenGL: return true;
default: return QPlatformIntegration::hasCapability(cap);
case ThreadedPixmaps:
case OpenGL:
case ThreadedOpenGL:
case BufferQueueingOpenGL:
case WindowMasks:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
}

View File

@ -107,6 +107,7 @@ public:
void lower();
void propagateSizeHints();
void setOpacity(qreal level);
void setMask(const QRegion &region);
bool setKeyboardGrabEnabled(bool grab);
bool setMouseGrabEnabled(bool grab);
QMargins frameMargins() const;

View File

@ -509,6 +509,16 @@ void QCocoaWindow::setOpacity(qreal level)
[m_nsWindow setAlphaValue:level];
}
void QCocoaWindow::setMask(const QRegion &region)
{
if (m_nsWindow) {
[m_nsWindow setOpaque:NO];
[m_nsWindow setBackgroundColor:[NSColor clearColor]];
}
[m_contentView setMaskRegion:&region];
}
bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
{
if (!m_nsWindow)

View File

@ -54,6 +54,8 @@ QT_END_NAMESPACE
@interface QNSView : NSView <NSTextInputClient> {
CGImageRef m_cgImage;
CGImageRef m_maskImage;
uchar *m_maskData;
QWindow *m_window;
QCocoaWindow *m_platformWindow;
Qt::MouseButtons m_buttons;
@ -68,6 +70,7 @@ QT_END_NAMESPACE
- (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow;
- (void)setImage:(QImage *)image;
- (void)setMaskRegion:(const QRegion *)region;
- (void)drawRect:(NSRect)dirtyRect;
- (void)updateGeometry;
- (void)windowNotification : (NSNotification *) windowNotification;

View File

@ -75,6 +75,8 @@ static QTouchDevice *touchDevice = 0;
self = [super initWithFrame : NSMakeRect(0,0, 300,300)];
if (self) {
m_cgImage = 0;
m_maskImage = 0;
m_maskData = 0;
m_window = 0;
m_buttons = Qt::NoButton;
m_sendKeyEvent = false;
@ -93,6 +95,10 @@ static QTouchDevice *touchDevice = 0;
{
CGImageRelease(m_cgImage);
m_cgImage = 0;
CGImageRelease(m_maskImage);
m_maskImage = 0;
delete[] m_maskData;
m_maskData = 0;
m_window = 0;
[super dealloc];
}
@ -205,47 +211,86 @@ static QTouchDevice *touchDevice = 0;
}
}
- (void) setImage:(QImage *)image
static CGImageRef qt_mac_toCGImage(QImage *qImage, bool isMask, uchar **dataCopy)
{
CGImageRelease(m_cgImage);
int width = image->width();
int height = image->height();
int width = qImage->width();
int height = qImage->height();
if (width <= 0 || height <= 0) {
qWarning() << Q_FUNC_INFO <<
"setting invalid size" << width << "x" << height << "for qnsview image";
m_cgImage = 0;
return;
return 0;
}
const uchar *imageData = image->bits();
int bitDepth = image->depth();
const uchar *imageData = qImage->bits();
if (dataCopy) {
delete[] *dataCopy;
*dataCopy = new uchar[qImage->byteCount()];
memcpy(*dataCopy, imageData, qImage->byteCount());
}
int bitDepth = qImage->depth();
int colorBufferSize = 8;
int bytesPrLine = image->bytesPerLine();
CGColorSpaceRef cgColourSpaceRef = CGColorSpaceCreateDeviceRGB();
int bytesPrLine = qImage->bytesPerLine();
CGDataProviderRef cgDataProviderRef = CGDataProviderCreateWithData(
NULL,
imageData,
image->byteCount(),
dataCopy ? *dataCopy : imageData,
qImage->byteCount(),
NULL);
m_cgImage = CGImageCreate(width,
height,
colorBufferSize,
bitDepth,
bytesPrLine,
cgColourSpaceRef,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
cgDataProviderRef,
NULL,
false,
kCGRenderingIntentDefault);
CGImageRef cgImage = 0;
if (isMask) {
cgImage = CGImageMaskCreate(width,
height,
colorBufferSize,
bitDepth,
bytesPrLine,
cgDataProviderRef,
NULL,
false);
} else {
CGColorSpaceRef cgColourSpaceRef = CGColorSpaceCreateDeviceRGB();
cgImage = CGImageCreate(width,
height,
colorBufferSize,
bitDepth,
bytesPrLine,
cgColourSpaceRef,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
cgDataProviderRef,
NULL,
false,
kCGRenderingIntentDefault);
CGColorSpaceRelease(cgColourSpaceRef);
}
return cgImage;
}
CGColorSpaceRelease(cgColourSpaceRef);
- (void) setImage:(QImage *)image
{
CGImageRelease(m_cgImage);
m_cgImage = qt_mac_toCGImage(image, false, 0);
}
- (void) setMaskRegion:(const QRegion *)region
{
if (m_maskImage)
CGImageRelease(m_maskImage);
if (region->isEmpty()) {
m_maskImage = 0;
}
const QRect &rect = qt_mac_toQRect([self frame]);
QImage maskImage(rect.size(), QImage::Format_RGB888);
maskImage.fill(Qt::white);
QPainter p(&maskImage);
p.setRenderHint(QPainter::Antialiasing);
p.setClipRegion(*region);
p.fillRect(rect, QBrush(Qt::black));
p.end();
maskImage = maskImage.convertToFormat(QImage::Format_Indexed8);
m_maskImage = qt_mac_toCGImage(&maskImage, true, &m_maskData);
}
- (void) drawRect:(NSRect)dirtyRect
@ -263,13 +308,19 @@ static QTouchDevice *touchDevice = 0;
CGContextTranslateCTM(cgContext, 0, dy);
CGContextScaleCTM(cgContext, 1, -1);
CGImageRef subMask = 0;
if (m_maskImage) {
subMask = CGImageCreateWithImageInRect(m_maskImage, dirtyCGRect);
CGContextClipToMask(cgContext, dirtyCGRect, subMask);
}
CGImageRef subImage = CGImageCreateWithImageInRect(m_cgImage, dirtyCGRect);
CGContextDrawImage(cgContext,dirtyCGRect,subImage);
CGContextRestoreGState(cgContext);
CGImageRelease(subImage);
CGImageRelease(subMask);
}
- (BOOL) isFlipped