QPlatformWindow: Add Window masks.

Add functionality for window masks to QPlatformWindow, which is
required to implement QWidget::setMask() in order to fix
the regression in functionality from Qt 4.8.

Change-Id: I2c2d5629f0b4c6d90e52595ad70b13559aab1f41
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
This commit is contained in:
Friedemann Kleint 2012-06-25 13:58:41 +02:00 committed by Qt by Nokia
parent 799f0841a6
commit 8e280d1e18
11 changed files with 139 additions and 5 deletions

View File

@ -85,8 +85,8 @@ public:
OpenGL = 2,
ThreadedOpenGL = 3,
SharedGraphicsCache = 4,
BufferQueueingOpenGL = 5
BufferQueueingOpenGL = 5,
WindowMasks = 6
};
virtual ~QPlatformIntegration() { }

View File

@ -68,6 +68,7 @@ class QPlatformScreen;
class QPlatformWindowPrivate;
class QWindow;
class QIcon;
class QRegion;
class Q_GUI_EXPORT QPlatformWindow : public QPlatformSurface
{
@ -105,6 +106,7 @@ public:
virtual void propagateSizeHints();
virtual void setOpacity(qreal level);
virtual void setMask(const QRegion &region);
virtual void requestActivateWindow();
virtual void handleContentOrientationChange(Qt::ScreenOrientation orientation);

View File

@ -241,6 +241,16 @@ void QPlatformWindow::setOpacity(qreal level)
qWarning("This plugin does not support setting window opacity");
}
/*!
Reimplement to be able to let Qt set the mask of a window
*/
void QPlatformWindow::setMask(const QRegion &region)
{
Q_UNUSED(region);
qWarning("This plugin does not support setting window masks");
}
/*!
Reimplement to let Qt be able to request activation/focus for a window

View File

@ -265,6 +265,8 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
return true;
# endif // QT_OPENGL_ES_2
#endif // !QT_NO_OPENGL
case WindowMasks:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
}

View File

@ -53,6 +53,7 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <QtGui/QRegion>
#include <private/qwindow_p.h>
#include <QtGui/QWindowSystemInterface>
@ -1344,6 +1345,49 @@ void QWindowsWindow::setOpacity(qreal level)
}
}
static inline HRGN createRectRegion(const QRect &r)
{
return CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
}
static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
{
if (const HRGN rectRegion = createRectRegion(rect)) {
HRGN result = CreateRectRgn(0, 0, 0, 0);
if (CombineRgn(result, *winRegion, rectRegion, RGN_OR)) {
DeleteObject(winRegion);
*winRegion = result;
}
DeleteObject(rectRegion);
}
}
static HRGN qRegionToWinRegion(const QRegion &region)
{
const QVector<QRect> rects = region.rects();
if (rects.isEmpty())
return NULL;
const int rectCount = rects.size();
if (rectCount == 1)
return createRectRegion(region.boundingRect());
HRGN hRegion = createRectRegion(rects.front());
for (int i = 1; i < rectCount; ++i)
addRectToWinRegion(rects.at(i), &hRegion);
return hRegion;
}
void QWindowsWindow::setMask(const QRegion &region)
{
if (region.isEmpty()) {
SetWindowRgn(m_data.hwnd, 0, true);
return;
}
const HRGN winRegion = qRegionToWinRegion(region);
// SetWindowRgn takes ownership.
if (!SetWindowRgn(m_data.hwnd, winRegion, true))
DeleteObject(winRegion);
}
void QWindowsWindow::requestActivateWindow()
{
if (QWindowsContext::verboseWindows)

View File

@ -168,6 +168,7 @@ public:
virtual QMargins frameMargins() const;
virtual void setOpacity(qreal level);
virtual void setMask(const QRegion &region);
qreal opacity() const { return m_opacity; }
virtual void requestActivateWindow();

View File

@ -203,6 +203,7 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
case ThreadedPixmaps: return true;
case OpenGL: return true;
case ThreadedOpenGL: return false;
case WindowMasks: return true;
default: return QPlatformIntegration::hasCapability(cap);
}
}

View File

@ -44,6 +44,7 @@
#include <QtDebug>
#include <QScreen>
#include <QtGui/QIcon>
#include <QtGui/QRegion>
#include "qxcbconnection.h"
#include "qxcbscreen.h"
@ -97,6 +98,9 @@
#ifdef XCB_USE_XLIB
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifndef QT_NO_SHAPE
# include <X11/extensions/shape.h>
#endif // QT_NO_SHAPE
#endif
#ifdef XCB_USE_XINPUT2_MAEMO
@ -1698,4 +1702,54 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
return true;
}
#if defined(XCB_USE_XLIB) && !defined(QT_NO_SHAPE)
static inline XRectangle qRectToX11Rectangle(const QRect &r)
{
XRectangle result;
result.x = qMax(SHRT_MIN, r.x());
result.y = qMax(SHRT_MIN, r.y());
result.width = qMin((int)USHRT_MAX, r.width());
result.height = qMin((int)USHRT_MAX, r.height());
return result;
}
static inline Region qRegionToX11Region(const QRegion &region)
{
if (region.isEmpty())
return None;
Region result = XCreateRegion();
if (!result)
return None;
const QVector<QRect> rects = region.rects();
if (rects.size() == 1) {
XRectangle xrect = qRectToX11Rectangle(region.boundingRect());
XUnionRectWithRegion(&xrect, result, result);
} else {
foreach (const QRect &r, rects) {
XRectangle xrect = qRectToX11Rectangle(r);
XUnionRectWithRegion(&xrect, result, result);
}
}
return result;
}
void QXcbWindow::setMask(const QRegion &region)
{
Display *display = (Display *)connection()->xlib_display();
if (region.isEmpty()) {
XShapeCombineMask(display, xcb_window(),
ShapeBounding, 0, 0,
None, ShapeSet);
} else {
XShapeCombineRegion(display, xcb_window(),
ShapeBounding, 0, 0,
qRegionToX11Region(region), ShapeSet);
}
}
#endif // XCB_USE_XLIB && !QT_NO_SHAPE
QT_END_NAMESPACE

View File

@ -109,6 +109,10 @@ public:
bool startSystemResize(const QPoint &pos, Qt::Corner corner);
#if defined(XCB_USE_XLIB) && !defined(QT_NO_SHAPE)
void setMask(const QRegion &region);
#endif // XCB_USE_XLIB && !QT_NO_SHAPE
xcb_window_t xcb_window() const { return m_window; }
uint depth() const { return m_depth; }
QImage::Format imageFormat() const { return m_imageFormat; }

View File

@ -45,6 +45,7 @@ contains(QT_CONFIG, xcb-poll-for-queued-event) {
# needed by GLX, Xcursor, XLookupString, ...
contains(QT_CONFIG, xcb-xlib) {
DEFINES += XCB_USE_XLIB
!contains(DEFINES, QT_NO_SHAPE):LIBS += -lXext
LIBS += -lX11 -lX11-xcb
linux-g++-maemo {

View File

@ -50,6 +50,7 @@
#include <qpa/qplatformwindow.h>
#include "QtGui/qsurfaceformat.h"
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformintegration.h>
#include "QtGui/private/qwindow_p.h"
#include <qpa/qplatformcursor.h>
@ -929,10 +930,24 @@ void QWidgetPrivate::registerDropSite(bool on)
Q_UNUSED(on);
}
void QWidgetPrivate::setMask_sys(const QRegion &region)
void QWidgetPrivate::setMask_sys(const QRegion &regionIn)
{
Q_UNUSED(region);
// XXX
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowMasks)) {
qWarning("%s: Not supported on %s.", Q_FUNC_INFO, qPrintable(QGuiApplication::platformName()));
return;
}
Q_Q(QWidget);
QRegion region = regionIn;
QWindow *window = q->windowHandle();
if (!window) {
if (QWidget *nativeParent = q->nativeParentWidget()) {
window = nativeParent->windowHandle();
region.translate(q->mapTo(nativeParent, QPoint(0, 0)));
}
}
if (window)
if (QPlatformWindow *platformWindow = window->handle())
platformWindow->setMask(region);
}
void QWidgetPrivate::updateFrameStrut()