diff options
Diffstat (limited to 'src/gui/kernel')
49 files changed, 3539 insertions, 872 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index e9e4a1d818..1169985ea8 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -66,13 +66,14 @@ HEADERS += \ kernel/qplatformsharedgraphicscache.h \ kernel/qplatformdialoghelper.h \ kernel/qplatformservices.h \ - kernel/qplatformscreenpageflipper.h \ kernel/qplatformsystemtrayicon.h \ - kernel/qplatformsessionmanager.h + kernel/qplatformsessionmanager.h \ + kernel/qpixelformat.h \ + kernel/qpaintdevicewindow.h \ + kernel/qpaintdevicewindow_p.h \ + kernel/qrasterwindow.h SOURCES += \ - kernel/qclipboard_qpa.cpp \ - kernel/qcursor_qpa.cpp \ kernel/qgenericpluginfactory.cpp \ kernel/qgenericplugin.cpp \ kernel/qwindowsysteminterface.cpp \ @@ -109,7 +110,6 @@ SOURCES += \ kernel/qinputmethod.cpp \ kernel/qkeysequence.cpp \ kernel/qkeymapper.cpp \ - kernel/qkeymapper_qpa.cpp \ kernel/qpalette.cpp \ kernel/qguivariant.cpp \ kernel/qscreen.cpp \ @@ -119,20 +119,24 @@ SOURCES += \ kernel/qplatformsharedgraphicscache.cpp \ kernel/qplatformdialoghelper.cpp \ kernel/qplatformservices.cpp \ - kernel/qplatformscreenpageflipper.cpp \ - kernel/qplatformsystemtrayicon_qpa.cpp \ + kernel/qplatformsystemtrayicon.cpp \ kernel/qplatformsessionmanager.cpp \ - kernel/qplatformmenu.cpp + kernel/qplatformmenu.cpp \ + kernel/qpixelformat.cpp \ + kernel/qpaintdevicewindow.cpp \ + kernel/qrasterwindow.cpp contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) { HEADERS += \ kernel/qplatformopenglcontext.h \ kernel/qopenglcontext.h \ - kernel/qopenglcontext_p.h + kernel/qopenglcontext_p.h \ + kernel/qopenglwindow.h SOURCES += \ kernel/qplatformopenglcontext.cpp \ - kernel/qopenglcontext.cpp + kernel/qopenglcontext.cpp \ + kernel/qopenglwindow.cpp } win32:HEADERS+=kernel/qwindowdefs_win.h diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index 3c2d36ce86..672eb9eb65 100644 --- a/src/gui/kernel/qclipboard.cpp +++ b/src/gui/kernel/qclipboard.cpp @@ -50,6 +50,10 @@ #include "qimage.h" #include "qtextcodec.h" +#include "private/qguiapplication_p.h" +#include <qpa/qplatformintegration.h> +#include <qpa/qplatformclipboard.h> + QT_BEGIN_NAMESPACE /*! @@ -438,6 +442,12 @@ void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode) \sa setMimeData() */ +const QMimeData* QClipboard::mimeData(Mode mode) const +{ + QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); + if (!clipboard->supportsMode(mode)) return 0; + return clipboard->mimeData(mode); +} /*! \fn void QClipboard::setMimeData(QMimeData *src, Mode mode) @@ -458,6 +468,13 @@ void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode) \sa mimeData() */ +void QClipboard::setMimeData(QMimeData* src, Mode mode) +{ + QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); + if (!clipboard->supportsMode(mode)) return; + + clipboard->setMimeData(src,mode); +} /*! \fn void QClipboard::clear(Mode mode) @@ -472,7 +489,10 @@ void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode) \sa QClipboard::Mode, supportsSelection() */ - +void QClipboard::clear(Mode mode) +{ + setMimeData(0, mode); +} /*! Returns \c true if the clipboard supports mouse selection; otherwise @@ -527,6 +547,11 @@ bool QClipboard::ownsFindBuffer() const Returns \c true if the clipboard supports the clipboard mode speacified by \a mode; otherwise returns \c false. */ +bool QClipboard::supportsMode(Mode mode) const +{ + QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); + return clipboard->supportsMode(mode); +} /*! \internal @@ -534,6 +559,11 @@ bool QClipboard::ownsFindBuffer() const Returns \c true if the clipboard supports the clipboard data speacified by \a mode; otherwise returns \c false. */ +bool QClipboard::ownsMode(Mode mode) const +{ + QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); + return clipboard->ownsMode(mode); +} /*! \internal diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp index a33b264704..87774b2056 100644 --- a/src/gui/kernel/qcursor.cpp +++ b/src/gui/kernel/qcursor.cpp @@ -51,6 +51,9 @@ #include <private/qcursor_p.h> #include <qdebug.h> +#include <qpa/qplatformcursor.h> +#include <private/qguiapplication_p.h> + QT_BEGIN_NAMESPACE /*! @@ -172,6 +175,13 @@ QT_BEGIN_NAMESPACE \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal() */ +QPoint QCursor::pos(const QScreen *screen) +{ + if (screen) + if (const QPlatformCursor *cursor = screen->handle()->cursor()) + return cursor->pos(); + return QGuiApplicationPrivate::lastCursorPosition.toPoint(); +} /*! \fn QPoint QCursor::pos() @@ -191,7 +201,10 @@ QT_BEGIN_NAMESPACE \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen() */ - +QPoint QCursor::pos() +{ + return QCursor::pos(QGuiApplication::primaryScreen()); +} /*! \fn void QCursor::setPos(QScreen *screen, int x, int y) @@ -214,6 +227,19 @@ QT_BEGIN_NAMESPACE \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal() */ +void QCursor::setPos(QScreen *screen, int x, int y) +{ + if (screen) { + if (QPlatformCursor *cursor = screen->handle()->cursor()) { + const QPoint pos = QPoint(x, y); + // Need to check, since some X servers generate null mouse move + // events, causing looping in applications which call setPos() on + // every mouse move event. + if (pos != cursor->pos()) + cursor->setPos(pos); + } + } +} /*! \fn void QCursor::setPos(int x, int y) @@ -226,6 +252,10 @@ QT_BEGIN_NAMESPACE \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen() */ +void QCursor::setPos(int x, int y) +{ + QCursor::setPos(QGuiApplication::primaryScreen(), x, y); +} /*! \fn void QCursor::setPos (const QPoint &p) @@ -401,34 +431,6 @@ QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) d = QCursorData::setBitmap(bitmap, mask, hotX, hotY); } -QCursorData *qt_cursorTable[Qt::LastCursor + 1]; -bool QCursorData::initialized = false; - -/*! \internal */ -void QCursorData::cleanup() -{ - if(!QCursorData::initialized) - return; - - for (int shape = 0; shape <= Qt::LastCursor; ++shape) { - // In case someone has a static QCursor defined with this shape - if (!qt_cursorTable[shape]->ref.deref()) - delete qt_cursorTable[shape]; - qt_cursorTable[shape] = 0; - } - QCursorData::initialized = false; -} - -/*! \internal */ -void QCursorData::initialize() -{ - if (QCursorData::initialized) - return; - for (int shape = 0; shape <= Qt::LastCursor; ++shape) - qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape); - QCursorData::initialized = true; -} - /*! Constructs a cursor with the default arrow shape. */ @@ -602,6 +604,73 @@ QDebug operator<<(QDebug dbg, const QCursor &c) } #endif +/***************************************************************************** + Internal QCursorData class + *****************************************************************************/ + +QCursorData *qt_cursorTable[Qt::LastCursor + 1]; +bool QCursorData::initialized = false; + +QCursorData::QCursorData(Qt::CursorShape s) + : ref(1), cshape(s), bm(0), bmm(0), hx(0), hy(0) +{ +} + +QCursorData::~QCursorData() +{ + delete bm; + delete bmm; +} + +/*! \internal */ +void QCursorData::cleanup() +{ + if(!QCursorData::initialized) + return; + + for (int shape = 0; shape <= Qt::LastCursor; ++shape) { + // In case someone has a static QCursor defined with this shape + if (!qt_cursorTable[shape]->ref.deref()) + delete qt_cursorTable[shape]; + qt_cursorTable[shape] = 0; + } + QCursorData::initialized = false; +} + +/*! \internal */ +void QCursorData::initialize() +{ + if (QCursorData::initialized) + return; + for (int shape = 0; shape <= Qt::LastCursor; ++shape) + qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape); + QCursorData::initialized = true; +} + +QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) +{ + if (!QCursorData::initialized) + QCursorData::initialize(); + if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) { + qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)"); + QCursorData *c = qt_cursorTable[0]; + c->ref.ref(); + return c; + } + QCursorData *d = new QCursorData; + d->bm = new QBitmap(bitmap); + d->bmm = new QBitmap(mask); + d->cshape = Qt::BitmapCursor; + d->hx = hotX >= 0 ? hotX : bitmap.width() / 2; + d->hy = hotY >= 0 ? hotY : bitmap.height() / 2; + + return d; +} + +void QCursorData::update() +{ +} + QT_END_NAMESPACE #endif // QT_NO_CURSOR diff --git a/src/gui/kernel/qcursor_qpa.cpp b/src/gui/kernel/qcursor_qpa.cpp deleted file mode 100644 index 0b19a47c69..0000000000 --- a/src/gui/kernel/qcursor_qpa.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qcursor.h> -#include <qscreen.h> -#include <private/qcursor_p.h> -#include <qpa/qplatformcursor.h> -#include <private/qguiapplication_p.h> -#include <qbitmap.h> - -QT_BEGIN_NAMESPACE - -QT_USE_NAMESPACE - -#ifndef QT_NO_CURSOR - -/***************************************************************************** - Internal QCursorData class - *****************************************************************************/ - -QCursorData::QCursorData(Qt::CursorShape s) - : ref(1), cshape(s), bm(0), bmm(0), hx(0), hy(0) -{ -} - -QCursorData::~QCursorData() -{ - delete bm; - delete bmm; -} - - -/***************************************************************************** - Global cursors - *****************************************************************************/ - -extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp - -QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) -{ - if (!QCursorData::initialized) - QCursorData::initialize(); - if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) { - qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)"); - QCursorData *c = qt_cursorTable[0]; - c->ref.ref(); - return c; - } - QCursorData *d = new QCursorData; - d->bm = new QBitmap(bitmap); - d->bmm = new QBitmap(mask); - d->cshape = Qt::BitmapCursor; - d->hx = hotX >= 0 ? hotX : bitmap.width() / 2; - d->hy = hotY >= 0 ? hotY : bitmap.height() / 2; - - return d; -} - -void QCursorData::update() -{ -} - -#endif //QT_NO_CURSOR - -QPoint QCursor::pos() -{ - return QCursor::pos(QGuiApplication::primaryScreen()); -} - -QPoint QCursor::pos(const QScreen *screen) -{ - if (screen) - if (const QPlatformCursor *cursor = screen->handle()->cursor()) - return cursor->pos(); - return QGuiApplicationPrivate::lastCursorPosition.toPoint(); -} - -void QCursor::setPos(QScreen *screen, int x, int y) -{ - if (screen) { - if (QPlatformCursor *cursor = screen->handle()->cursor()) { - const QPoint pos = QPoint(x, y); - // Need to check, since some X servers generate null mouse move - // events, causing looping in applications which call setPos() on - // every mouse move event. - if (pos != cursor->pos()) - cursor->setPos(pos); - } - } -} - -void QCursor::setPos(int x, int y) -{ - QCursor::setPos(QGuiApplication::primaryScreen(), x, y); -} - -QT_END_NAMESPACE diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp index d34a135eb7..328ca389ed 100644 --- a/src/gui/kernel/qdnd.cpp +++ b/src/gui/kernel/qdnd.cpp @@ -142,6 +142,7 @@ Qt::DropAction QDragManager::drag(QDrag *o) QGuiApplicationPrivate::instance()->notifyDragStarted(o); const Qt::DropAction result = m_platformDrag->drag(m_object); m_object = 0; + o->deleteLater(); return result; } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index d6741af152..958df48f17 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -46,6 +46,7 @@ #include "qpa/qplatformdrag.h" #include "private/qevent_p.h" #include "qdebug.h" +#include "qmetaobject.h" #include "qmimedata.h" #include "private/qdnd_p.h" #include "qevent_p.h" @@ -287,6 +288,8 @@ QMouseEvent::~QMouseEvent() \l Qt::MouseEventNotSynthesized is returned always. \sa Qt::MouseEventSource + \sa QGraphicsSceneMouseEvent::source() + \sa QGraphicsSceneMouseEvent::setSource() */ Qt::MouseEventSource QMouseEvent::source() const { @@ -301,6 +304,8 @@ Qt::MouseEventSource QMouseEvent::source() const The mouse event flags provide additional information about a mouse event. \sa Qt::MouseEventFlag + \sa QGraphicsSceneMouseEvent::flags() + \sa QGraphicsSceneMouseEvent::setFlags() */ Qt::MouseEventFlags QMouseEvent::flags() const { @@ -1185,7 +1190,7 @@ Qt::FocusReason QFocusEvent::reason() const The event contains a region() that needs to be updated, and a rect() that is the bounding rectangle of that region. Both are - provided because many widgets can't make much use of region(), + provided because many widgets cannot make much use of region(), and rect() can be much faster than region().boundingRect(). \section1 Automatic Clipping @@ -1302,7 +1307,8 @@ QMoveEvent::~QMoveEvent() */ /*! - Constructs an expose event for the given \a exposeRegion. + Constructs an expose event for the given \a exposeRegion which must be + in local coordinates. */ QExposeEvent::QExposeEvent(const QRegion &exposeRegion) : QEvent(Expose) @@ -1320,7 +1326,7 @@ QExposeEvent::~QExposeEvent() /*! \fn const QRegion &QExposeEvent::region() const - Returns the window area that has been exposed. + Returns the window area that has been exposed. The region is given in local coordinates. */ /*! @@ -1977,40 +1983,63 @@ QVariant QInputMethodQueryEvent::value(Qt::InputMethodQuery query) const \ingroup events - Tablet Events are generated from a Wacom tablet. Most of the time you will - want to deal with events from the tablet as if they were events from a - mouse; for example, you would retrieve the cursor position with x(), y(), - pos(), globalX(), globalY(), and globalPos(). In some situations you may - wish to retrieve the extra information provided by the tablet device - driver; for example, you might want to do subpixeling with higher - resolution coordinates or you may want to adjust color brightness based on - pressure. QTabletEvent allows you to read the pressure(), the xTilt(), and - yTilt(), as well as the type of device being used with device() (see - \l{TabletDevice}). It can also give you the minimum and maximum values for - each device's pressure and high resolution coordinates. - - A tablet event contains a special accept flag that indicates whether the - receiver wants the event. You should call QTabletEvent::accept() if you - handle the tablet event; otherwise it will be sent to the parent widget. - The exception are TabletEnterProximity and TabletLeaveProximity events, - these are only sent to QApplication and don't check whether or not they are - accepted. - - The QWidget::setEnabled() function can be used to enable or - disable mouse and keyboard events for a widget. - - The event handler QWidget::tabletEvent() receives all three types of - tablet events. Qt will first send a tabletEvent then, if it is not - accepted, it will send a mouse event. This allows applications that - don't utilize tablets to use a tablet like a mouse, while also - enabling those who want to use both tablets and mouses differently. + \e{Tablet events} are generated from tablet peripherals such as Wacom + tablets and various other brands, and electromagnetic stylus devices + included with some types of tablet computers. (It is not the same as + \l QTouchEvent which a touchscreen generates, even when a passive stylus is + used on a touchscreen.) + + Tablet events are similar to mouse events; for example, the \l x(), \l y(), + \l pos(), \l globalX(), \l globalY(), and \l globalPos() accessors provide + the cursor position, and you can see which \l buttons() are pressed + (pressing the stylus tip against the tablet surface is equivalent to a left + mouse button). But tablet events also pass through some extra information + that the tablet device driver provides; for example, you might want to do + subpixel rendering with higher resolution coordinates (\l hiResGlobalX() + and \l hiResGlobalY()), adjust color brightness based on the \l pressure() + of the tool against the tablet surface, use different brushes depending on + the type of tool in use (\l device()), modulate the brush shape in some way + according to the X-axis and Y-axis tilt of the tool with respect to the + tablet surface (\l xTilt() and \l yTilt()), and use a virtual eraser + instead of a brush if the user switches to the other end of a double-ended + stylus (\l pointerType()). + + Every event contains an accept flag that indicates whether the receiver + wants the event. You should call QTabletEvent::accept() if you handle the + tablet event; otherwise it will be sent to the parent widget. The exception + are TabletEnterProximity and TabletLeaveProximity events: these are only + sent to QApplication and do not check whether or not they are accepted. + + The QWidget::setEnabled() function can be used to enable or disable + mouse, tablet and keyboard events for a widget. + + The event handler QWidget::tabletEvent() receives TabletPress, + TabletRelease and TabletMove events. Qt will first send a + tablet event, then if it is not accepted by any widget, it will send a + mouse event. This allows users of applications that are not designed for + tablets to use a tablet like a mouse. However high-resolution drawing + applications should handle the tablet events, because they can occur at a + higher frequency, which is a benefit for smooth and accurate drawing. + If the tablet events are rejected, the synthetic mouse events may be + compressed for efficiency. + + New in Qt 5.4: QTabletEvent includes all information available from the + device, including \l QTabletEvent::buttons(). Previously it was not + possible to accept all tablet events and also know which stylus buttons + were pressed. + + Note that pressing the stylus button while the stylus hovers over the + tablet will generate a button press on some types of tablets, while on + other types it will be necessary to press the stylus against the tablet + surface in order to register the simultaneous stylus button press. \section1 Notes for X11 Users - Qt uses the following hard-coded names to identify tablet - devices from the xorg.conf file on X11 (apart from IRIX): - 'stylus', 'pen', and 'eraser'. If the devices have other names, - they will not be picked up Qt. + If the tablet is configured in xorg.conf to use the Wacom driver, there + will be separate XInput "devices" for the stylus, eraser, and (optionally) + cursor and touchpad. Qt recognizes these by their names. Otherwise, if the + tablet is configured to use the evdev driver, there will be only one device + and applications may not be able to distinguish the stylus from the eraser. */ /*! @@ -2068,11 +2097,73 @@ QVariant QInputMethodQueryEvent::value(Qt::InputMethodQuery query) const The \a tangentialPressure parameter contins the tangential pressure of an air brush. If the device does not support tangential pressure, pass 0 here. + \a rotation contains the device's rotation in degrees. 4D mice and the Wacom + Art Pen support rotation. If the device does not support rotation, pass 0 here. + + The \a button that caused the event is given as a value from the + \l Qt::MouseButton enum. If the event \a type is not \l TabletPress or + \l TabletRelease, the appropriate button for this event is \l Qt::NoButton. + + \a buttons is the state of all buttons at the time of the event. + + \sa pos(), globalPos(), device(), pressure(), xTilt(), yTilt(), uniqueId(), rotation(), + tangentialPressure(), z() +*/ + +QTabletEvent::QTabletEvent(Type type, const QPointF &pos, const QPointF &globalPos, + int device, int pointerType, + qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, + qreal rotation, int z, Qt::KeyboardModifiers keyState, qint64 uniqueID, + Qt::MouseButton button, Qt::MouseButtons buttons) + : QInputEvent(type, keyState), + mPos(pos), + mGPos(globalPos), + mDev(device), + mPointerType(pointerType), + mXT(xTilt), + mYT(yTilt), + mZ(z), + mPress(pressure), + mTangential(tangentialPressure), + mRot(rotation), + mUnique(uniqueID), + mExtra(new QTabletEventPrivate(button, buttons)) +{ +} + +/*! + Construct a tablet event of the given \a type. + + The \a pos parameter indicates where the event occurred in the + widget; \a globalPos is the corresponding position in absolute + coordinates. + + \a pressure contains the pressure exerted on the \a device. + + \a pointerType describes the type of pen that is being used. + + \a xTilt and \a yTilt contain the device's degree of tilt from the + x and y axes respectively. + + \a keyState specifies which keyboard modifiers are pressed (e.g., + \uicontrol{Ctrl}). + + The \a uniqueID parameter contains the unique ID for the current device. + + The \a z parameter contains the coordinate of the device on the tablet, this + is usually given by a wheel on 4D mouse. If the device does not support a + Z-axis, pass zero here. + + The \a tangentialPressure parameter contins the tangential pressure of an air + brush. If the device does not support tangential pressure, pass 0 here. + \a rotation contains the device's rotation in degrees. 4D mice support rotation. If the device does not support rotation, pass 0 here. \sa pos(), globalPos(), device(), pressure(), xTilt(), yTilt(), uniqueId(), rotation(), tangentialPressure(), z() + + \deprecated in 5.4: use the constructor with MouseButton status */ QTabletEvent::QTabletEvent(Type type, const QPointF &pos, const QPointF &globalPos, @@ -2091,7 +2182,7 @@ QTabletEvent::QTabletEvent(Type type, const QPointF &pos, const QPointF &globalP mTangential(tangentialPressure), mRot(rotation), mUnique(uniqueID), - mExtra(0) + mExtra(new QTabletEventPrivate(Qt::NoButton, Qt::NoButton)) { } @@ -2103,6 +2194,34 @@ QTabletEvent::~QTabletEvent() } /*! + Returns the button that caused the event. + + Note that the returned value is always Qt::NoButton for \l TabletMove, + \l TabletEnterProximity and \l TabletLeaveProximity events. + + \sa buttons(), Qt::MouseButton +*/ +Qt::MouseButton QTabletEvent::button() const +{ + return static_cast<QTabletEventPrivate *>(mExtra)->b; +} + +/*! + Returns the button state when the event was generated. The button state is + a combination of buttons from the \l Qt::MouseButton enum using the OR + operator. For \l TabletMove events, this is all buttons that are pressed + down. For \l TabletPress events this includes the button that caused the + event. For \l TabletRelease events this excludes the button that caused the + event. + + \sa button(), Qt::MouseButton +*/ +Qt::MouseButtons QTabletEvent::buttons() const +{ + return static_cast<QTabletEventPrivate *>(mExtra)->buttonState; +} + +/*! \fn TabletDevices QTabletEvent::device() const Returns the type of device that generated the event. @@ -2132,7 +2251,7 @@ QTabletEvent::~QTabletEvent() \fn qreal QTabletEvent::rotation() const Returns the rotation of the current device in degress. This is usually - given by a 4D Mouse. If the device doesn't support rotation this value is + given by a 4D Mouse. If the device does not support rotation this value is always 0.0. */ @@ -3036,7 +3155,7 @@ QActionEvent::~QActionEvent() If spontaneous() is true, the event originated outside the application. In this case, the user hid the window using the window manager controls, either by iconifying the window or by - switching to another virtual desktop where the window isn't + switching to another virtual desktop where the window is not visible. The window will become hidden but not withdrawn. If the window was iconified, QWidget::isMinimized() returns \c true. @@ -3237,330 +3356,470 @@ QShortcutEvent::~QShortcutEvent() #ifndef QT_NO_DEBUG_STREAM +static inline void formatTouchPoint(QDebug d, const QTouchEvent::TouchPoint &tp) +{ + d << "TouchPoint(" << tp.id() << ' ' << tp.rect(); + switch (tp.state()) { + case Qt::TouchPointPressed: + d << " pressed"; + break; + case Qt::TouchPointReleased: + d << " released"; + break; + case Qt::TouchPointMoved: + d << " moved"; + break; + case Qt::TouchPointStationary: + d << " stationary"; + break; + } + d << ')'; +} + static inline void formatTouchEvent(QDebug d, const char *name, const QTouchEvent &t) { d << "QTouchEvent(" << name << " states: " << t.touchPointStates(); - const QList<QTouchEvent::TouchPoint> points = t.touchPoints(); - const int size = points.size(); - d << ", " << size << " points: "; - for (int i = 0; i < size; ++i) { + d << ", " << t.touchPoints().size() << " points: " << t.touchPoints() << ')'; +} + +static void formatUnicodeString(QDebug d, const QString &s) +{ + d << '"' << hex; + for (int i = 0; i < s.size(); ++i) { if (i) - d << ", "; - d << points.at(i).pos() << ' ' << points.at(i).rect(); - switch (points.at(i).state()) { - case Qt::TouchPointPressed: - d << " pressed"; - break; - case Qt::TouchPointReleased: - d << " released"; - break; - case Qt::TouchPointMoved: - d << " moved"; - break; - case Qt::TouchPointStationary: - d << " stationary"; - break; + d << ','; + d << "U+" << s.at(i).unicode(); + } + d << dec << '"'; +} + +static inline void formatInputMethodEvent(QDebug d, const QInputMethodEvent *e) +{ + d << "QInputMethodEvent("; + if (!e->preeditString().isEmpty()) { + d << "preedit="; + formatUnicodeString(d, e->preeditString()); + } + if (!e->commitString().isEmpty()) { + d << ", commit="; + formatUnicodeString(d, e->commitString()); + } + if (e->replacementLength()) { + d << ", replacementStart=" << e->replacementStart() << ", replacementLength=" + << e->replacementLength(); + } + if (const int attributeCount = e->attributes().size()) { + d << ", attributes= {"; + for (int a = 0; a < attributeCount; ++a) { + const QInputMethodEvent::Attribute &at = e->attributes().at(a); + if (a) + d << ','; + d << "[type= " << at.type << ", start=" << at.start << ", length=" << at.length + << ", value=" << at.value << ']'; } + d << '}'; } d << ')'; } -QDebug operator<<(QDebug dbg, const QEvent *e) { - // More useful event output could be added here - if (!e) - return dbg << "QEvent(this = 0x0)"; - const char *n = 0; - switch (e->type()) { - case QEvent::Timer: - n = "Timer"; - break; - case QEvent::MouseButtonPress: - case QEvent::MouseMove: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - { - const QMouseEvent *me = static_cast<const QMouseEvent*>(e); - switch(me->type()) { - case QEvent::MouseButtonPress: - n = "MouseButtonPress"; - break; - case QEvent::MouseMove: - n = "MouseMove"; - break; - case QEvent::MouseButtonRelease: - n = "MouseButtonRelease"; - break; - case QEvent::MouseButtonDblClick: - default: - n = "MouseButtonDblClick"; - break; +static inline void formatInputMethodQueryEvent(QDebug d, const QInputMethodQueryEvent *e) +{ + const Qt::InputMethodQueries queries = e->queries(); + d << "QInputMethodQueryEvent(queries=" << showbase << hex << int(queries) + << noshowbase << dec << ", {"; + for (unsigned mask = 1; mask <= Qt::ImTextAfterCursor; mask<<=1) { + if (queries & mask) { + const QVariant value = e->value(static_cast<Qt::InputMethodQuery>(mask)); + if (value.isValid()) + d << '[' << showbase << hex << mask << noshowbase << dec << '=' << value << "],"; } - QDebug nsp = dbg.nospace(); - nsp << "QMouseEvent(" << n - << ", " << me->button() - << ", " << hex << (int)me->buttons() - << ", " << hex << (int)me->modifiers() << dec; - if (const Qt::MouseEventSource source = me->source()) - nsp << ", source = " << source; - nsp << ')'; } - return dbg.space(); + d << "})"; +} -#ifndef QT_NO_TOOLTIP - case QEvent::ToolTip: - n = "ToolTip"; - break; -#endif - case QEvent::WindowActivate: - n = "WindowActivate"; - break; - case QEvent::WindowDeactivate: - n = "WindowDeactivate"; - break; - case QEvent::ActivationChange: - n = "ActivationChange"; - break; -#ifndef QT_NO_WHEELEVENT - case QEvent::Wheel: - dbg.nospace() << "QWheelEvent(" - << static_cast<const QWheelEvent *>(e)->pixelDelta() - << static_cast<const QWheelEvent *>(e)->angleDelta() - << ')'; - return dbg.space(); -#endif +static const char *eventTypeName(QEvent::Type t) +{ + static const int enumIdx = QEvent::staticMetaObject.indexOfEnumerator("Type"); + return t <= QEvent::User + ? QEvent::staticMetaObject.enumerator(enumIdx).valueToKey(t) + : "User"; +} + +static const char *eventClassName(QEvent::Type t) +{ + switch (t) { + case QEvent::ActionAdded: + case QEvent::ActionRemoved: + case QEvent::ActionChanged: + return "QActionEvent"; + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::NonClientAreaMouseMove: + case QEvent::NonClientAreaMouseButtonPress: + case QEvent::NonClientAreaMouseButtonRelease: + case QEvent::NonClientAreaMouseButtonDblClick: + return "QMouseEvent"; + case QEvent::DragEnter: + return "QDragEnterEvent"; + case QEvent::DragMove: + return "QDragMoveEvent"; + case QEvent::Drop: + return "QDropEvent"; case QEvent::KeyPress: case QEvent::KeyRelease: case QEvent::ShortcutOverride: - { - const QKeyEvent *ke = static_cast<const QKeyEvent*>(e); - switch(ke->type()) { - case QEvent::ShortcutOverride: - n = "ShortcutOverride"; - break; - case QEvent::KeyRelease: - n = "KeyRelease"; - break; - case QEvent::KeyPress: - default: - n = "KeyPress"; - break; - } - dbg.nospace() << "QKeyEvent(" << n - << ", " << hex << ke->key() - << ", " << hex << (int)ke->modifiers() - << ", \"" << ke->text() - << "\", " << ke->isAutoRepeat() - << ", " << ke->count() - << ')'; - } - return dbg.space(); + return "QKeyEvent"; case QEvent::FocusIn: - n = "FocusIn"; - break; case QEvent::FocusOut: - n = "FocusOut"; - break; - case QEvent::Enter: - n = "Enter"; - break; - case QEvent::Leave: - n = "Leave"; - break; - case QEvent::PaletteChange: - n = "PaletteChange"; - break; - case QEvent::PolishRequest: - n = "PolishRequest"; - break; - case QEvent::Polish: - n = "Polish"; - break; - case QEvent::UpdateRequest: - n = "UpdateRequest"; - break; + case QEvent::FocusAboutToChange: + return "QFocusEvent"; + case QEvent::ChildAdded: + case QEvent::ChildPolished: + case QEvent::ChildRemoved: + return "QChildEvent"; case QEvent::Paint: - n = "Paint"; - break; + return "QPaintEvent"; case QEvent::Move: - n = "Move"; - break; + return "QMoveEvent"; case QEvent::Resize: - n = "Resize"; - break; - case QEvent::Create: - n = "Create"; - break; - case QEvent::Destroy: - n = "Destroy"; - break; - case QEvent::Close: - n = "Close"; - break; - case QEvent::Quit: - n = "Quit"; - break; - case QEvent::FileOpen: - n = "FileOpen"; - break; + return "QResizeEvent"; case QEvent::Show: - n = "Show"; - break; - case QEvent::ShowToParent: - n = "ShowToParent"; - break; + return "QShowEvent"; case QEvent::Hide: - n = "Hide"; - break; - case QEvent::HideToParent: - n = "HideToParent"; - break; - case QEvent::None: - n = "None"; - break; - case QEvent::ParentChange: - n = "ParentChange"; - break; - case QEvent::ParentAboutToChange: - n = "ParentAboutToChange"; - break; + return "QHideEvent"; + case QEvent::Enter: + return "QEnterEvent"; + case QEvent::Close: + return "QCloseEvent"; + case QEvent::FileOpen: + return "QFileOpenEvent"; +#ifndef QT_NO_GESTURES + case QEvent::NativeGesture: + return "QNativeGestureEvent"; + case QEvent::Gesture: + case QEvent::GestureOverride: + return "QGestureEvent"; +#endif case QEvent::HoverEnter: - n = "HoverEnter"; - break; - case QEvent::HoverMove: - n = "HoverMove"; - break; case QEvent::HoverLeave: - n = "HoverLeave"; - break; - case QEvent::ZOrderChange: - n = "ZOrderChange"; - break; - case QEvent::StyleChange: - n = "StyleChange"; - break; - case QEvent::DragEnter: - n = "DragEnter"; - break; - case QEvent::DragMove: - n = "DragMove"; - break; - case QEvent::DragLeave: - n = "DragLeave"; - break; - case QEvent::Drop: - n = "Drop"; - break; + case QEvent::HoverMove: + return "QHoverEvent"; + case QEvent::TabletEnterProximity: + case QEvent::TabletLeaveProximity: + case QEvent::TabletPress: + case QEvent::TabletMove: + case QEvent::TabletRelease: + return "QTabletEvent"; + case QEvent::StatusTip: + return "QStatusTipEvent"; + case QEvent::ToolTip: + return "QHelpEvent"; + case QEvent::WindowStateChange: + return "QWindowStateChangeEvent"; + case QEvent::Wheel: + return "QWheelEvent"; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + return "QTouchEvent"; + case QEvent::Shortcut: + return "QShortcutEvent"; + case QEvent::InputMethod: + return "QInputMethodEvent"; + case QEvent::InputMethodQuery: + return "QInputMethodQueryEvent"; + case QEvent::OrientationChange: + return "QScreenOrientationChangeEvent"; + case QEvent::ScrollPrepare: + return "QScrollPrepareEvent"; + case QEvent::Scroll: + return "QScrollEvent"; case QEvent::GraphicsSceneMouseMove: - n = "GraphicsSceneMouseMove"; - break; case QEvent::GraphicsSceneMousePress: - n = "GraphicsSceneMousePress"; - break; case QEvent::GraphicsSceneMouseRelease: - n = "GraphicsSceneMouseRelease"; - break; case QEvent::GraphicsSceneMouseDoubleClick: - n = "GraphicsSceneMouseDoubleClick"; - break; + return "QGraphicsSceneMouseEvent"; case QEvent::GraphicsSceneContextMenu: - n = "GraphicsSceneContextMenu"; - break; case QEvent::GraphicsSceneHoverEnter: - n = "GraphicsSceneHoverEnter"; - break; case QEvent::GraphicsSceneHoverMove: - n = "GraphicsSceneHoverMove"; - break; case QEvent::GraphicsSceneHoverLeave: - n = "GraphicsSceneHoverLeave"; - break; case QEvent::GraphicsSceneHelp: - n = "GraphicsSceneHelp"; - break; case QEvent::GraphicsSceneDragEnter: - n = "GraphicsSceneDragEnter"; - break; case QEvent::GraphicsSceneDragMove: - n = "GraphicsSceneDragMove"; - break; case QEvent::GraphicsSceneDragLeave: - n = "GraphicsSceneDragLeave"; - break; case QEvent::GraphicsSceneDrop: - n = "GraphicsSceneDrop"; - break; case QEvent::GraphicsSceneWheel: - n = "GraphicsSceneWheel"; + return "QGraphicsSceneEvent"; + case QEvent::Timer: + return "QTimerEvent"; + default: break; - case QEvent::GraphicsSceneResize: - n = "GraphicsSceneResize"; + } + return "QEvent"; +} + +namespace { +// Make protected QObject::staticQtMetaObject accessible for formatting enums. +class DebugHelper : public QObject { +public: + static const char *mouseButtonToString(Qt::MouseButton button) + { + static const int enumIdx = QObject::staticQtMetaObject.indexOfEnumerator("MouseButtons"); + return QObject::staticQtMetaObject.enumerator(enumIdx).valueToKey(button); + } + + static QByteArray mouseButtonsToString(Qt::MouseButtons buttons) + { + QByteArray result; + for (int i = 0; (uint)(1 << i) <= Qt::MaxMouseButton; ++i) { + const Qt::MouseButton button = static_cast<Qt::MouseButton>(1 << i); + if (buttons.testFlag(button)) { + if (!result.isEmpty()) + result.append('|'); + result.append(mouseButtonToString(button)); + } + } + if (result.isEmpty()) + result.append("NoButton"); + return result; + } + + static const char *mouseEventSourceToString(Qt::MouseEventSource source) + { + static const int enumIdx = QObject::staticQtMetaObject.indexOfEnumerator("MouseEventSource"); + return QObject::staticQtMetaObject.enumerator(enumIdx).valueToKey(source); + } + + static const char *focusReasonToString(Qt::FocusReason reason) + { + static const int enumIdx = QObject::staticQtMetaObject.indexOfEnumerator("FocusReason"); + return QObject::staticQtMetaObject.enumerator(enumIdx).valueToKey(reason); + } + +# ifndef QT_NO_GESTURES + static const char *nativeGestureTypeToString(Qt::NativeGestureType type) + { + static const int enumIdx = QObject::staticQtMetaObject.indexOfEnumerator("NativeGestureType"); + return QObject::staticQtMetaObject.enumerator(enumIdx).valueToKey(type); + } +# endif // !QT_NO_GESTURES +}; +} // namespace + +# ifndef QT_NO_DRAGANDDROP + +static void formatDropEvent(QDebug d, const QDropEvent *e) +{ + const QEvent::Type type = e->type(); + d << eventClassName(type) << "(dropAction=" << e->dropAction() << ", proposedAction=" + << e->proposedAction() << ", possibleActions=" << e->possibleActions() + << ", posF=" << e->posF(); + if (type == QEvent::DragMove || type == QEvent::DragEnter) + d << ", answerRect=" << static_cast<const QDragMoveEvent *>(e)->answerRect(); + d << ", formats=" << e->mimeData()->formats(); + if (const Qt::KeyboardModifiers mods = e->keyboardModifiers()) + d << ", keyboardModifiers=" << mods; + d << ", " << DebugHelper::mouseButtonsToString(e->mouseButtons()).constData(); +} + +# endif // !QT_NO_DRAGANDDROP + +# ifndef QT_NO_TABLETEVENT + +static void formatTabletEvent(QDebug d, const QTabletEvent *e) +{ + const QEvent::Type type = e->type(); + + static const int deviceEnumIdx = QTabletEvent::staticMetaObject.indexOfEnumerator("TabletDevice"); + static const int pointerTypeEnumIdx = QTabletEvent::staticMetaObject.indexOfEnumerator("PointerType"); + const char* device = QTabletEvent::staticMetaObject.enumerator(deviceEnumIdx).valueToKey(e->device()); + const char* pointerType = QTabletEvent::staticMetaObject.enumerator(pointerTypeEnumIdx).valueToKey(e->pointerType()); + + d << eventClassName(type) << '(' << eventTypeName(type) + << ", device=" << device + << ", pointerType=" << pointerType + << ", uniqueId=" << e->uniqueId() + << ", pos=" << e->posF() + << ", z=" << e->z() + << ", xTilt=" << e->xTilt() + << ", yTilt=" << e->yTilt() + << ", " << DebugHelper::mouseButtonsToString(e->buttons()).constData(); + if (type == QEvent::TabletPress || type == QEvent::TabletMove) + d << ", pressure=" << e->pressure(); + if (e->device() == QTabletEvent::RotationStylus || e->device() == QTabletEvent::FourDMouse) + d << ", rotation=" << e->rotation(); + if (e->device() == QTabletEvent::Airbrush) + d << ", tangentialPressure=" << e->tangentialPressure(); +} + +# endif // !QT_NO_TABLETEVENT + +QDebug operator<<(QDebug dbg, const QTouchEvent::TouchPoint &tp) +{ + QDebugStateSaver saver(dbg); + dbg.nospace(); + formatTouchPoint(dbg, tp); + return dbg; +} + +QDebug operator<<(QDebug dbg, const QEvent *e) +{ + QDebugStateSaver saver(dbg); + dbg.nospace(); + if (!e) { + dbg << "QEvent(this = 0x0)"; + return dbg; + } + // More useful event output could be added here + const QEvent::Type type = e->type(); + switch (type) { + case QEvent::Expose: + dbg << "QExposeEvent(" << static_cast<const QExposeEvent *>(e)->region() << ')'; + break; + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::NonClientAreaMouseButtonPress: + case QEvent::NonClientAreaMouseMove: + case QEvent::NonClientAreaMouseButtonRelease: + case QEvent::NonClientAreaMouseButtonDblClick: + { + const QMouseEvent *me = static_cast<const QMouseEvent*>(e); + const Qt::MouseButton button = me->button(); + const Qt::MouseButtons buttons = me->buttons(); + dbg << "QMouseEvent(" << eventTypeName(type); + if (type != QEvent::MouseMove && type != QEvent::NonClientAreaMouseMove) + dbg << ", " << DebugHelper::mouseButtonToString(button); + if (buttons && button != buttons) + dbg << ", buttons=" << DebugHelper::mouseButtonsToString(buttons).constData(); + if (const int mods = int(me->modifiers())) + dbg << ", modifiers=0x" << hex << mods << dec; + dbg << ", localPos=" << me->localPos() << ", screenPos=" << me->screenPos(); + if (me->source()) + dbg << ", " << DebugHelper::mouseEventSourceToString(me->source()); + if (const Qt::MouseEventFlags flags = me->flags()) + dbg << ", flags = " << hex << int(flags) << dec; + dbg << ')'; + } break; - case QEvent::GraphicsSceneMove: - n = "GraphicsSceneMove"; +# ifndef QT_NO_WHEELEVENT + case QEvent::Wheel: { + const QWheelEvent *we = static_cast<const QWheelEvent *>(e); + dbg << "QWheelEvent(" << "pixelDelta=" << we->pixelDelta() << ", angleDelta=" << we->angleDelta() << ')'; + } break; - case QEvent::CursorChange: - n = "CursorChange"; +# endif // !QT_NO_WHEELEVENT + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::ShortcutOverride: + { + const QKeyEvent *ke = static_cast<const QKeyEvent *>(e); + dbg << "QKeyEvent(" << eventTypeName(type) + << ", key=0x" << hex << ke->key() << dec; + if (const int mods = ke->modifiers()) + dbg << ", modifiers=0x" << hex << mods << dec; + if (!ke->text().isEmpty()) + dbg << ", text=" << ke->text(); + if (ke->isAutoRepeat()) + dbg << ", autorepeat, count=" << ke->count(); + dbg << ')'; + } break; - case QEvent::ToolTipChange: - n = "ToolTipChange"; + case QEvent::Shortcut: { + const QShortcutEvent *se = static_cast<const QShortcutEvent *>(e); + dbg << "QShortcutEvent(" << se->key().toString() << ", id=" << se->shortcutId(); + if (se->isAmbiguous()) + dbg << ", ambiguous"; + dbg << ')'; + } break; - case QEvent::StatusTip: - n = "StatusTip"; + case QEvent::FocusAboutToChange: + case QEvent::FocusIn: + case QEvent::FocusOut: + dbg << "QFocusEvent(" << eventTypeName(type) << ", " + << DebugHelper::focusReasonToString(static_cast<const QFocusEvent *>(e)->reason()) + << ')'; break; - case QEvent::WhatsThis: - n = "WhatsThis"; + case QEvent::Move: { + const QMoveEvent *me = static_cast<const QMoveEvent *>(e); + dbg << "QMoveEvent(" << me->pos(); + if (!me->spontaneous()) + dbg << ", non-spontaneous"; + dbg << ')'; + } + break; + case QEvent::Resize: { + const QResizeEvent *re = static_cast<const QResizeEvent *>(e); + dbg << "QResizeEvent(" << re->size(); + if (!re->spontaneous()) + dbg << ", non-spontaneous"; + dbg << ')'; + } break; - case QEvent::FontChange: - n = "FontChange"; +# ifndef QT_NO_DRAGANDDROP + case QEvent::DragEnter: + case QEvent::DragMove: + case QEvent::Drop: + formatDropEvent(dbg, static_cast<const QDropEvent *>(e)); break; - case QEvent::Style: - n = "Style"; +# endif // !QT_NO_DRAGANDDROP + case QEvent::InputMethod: + formatInputMethodEvent(dbg, static_cast<const QInputMethodEvent *>(e)); break; - case QEvent::KeyboardLayoutChange: - n = "KeyboardLayoutChange"; + case QEvent::InputMethodQuery: + formatInputMethodQueryEvent(dbg, static_cast<const QInputMethodQueryEvent *>(e)); break; - case QEvent::DynamicPropertyChange: - n = "DynamicPropertyChange"; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + formatTouchEvent(dbg, eventTypeName(type), *static_cast<const QTouchEvent*>(e)); break; - case QEvent::GrabMouse: - n = "GrabMouse"; + case QEvent::ChildAdded: + case QEvent::ChildPolished: + case QEvent::ChildRemoved: + dbg << "QChildEvent(" << eventTypeName(type) << ", " << (static_cast<const QChildEvent*>(e))->child() << ')'; break; - case QEvent::UngrabMouse: - n = "UngrabMouse"; +# ifndef QT_NO_GESTURES + case QEvent::NativeGesture: { + const QNativeGestureEvent *ne = static_cast<const QNativeGestureEvent *>(e); + dbg << "QNativeGestureEvent(" << DebugHelper::nativeGestureTypeToString(ne->gestureType()) + << "localPos=" << ne->localPos() << ", value=" << ne->value() << ')'; + } + break; +# endif // !QT_NO_GESTURES + case QEvent::ApplicationStateChange: + dbg << "QApplicationStateChangeEvent(" + << static_cast<const QApplicationStateChangeEvent *>(e)->applicationState() << ')'; break; - case QEvent::GrabKeyboard: - n = "GrabKeyboard"; + case QEvent::ContextMenu: + dbg << "QContextMenuEvent(" << static_cast<const QContextMenuEvent *>(e)->pos() << ')'; break; - case QEvent::UngrabKeyboard: - n = "UngrabKeyboard"; +# ifndef QT_NO_TABLETEVENT + case QEvent::TabletEnterProximity: + case QEvent::TabletLeaveProximity: + case QEvent::TabletPress: + case QEvent::TabletMove: + case QEvent::TabletRelease: + formatTabletEvent(dbg, static_cast<const QTabletEvent *>(e)); break; - case QEvent::TouchBegin: - n = "TouchBegin"; - case QEvent::TouchUpdate: - n = n ? n : "TouchUpdate"; - case QEvent::TouchEnd: - n = n ? n : "TouchEnd"; - formatTouchEvent(dbg.nospace(), n, *static_cast<const QTouchEvent*>(e)); - return dbg.space(); - case QEvent::ChildAdded: n = n ? n : "ChildAdded"; - case QEvent::ChildPolished: n = n ? n : "ChildPolished"; - case QEvent::ChildRemoved: n = n ? n : "ChildRemoved"; - dbg.nospace() << "QChildEvent(" << n << ", " << (static_cast<const QChildEvent*>(e))->child(); - return dbg.space(); -#ifndef QT_NO_GESTURES - case QEvent::Gesture: - n = "Gesture"; +# endif // !QT_NO_TABLETEVENT + case QEvent::Enter: + dbg << "QEnterEvent(" << static_cast<const QEnterEvent *>(e)->pos() << ')'; + break; + case QEvent::Timer: + dbg << "QTimerEvent(id=" << static_cast<const QTimerEvent *>(e)->timerId() << ')'; break; -#endif default: - dbg.nospace() << "QEvent(" << (const void *)e << ", type = " << e->type() << ')'; - return dbg.space(); + dbg << eventClassName(type) << '(' << eventTypeName(type) << ", " + << (const void *)e << ", type = " << e->type() << ')'; + break; } - - dbg.nospace() << 'Q' << n << "Event(" << (const void *)e << ')'; - return dbg.space(); + return dbg; } -#endif +#endif // !QT_NO_DEBUG_STREAM /*! \class QShortcutEvent @@ -3570,7 +3829,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) { \ingroup events \inmodule QtGui - Normally you don't need to use this class directly; QShortcut + Normally you do not need to use this class directly; QShortcut provides a higher-level interface to handle shortcut keys. \sa QShortcut diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 0a826284c9..d128c34134 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -223,6 +223,9 @@ protected: #ifndef QT_NO_TABLETEVENT class Q_GUI_EXPORT QTabletEvent : public QInputEvent { + Q_GADGET + Q_ENUMS(TabletDevice) + Q_ENUMS(PointerType) public: enum TabletDevice { NoDevice, Puck, Stylus, Airbrush, FourDMouse, XFreeEraser /*internal*/, RotationStylus }; @@ -230,7 +233,12 @@ public: QTabletEvent(Type t, const QPointF &pos, const QPointF &globalPos, int device, int pointerType, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, - Qt::KeyboardModifiers keyState, qint64 uniqueID); + Qt::KeyboardModifiers keyState, qint64 uniqueID); // ### remove in Qt 6 + QTabletEvent(Type t, const QPointF &pos, const QPointF &globalPos, + int device, int pointerType, qreal pressure, int xTilt, int yTilt, + qreal tangentialPressure, qreal rotation, int z, + Qt::KeyboardModifiers keyState, qint64 uniqueID, + Qt::MouseButton button, Qt::MouseButtons buttons); ~QTabletEvent(); inline QPoint pos() const { return mPos.toPoint(); } @@ -257,6 +265,8 @@ public: inline qreal rotation() const { return mRot; } inline int xTilt() const { return mXT; } inline int yTilt() const { return mYT; } + Qt::MouseButton button() const; + Qt::MouseButtons buttons() const; protected: QPointF mPos, mGPos; @@ -264,9 +274,8 @@ protected: qreal mPress, mTangential, mRot; qint64 mUnique; - // I don't know what the future holds for tablets but there could be some - // new devices coming along, and there seem to be "holes" in the - // OS-specific events for this. + // QTabletEventPrivate for extra storage. + // ### Qt 6: QPointingEvent will have Buttons, QTabletEvent will inherit void *mExtra; }; #endif // QT_NO_TABLETEVENT @@ -377,8 +386,6 @@ public: inline const QRegion ®ion() const { return m_region; } protected: - friend class QApplication; - friend class QCoreApplication; QRect m_rect; QRegion m_region; bool m_erased; @@ -395,7 +402,6 @@ public: protected: QPoint p, oldp; friend class QApplication; - friend class QCoreApplication; }; class Q_GUI_EXPORT QExposeEvent : public QEvent @@ -421,7 +427,6 @@ public: protected: QSize s, olds; friend class QApplication; - friend class QCoreApplication; }; @@ -601,7 +606,6 @@ public: inline void ignore(const QRect & r) { ignore(); rect = r; } protected: - friend class QApplication; QRect rect; }; @@ -760,7 +764,11 @@ public: enum InfoFlag { Pen = 0x0001 }; +#ifndef Q_MOC_RUN + // otherwise moc gives + // Error: Meta object features not supported for nested classes Q_DECLARE_FLAGS(InfoFlags, InfoFlag) +#endif explicit TouchPoint(int id = -1); TouchPoint(const TouchPoint &other); @@ -881,6 +889,10 @@ protected: Q_DECLARE_TYPEINFO(QTouchEvent::TouchPoint, Q_MOVABLE_TYPE); Q_DECLARE_OPERATORS_FOR_FLAGS(QTouchEvent::TouchPoint::InfoFlags) +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QTouchEvent::TouchPoint &); +#endif + class Q_GUI_EXPORT QScrollPrepareEvent : public QEvent { public: diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index e01216e9f1..d24f3768a8 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -92,6 +92,20 @@ public: QVector<QPointF> rawScreenPositions; }; +#ifndef QT_NO_TABLETEVENT +class QTabletEventPrivate +{ +public: + inline QTabletEventPrivate(Qt::MouseButton button, Qt::MouseButtons buttons) + : b(button), + buttonState(buttons) + { } + + Qt::MouseButton b; + Qt::MouseButtons buttonState; +}; +#endif // QT_NO_TABLETEVENT + QT_END_NAMESPACE #endif // QEVENT_P_H diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 4727e754cd..51b1db8cf1 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -82,6 +82,7 @@ #include <qpa/qwindowsysteminterface_p.h> #include "private/qwindow_p.h" #include "private/qcursor_p.h" +#include "private/qopenglcontext_p.h" #include "private/qdnd_p.h" #include <qpa/qplatformthemefactory_p.h> @@ -118,7 +119,7 @@ Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier; QPointF QGuiApplicationPrivate::lastCursorPosition(qInf(), qInf()); -bool QGuiApplicationPrivate::tabletState = false; +Qt::MouseButtons QGuiApplicationPrivate::tabletState = Qt::NoButton; QWindow *QGuiApplicationPrivate::tabletPressTarget = 0; QWindow *QGuiApplicationPrivate::currentMouseWindow = 0; @@ -509,6 +510,7 @@ static QWindowGeometrySpecification windowGeometrySpecification; \li \c {-qwindowgeometry} \e geometry, specifies window geometry for the main window using the X11-syntax. For example: \c {-qwindowgeometry 100x100+50+50} + \li \c {-qwindowicon}, sets the default window icon \li \c {-qwindowtitle}, sets the title of the first window \li \c{-reverse}, sets the application's layout direction to Qt::RightToLeft. This option is intended to aid debugging and should @@ -606,7 +608,8 @@ QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv, int flags : QCoreApplicationPrivate(argc, argv, flags), styleHints(0), inputMethod(0), - lastTouchType(QEvent::TouchEnd) + lastTouchType(QEvent::TouchEnd), + ownGlobalShareContext(false) { self = this; application_type = QCoreApplicationPrivate::Gui; @@ -903,7 +906,19 @@ QList<QScreen *> QGuiApplication::screens() This signal is emitted whenever a new screen \a screen has been added to the system. - \sa screens(), primaryScreen() + \sa screens(), primaryScreen(), screenRemoved() +*/ + +/*! + \fn void QGuiApplication::screenRemoved(QScreen *screen) + + This signal is emitted whenever a \a screen is removed from the system. It + provides an opportunity to manage the windows on the screen before Qt falls back + to moving them to the primary screen. + + \sa screens(), screenAdded(), QObject::destroyed(), QWindow::setScreen() + + \since 5.4 */ @@ -1115,12 +1130,15 @@ void QGuiApplicationPrivate::createPlatformIntegration() // Get command line params + QString icon; + int j = argc ? 1 : 0; for (int i=1; i<argc; i++) { if (argv[i] && *argv[i] != '-') { argv[j++] = argv[i]; continue; } + const bool isXcb = platformName == "xcb"; QByteArray arg = argv[i]; if (arg.startsWith("--")) arg.remove(0, 1); @@ -1133,12 +1151,16 @@ void QGuiApplicationPrivate::createPlatformIntegration() } else if (arg == "-platformtheme") { if (++i < argc) platformThemeName = QString::fromLocal8Bit(argv[i]); - } else if (arg == "-qwindowgeometry" || (platformName == "xcb" && arg == "-geometry")) { + } else if (arg == "-qwindowgeometry" || (isXcb && arg == "-geometry")) { if (++i < argc) windowGeometrySpecification = QWindowGeometrySpecification::fromArgument(argv[i]); - } else if (arg == "-qwindowtitle" || (platformName == "xcb" && arg == "-title")) { + } else if (arg == "-qwindowtitle" || (isXcb && arg == "-title")) { if (++i < argc) firstWindowTitle = QString::fromLocal8Bit(argv[i]); + } else if (arg == "-qwindowicon" || (isXcb && arg == "-icon")) { + if (++i < argc) { + icon = QString::fromLocal8Bit(argv[i]); + } } else { argv[j++] = argv[i]; } @@ -1151,6 +1173,8 @@ void QGuiApplicationPrivate::createPlatformIntegration() init_platform(QLatin1String(platformName), platformPluginPath, platformThemeName, argc, argv); + if (!icon.isEmpty()) + forcedWindowIcon = QDir::isAbsolutePath(icon) ? QIcon(icon) : QIcon::fromTheme(icon); } /*! @@ -1296,6 +1320,17 @@ void QGuiApplicationPrivate::init() qRegisterGuiGetInterpolator(); #endif + // set a global share context when enabled unless there is already one +#ifndef QT_NO_OPENGL + if (qApp->testAttribute(Qt::AA_ShareOpenGLContexts) && !qt_gl_global_share_context()) { + QOpenGLContext *ctx = new QOpenGLContext; + ctx->setFormat(QSurfaceFormat::defaultFormat()); + ctx->create(); + qt_gl_set_global_share_context(ctx); + ownGlobalShareContext = true; + } +#endif + QWindowSystemInterfacePrivate::eventTime.start(); is_app_running = true; @@ -1357,6 +1392,13 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate() QPixmapCache::clear(); +#ifndef QT_NO_OPENGL + if (ownGlobalShareContext) { + delete qt_gl_global_share_context(); + qt_gl_set_global_share_context(0); + } +#endif + delete platform_theme; platform_theme = 0; delete platform_integration; @@ -1454,6 +1496,20 @@ QPlatformNativeInterface *QGuiApplication::platformNativeInterface() } /*! + Returns a function pointer from the platformplugin matching \a function +*/ +QFunctionPointer QGuiApplication::platformFunction(const QByteArray &function) +{ + QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration(); + if (!pi) { + qWarning() << "QGuiApplication::platformFunction(): Must construct a QGuiApplication before accessing a platform function"; + return Q_NULLPTR; + } + + return pi->nativeInterface() ? pi->nativeInterface()->platformFunction(function) : Q_NULLPTR; +} + +/*! Enters the main event loop and waits until exit() is called, and then returns the value that was set to exit() (which is 0 if exit() is called via quit()). @@ -1576,8 +1632,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv case QWindowSystemInterfacePrivate::WindowScreenChanged: QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowScreenChangedEvent *>(e)); break; - case QWindowSystemInterfacePrivate::ApplicationStateChanged: - QGuiApplicationPrivate::setApplicationState(static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e)->newState); + case QWindowSystemInterfacePrivate::ApplicationStateChanged: { + QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e); + QGuiApplicationPrivate::setApplicationState(changeEvent->newState, changeEvent->forcePropagate); } break; case QWindowSystemInterfacePrivate::FlushEvents: QWindowSystemInterface::deferredFlushWindowSystemEvents(); @@ -1594,10 +1651,6 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv QGuiApplicationPrivate::reportGeometryChange( static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e)); break; - case QWindowSystemInterfacePrivate::ScreenAvailableGeometry: - QGuiApplicationPrivate::reportAvailableGeometryChange( - static_cast<QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *>(e)); - break; case QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInch: QGuiApplicationPrivate::reportLogicalDotsPerInchChange( static_cast<QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *>(e)); @@ -1664,7 +1717,8 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo // with the current event, we fake a move-only event that we recurse and process first. This // will update the global mouse position and cause the second event to be a button only event. QWindowSystemInterfacePrivate::MouseEvent moveEvent(e->window.data(), - e->timestamp, e->type, e->localPos, e->globalPos, buttons, e->modifiers); + e->timestamp, e->type, e->localPos, e->globalPos, buttons, e->modifiers, e->source); + moveEvent.synthetic = e->synthetic; processMouseEvent(&moveEvent); Q_ASSERT(e->globalPos == QGuiApplicationPrivate::lastCursorPosition); // continue with processing mouse button change event @@ -1854,13 +1908,17 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE ev.setAccepted(false); static bool backKeyPressAccepted = false; + static bool menuKeyPressAccepted = false; if (e->keyType == QEvent::KeyPress) { backKeyPressAccepted = e->key == Qt::Key_Back && ev.isAccepted(); - } else if (e->keyType == QEvent::KeyRelease && e->key == Qt::Key_Back && !backKeyPressAccepted && !ev.isAccepted()) { - if (!window) - qApp->quit(); - else - QWindowSystemInterface::handleCloseEvent(window); + menuKeyPressAccepted = e->key == Qt::Key_Menu && ev.isAccepted(); + } else if (e->keyType == QEvent::KeyRelease) { + if (e->key == Qt::Key_Back && !backKeyPressAccepted && !ev.isAccepted()) { + if (window) + QWindowSystemInterface::handleCloseEvent(window); + } else if (e->key == Qt::Key_Menu && !menuKeyPressAccepted && !ev.isAccepted()) { + platform_theme->showPlatformMenuBar(); + } } #endif } @@ -1972,7 +2030,7 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf { if (QWindow *window = wse->window.data()) { if (QScreen *screen = wse->screen.data()) - window->d_func()->setScreen(screen, false /* recreate */); + window->d_func()->setTopLevelScreen(screen, false /* recreate */); else // Fall back to default behavior, and try to find some appropriate screen window->setScreen(0); } @@ -2058,10 +2116,8 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T { #ifndef QT_NO_TABLETEVENT QEvent::Type type = QEvent::TabletMove; - if (e->down != tabletState) { - type = e->down ? QEvent::TabletPress : QEvent::TabletRelease; - tabletState = e->down; - } + if (e->buttons != tabletState) + type = (e->buttons > tabletState) ? QEvent::TabletPress : QEvent::TabletRelease; QWindow *window = e->window.data(); modifier_buttons = e->modifiers; @@ -2093,12 +2149,21 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T QPointF delta = e->global - e->global.toPoint(); local = window->mapFromGlobal(e->global.toPoint()) + delta; } + Qt::MouseButtons stateChange = e->buttons ^ tabletState; + Qt::MouseButton button = Qt::NoButton; + for (int check = Qt::LeftButton; check <= int(Qt::MaxMouseButton); check = check << 1) { + if (check & stateChange) { + button = Qt::MouseButton(check); + break; + } + } QTabletEvent ev(type, local, e->global, e->device, e->pointerType, e->pressure, e->xTilt, e->yTilt, e->tangentialPressure, e->rotation, e->z, - e->modifiers, e->uid); + e->modifiers, e->uid, button, e->buttons); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(window, &ev); + tabletState = e->buttons; #else Q_UNUSED(e) #endif @@ -2110,7 +2175,7 @@ void QGuiApplicationPrivate::processTabletEnterProximityEvent(QWindowSystemInter QTabletEvent ev(QEvent::TabletEnterProximity, QPointF(), QPointF(), e->device, e->pointerType, 0, 0, 0, 0, 0, 0, - Qt::NoModifier, e->uid); + Qt::NoModifier, e->uid, Qt::NoButton, tabletState); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev); #else @@ -2124,7 +2189,7 @@ void QGuiApplicationPrivate::processTabletLeaveProximityEvent(QWindowSystemInter QTabletEvent ev(QEvent::TabletLeaveProximity, QPointF(), QPointF(), e->device, e->pointerType, 0, 0, 0, 0, 0, 0, - Qt::NoModifier, e->uid); + Qt::NoModifier, e->uid, Qt::NoButton, tabletState); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev); #else @@ -2213,7 +2278,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To e->timestamp, synthIt->pos, synthIt->screenPos, - Qt::NoButton, + buttons & ~Qt::LeftButton, e->modifiers, Qt::MouseEventSynthesizedByQt); fake.synthetic = true; @@ -2415,7 +2480,9 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To QWindowSystemInterfacePrivate::MouseEvent fake(w, e->timestamp, touchPoint.pos(), touchPoint.screenPos(), - b, e->modifiers); + b | (buttons & ~Qt::LeftButton), + e->modifiers, + Qt::MouseEventSynthesizedByQt); fake.synthetic = true; processMouseEvent(&fake); break; @@ -2483,40 +2550,36 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate: return; QScreen *s = e->screen.data(); - s->d_func()->geometry = e->geometry; - Qt::ScreenOrientation primaryOrientation = s->primaryOrientation(); - s->d_func()->updatePrimaryOrientation(); + bool geometryChanged = e->geometry != s->d_func()->geometry; + s->d_func()->geometry = e->geometry; - emit s->geometryChanged(s->geometry()); - emit s->physicalSizeChanged(s->physicalSize()); - emit s->physicalDotsPerInchChanged(s->physicalDotsPerInch()); - emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch()); - foreach (QScreen* sibling, s->virtualSiblings()) - emit sibling->virtualGeometryChanged(sibling->virtualGeometry()); + bool availableGeometryChanged = e->availableGeometry != s->d_func()->availableGeometry; + s->d_func()->availableGeometry = e->availableGeometry; - if (s->primaryOrientation() != primaryOrientation) - emit s->primaryOrientationChanged(s->primaryOrientation()); + if (geometryChanged) { + Qt::ScreenOrientation primaryOrientation = s->primaryOrientation(); + s->d_func()->updatePrimaryOrientation(); - if (s->d_func()->orientation == Qt::PrimaryOrientation) - updateFilteredScreenOrientation(s); -} + emit s->geometryChanged(s->geometry()); + emit s->physicalSizeChanged(s->physicalSize()); + emit s->physicalDotsPerInchChanged(s->physicalDotsPerInch()); + emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch()); -void QGuiApplicationPrivate::reportAvailableGeometryChange( - QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e) -{ - // This operation only makes sense after the QGuiApplication constructor runs - if (QCoreApplication::startingUp()) - return; + if (s->primaryOrientation() != primaryOrientation) + emit s->primaryOrientationChanged(s->primaryOrientation()); - if (!e->screen) - return; + if (s->d_func()->orientation == Qt::PrimaryOrientation) + updateFilteredScreenOrientation(s); + } - QScreen *s = e->screen.data(); - s->d_func()->availableGeometry = e->availableGeometry; + if (availableGeometryChanged) + emit s->availableGeometryChanged(s->geometry()); - foreach (QScreen* sibling, s->virtualSiblings()) - emit sibling->virtualGeometryChanged(sibling->virtualGeometry()); + if (geometryChanged || availableGeometryChanged) { + foreach (QScreen* sibling, s->virtualSiblings()) + emit sibling->virtualGeometryChanged(sibling->virtualGeometry()); + } } void QGuiApplicationPrivate::reportLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e) @@ -2656,6 +2719,15 @@ QClipboard * QGuiApplication::clipboard() #endif /*! + \since 5.4 + \fn void QGuiApplication::paletteChanged(const QPalette &palette) + + This signal is emitted when the \a palette of the application changes. + + \sa palette() +*/ + +/*! Returns the default application palette. \sa setPalette() @@ -2681,6 +2753,7 @@ void QGuiApplication::setPalette(const QPalette &pal) else *QGuiApplicationPrivate::app_pal = pal; applicationResourceFlags |= ApplicationPaletteExplicitlySet; + emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal); } QRect QGuiApplicationPrivate::applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window) @@ -2890,9 +2963,9 @@ Qt::ApplicationState QGuiApplication::applicationState() \sa applicationState() */ -void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state) +void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, bool forcePropagate) { - if (applicationState == state) + if ((applicationState == state) && !forcePropagate) return; applicationState = state; @@ -3093,6 +3166,8 @@ void QGuiApplicationPrivate::saveState() On system start-up, the default layout direction depends on the application's language. + The notifier signal was introduced in Qt 5.4. + \sa QWidget::layoutDirection, isLeftToRight(), isRightToLeft() */ @@ -3103,7 +3178,10 @@ void QGuiApplication::setLayoutDirection(Qt::LayoutDirection direction) layout_direction = direction; - QGuiApplicationPrivate::self->notifyLayoutDirectionChange(); + if (qGuiApp) { + emit qGuiApp->layoutDirectionChanged(direction); + QGuiApplicationPrivate::self->notifyLayoutDirectionChange(); + } } Qt::LayoutDirection QGuiApplication::layoutDirection() diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h index 6d9a4b2376..6e751e1275 100644 --- a/src/gui/kernel/qguiapplication.h +++ b/src/gui/kernel/qguiapplication.h @@ -75,7 +75,7 @@ class Q_GUI_EXPORT QGuiApplication : public QCoreApplication Q_OBJECT Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon) Q_PROPERTY(QString applicationDisplayName READ applicationDisplayName WRITE setApplicationDisplayName) - Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection) + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(QString platformName READ platformName STORED false) Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed) @@ -143,6 +143,8 @@ public: static QPlatformNativeInterface *platformNativeInterface(); + static QFunctionPointer platformFunction(const QByteArray &function); + static void setQuitOnLastWindowClosed(bool quit); static bool quitOnLastWindowClosed(); @@ -163,14 +165,17 @@ public: Q_SIGNALS: void fontDatabaseChanged(); void screenAdded(QScreen *screen); + void screenRemoved(QScreen *screen); void lastWindowClosed(); void focusObjectChanged(QObject *focusObject); void focusWindowChanged(QWindow *focusWindow); void applicationStateChanged(Qt::ApplicationState state); + void layoutDirectionChanged(Qt::LayoutDirection direction); #ifndef QT_NO_SESSIONMANAGER void commitDataRequest(QSessionManager &sessionManager); void saveStateRequest(QSessionManager &sessionManager); #endif + void paletteChanged(const QPalette &pal); protected: bool event(QEvent *); diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 1ec808ec27..d82abfe20a 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -137,7 +137,6 @@ public: static void reportScreenOrientationChange(QScreen *screen); static void reportScreenOrientationChange(QWindowSystemInterfacePrivate::ScreenOrientationEvent *e); static void reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e); - static void reportAvailableGeometryChange(QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e); static void reportLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e); static void reportRefreshRateChange(QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *e); static void processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *tce); @@ -207,7 +206,7 @@ public: static int mousePressY; static int mouse_double_click_distance; static QPointF lastCursorPosition; - static bool tabletState; + static Qt::MouseButtons tabletState; static QWindow *tabletPressTarget; static QWindow *currentMouseWindow; static Qt::ApplicationState applicationState; @@ -234,6 +233,7 @@ public: QInputMethod *inputMethod; QString firstWindowTitle; + QIcon forcedWindowIcon; static QList<QObject *> generic_plugin_list; #ifndef QT_NO_SHORTCUT @@ -288,7 +288,7 @@ public: static QRect applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window); - static void setApplicationState(Qt::ApplicationState state); + static void setApplicationState(Qt::ApplicationState state, bool forcePropagate = false); protected: virtual void notifyThemeChanged(); @@ -306,6 +306,8 @@ private: static QTouchDevice *m_fakeTouchDevice; static int m_fakeMouseSourcePointId; QAtomicPointer<QDrawHelperGammaTables> m_gammaTables; + + bool ownGlobalShareContext; }; Q_GUI_EXPORT uint qHash(const QGuiApplicationPrivate::ActiveTouchPointsKey &k); diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp index 0e150a9c1e..2ec72fd2d0 100644 --- a/src/gui/kernel/qkeymapper.cpp +++ b/src/gui/kernel/qkeymapper.cpp @@ -45,6 +45,9 @@ #include <private/qobject_p.h> #include "qkeymapper_p.h" +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> + QT_BEGIN_NAMESPACE /*! @@ -117,4 +120,32 @@ QKeyMapperPrivate *qt_keymapper_private() return QKeyMapper::instance()->d_func(); } +QKeyMapperPrivate::QKeyMapperPrivate() +{ + keyboardInputLocale = QLocale::system(); + keyboardInputDirection = keyboardInputLocale.textDirection(); +} + +QKeyMapperPrivate::~QKeyMapperPrivate() +{ + // clearMappings(); +} + +void QKeyMapperPrivate::clearMappings() +{ +} + +QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e) +{ + QList<int> result = QGuiApplicationPrivate::platformIntegration()->possibleKeys(e); + if (!result.isEmpty()) + return result; + + if (e->key() && (e->key() != Qt::Key_unknown)) + result << int(e->key() + e->modifiers()); + else if (!e->text().isEmpty()) + result << int(e->text().at(0).unicode() + e->modifiers()); + return result; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 59cdabbc0f..8261ac7208 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -490,7 +490,7 @@ static const struct { { Qt::Key_BrightnessAdjust, QT_TRANSLATE_NOOP("QShortcut", "Adjust Brightness") }, { Qt::Key_Finance, QT_TRANSLATE_NOOP("QShortcut", "Finance") }, { Qt::Key_Community, QT_TRANSLATE_NOOP("QShortcut", "Community") }, - { Qt::Key_AudioRewind, QT_TRANSLATE_NOOP("QShortcut", "Audio Rewind") }, + { Qt::Key_AudioRewind, QT_TRANSLATE_NOOP("QShortcut", "Media Rewind") }, { Qt::Key_BackForward, QT_TRANSLATE_NOOP("QShortcut", "Back Forward") }, { Qt::Key_ApplicationLeft, QT_TRANSLATE_NOOP("QShortcut", "Application Left") }, { Qt::Key_ApplicationRight, QT_TRANSLATE_NOOP("QShortcut", "Application Right") }, @@ -550,17 +550,40 @@ static const struct { { Qt::Key_Bluetooth, QT_TRANSLATE_NOOP("QShortcut", "Bluetooth") }, { Qt::Key_WLAN, QT_TRANSLATE_NOOP("QShortcut", "Wireless") }, { Qt::Key_UWB, QT_TRANSLATE_NOOP("QShortcut", "Ultra Wide Band") }, - { Qt::Key_AudioForward, QT_TRANSLATE_NOOP("QShortcut", "Audio Forward") }, + { Qt::Key_AudioForward, QT_TRANSLATE_NOOP("QShortcut", "Media Fast Forward") }, { Qt::Key_AudioRepeat, QT_TRANSLATE_NOOP("QShortcut", "Audio Repeat") }, { Qt::Key_AudioRandomPlay, QT_TRANSLATE_NOOP("QShortcut", "Audio Random Play") }, { Qt::Key_Subtitle, QT_TRANSLATE_NOOP("QShortcut", "Subtitle") }, { Qt::Key_AudioCycleTrack, QT_TRANSLATE_NOOP("QShortcut", "Audio Cycle Track") }, { Qt::Key_Time, QT_TRANSLATE_NOOP("QShortcut", "Time") }, - { Qt::Key_Select, QT_TRANSLATE_NOOP("QShortcut", "Select") }, + { Qt::Key_Hibernate, QT_TRANSLATE_NOOP("QShortcut", "Hibernate") }, { Qt::Key_View, QT_TRANSLATE_NOOP("QShortcut", "View") }, { Qt::Key_TopMenu, QT_TRANSLATE_NOOP("QShortcut", "Top Menu") }, + { Qt::Key_PowerDown, QT_TRANSLATE_NOOP("QShortcut", "Power Down") }, { Qt::Key_Suspend, QT_TRANSLATE_NOOP("QShortcut", "Suspend") }, - { Qt::Key_Hibernate, QT_TRANSLATE_NOOP("QShortcut", "Hibernate") }, + + { Qt::Key_MicMute, QT_TRANSLATE_NOOP("QShortcut", "Microphone Mute") }, + + { Qt::Key_Red, QT_TRANSLATE_NOOP("QShortcut", "Red") }, + { Qt::Key_Green, QT_TRANSLATE_NOOP("QShortcut", "Green") }, + { Qt::Key_Yellow, QT_TRANSLATE_NOOP("QShortcut", "Yellow") }, + { Qt::Key_Blue, QT_TRANSLATE_NOOP("QShortcut", "Blue") }, + + { Qt::Key_ChannelUp, QT_TRANSLATE_NOOP("QShortcut", "Channel Up") }, + { Qt::Key_ChannelDown, QT_TRANSLATE_NOOP("QShortcut", "Channel Down") }, + + { Qt::Key_Guide, QT_TRANSLATE_NOOP("QShortcut", "Guide") }, + { Qt::Key_Info, QT_TRANSLATE_NOOP("QShortcut", "Info") }, + { Qt::Key_Settings, QT_TRANSLATE_NOOP("QShortcut", "Settings") }, + + { Qt::Key_MicVolumeUp, QT_TRANSLATE_NOOP("QShortcut", "Microphone Volume Up") }, + { Qt::Key_MicVolumeDown, QT_TRANSLATE_NOOP("QShortcut", "Microphone Volume Down") }, + + { Qt::Key_New, QT_TRANSLATE_NOOP("QShortcut", "New") }, + { Qt::Key_Open, QT_TRANSLATE_NOOP("QShortcut", "Open") }, + { Qt::Key_Find, QT_TRANSLATE_NOOP("QShortcut", "Find") }, + { Qt::Key_Undo, QT_TRANSLATE_NOOP("QShortcut", "Undo") }, + { Qt::Key_Redo, QT_TRANSLATE_NOOP("QShortcut", "Redo") }, // -------------------------------------------------------------- // More consistent namings @@ -647,6 +670,7 @@ static const struct { { Qt::Key_Execute, QT_TRANSLATE_NOOP("QShortcut", "Execute") }, { Qt::Key_Play, QT_TRANSLATE_NOOP("QShortcut", "Play") }, { Qt::Key_Zoom, QT_TRANSLATE_NOOP("QShortcut", "Zoom") }, + { Qt::Key_Exit, QT_TRANSLATE_NOOP("QShortcut", "Exit") }, { 0, 0 } }; diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp index 003e3a0cc9..0307a4a2ad 100644 --- a/src/gui/kernel/qoffscreensurface.cpp +++ b/src/gui/kernel/qoffscreensurface.cpp @@ -90,6 +90,7 @@ public: , surfaceType(QSurface::OpenGLSurface) , platformOffscreenSurface(0) , offscreenWindow(0) + , requestedFormat(QSurfaceFormat::defaultFormat()) , screen(0) , size(1, 1) { diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 406c784c5c..be8fa2415d 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -63,6 +63,7 @@ #ifndef QT_OPENGL_ES_2 #include <QOpenGLFunctions_1_0> +#include <QOpenGLFunctions_3_2_Core> #endif QT_BEGIN_NAMESPACE @@ -242,6 +243,28 @@ QMutex QOpenGLContextPrivate::makeCurrentTrackerMutex; #endif /*! + \internal + + This function is used by Qt::AA_ShareOpenGLContexts and the Qt + WebEngine to set up context sharing across multiple windows. Do + not use it for any other purpose. + + Please maintain the binary compatibility of these functions. +*/ +void qt_gl_set_global_share_context(QOpenGLContext *context) +{ + global_share_context = context; +} + +/*! + \internal +*/ +QOpenGLContext *qt_gl_global_share_context() +{ + return global_share_context; +} + +/*! \class QOpenGLContext \inmodule QtGui \since 5.0 @@ -335,23 +358,14 @@ QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context return previous; } -/*! - \internal - - This function is used by the Qt WebEngine to set up context sharing - across multiple windows. Do not use it for any other purpose. -*/ void QOpenGLContextPrivate::setGlobalShareContext(QOpenGLContext *context) { - global_share_context = context; + qt_gl_set_global_share_context(context); } -/*! - \internal -*/ QOpenGLContext *QOpenGLContextPrivate::globalShareContext() { - return global_share_context; + return qt_gl_global_share_context(); } int QOpenGLContextPrivate::maxTextureSize() @@ -370,9 +384,25 @@ int QOpenGLContextPrivate::maxTextureSize() GLint size; GLint next = 64; funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - QOpenGLFunctions_1_0 *gl1funcs = q->versionFunctions<QOpenGLFunctions_1_0>(); - gl1funcs->initializeOpenGLFunctions(); - gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size); + + QOpenGLFunctions_1_0 *gl1funcs = 0; + QOpenGLFunctions_3_2_Core *gl3funcs = 0; + + if (q->format().profile() == QSurfaceFormat::CoreProfile) { + gl3funcs = q->versionFunctions<QOpenGLFunctions_3_2_Core>(); + gl3funcs->initializeOpenGLFunctions(); + } else { + gl1funcs = q->versionFunctions<QOpenGLFunctions_1_0>(); + gl1funcs->initializeOpenGLFunctions(); + } + + Q_ASSERT(gl1funcs || gl3funcs); + + if (gl1funcs) + gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size); + else + gl3funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size); + if (size == 0) { return max_texture_size; } @@ -383,7 +413,11 @@ int QOpenGLContextPrivate::maxTextureSize() if (next > max_texture_size) break; funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next); + if (gl1funcs) + gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next); + else + gl3funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next); + } while (next > size); max_texture_size = size; @@ -456,6 +490,12 @@ QOpenGLContext::QOpenGLContext(QObject *parent) /*! Sets the \a format the OpenGL context should be compatible with. You need to call create() before it takes effect. + + When the format is not explicitly set via this function, the format returned + by QSurfaceFormat::defaultFormat() will be used. This means that when having + multiple contexts, individual calls to this function can be replaced by one + single call to QSurfaceFormat::setDefaultFormat() before creating the first + context. */ void QOpenGLContext::setFormat(const QSurfaceFormat &format) { @@ -486,6 +526,64 @@ void QOpenGLContext::setScreen(QScreen *screen) } /*! + Set the native handles for this context. When create() is called and a + native handle is set, configuration settings, like format(), are ignored + since this QOpenGLContext will wrap an already created native context + instead of creating a new one from scratch. + + On some platforms the native context handle is not sufficient and other + related handles (for example, for a window or display) have to be provided + in addition. Therefore \a handle is variant containing a platform-specific + value type. These classes can be found in the QtPlatformHeaders module. + + When create() is called with native handles set, the handles' ownership are + not taken, meaning that destroy() will not destroy the native context. + + \note Some frameworks track the current context and surfaces internally. + Making the adopted QOpenGLContext current via Qt will have no effect on such + other frameworks' internal state. Therefore a subsequent makeCurrent done + via the other framework may have no effect. It is therefore advisable to + make explicit calls to make no context and surface current to reset the + other frameworks' internal state after performing OpenGL operations via Qt. + + \note Using foreign contexts with Qt windows and Qt contexts with windows + and surfaces created by other frameworks may give unexpected results, + depending on the platform, due to potential mismatches in context and window + pixel formats. To make sure this does not happen, avoid making contexts and + surfaces from different frameworks current together. Instead, prefer + approaches based on context sharing where OpenGL resources like textures are + accessible both from Qt's and the foreign framework's contexts. + + \since 5.4 + \sa nativeHandle() +*/ +void QOpenGLContext::setNativeHandle(const QVariant &handle) +{ + Q_D(QOpenGLContext); + d->nativeHandle = handle; +} + +/*! + Returns the native handle for the context. + + This function provides access to the QOpenGLContext's underlying native + context. The returned variant contains a platform-specific value type. These + classes can be found in the module QtPlatformHeaders. + + On platforms where retrieving the native handle is not supported, or if + neither create() nor setNativeHandle() was called, a null variant is + returned. + + \since 5.4 + \sa setNativeHandle() + */ +QVariant QOpenGLContext::nativeHandle() const +{ + Q_D(const QOpenGLContext); + return d->nativeHandle; +} + +/*! Attempts to create the OpenGL context with the current configuration. The current configuration includes the format, the share context, and the @@ -502,11 +600,15 @@ void QOpenGLContext::setScreen(QScreen *screen) Returns \c true if the native context was successfully created and is ready to be used with makeCurrent(), swapBuffers(), etc. + \note If the context is already created, this function will first call + destroy(), and then create a new OpenGL context. + \sa makeCurrent(), destroy(), format() */ bool QOpenGLContext::create() { - destroy(); + if (isValid()) + destroy(); Q_D(QOpenGLContext); d->platformGLContext = QGuiApplicationPrivate::platformIntegration()->createPlatformOpenGLContext(this); @@ -557,6 +659,7 @@ void QOpenGLContext::destroy() d->versionFunctionsBackend.clear(); delete d->textureFunctions; d->textureFunctions = 0; + d->nativeHandle = QVariant(); } /*! diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index 19aecee75a..99f2fece51 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -64,6 +64,7 @@ #include <QtCore/qhash.h> #include <QtCore/qpair.h> +#include <QtCore/qvariant.h> QT_BEGIN_NAMESPACE @@ -153,6 +154,7 @@ public: void setFormat(const QSurfaceFormat &format); void setShareContext(QOpenGLContext *shareContext); void setScreen(QScreen *screen); + void setNativeHandle(const QVariant &handle); bool create(); bool isValid() const; @@ -161,6 +163,7 @@ public: QOpenGLContext *shareContext() const; QOpenGLContextGroup *shareGroup() const; QScreen *screen() const; + QVariant nativeHandle() const; GLuint defaultFramebufferObject() const; @@ -242,4 +245,4 @@ QT_END_NAMESPACE #endif // QT_NO_OPENGL -#endif // QGUIGLCONTEXT_H +#endif // QOPENGLCONTEXT_H diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index e9907480f2..2d27b19ebe 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -206,13 +206,13 @@ public: , surface(0) , functions(0) , textureFunctions(0) - , current_fbo(0) , max_texture_size(-1) , workaround_brokenFBOReadBack(false) , workaround_brokenTexSubImage(false) , workaround_missingPrecisionQualifiers(false) , active_engine(0) { + requestedFormat = QSurfaceFormat::defaultFormat(); } virtual ~QOpenGLContextPrivate() @@ -237,7 +237,6 @@ public: mutable QSet<QByteArray> extensionNames; QOpenGLTextureHelper* textureFunctions; - GLuint current_fbo; GLint max_texture_size; bool workaround_brokenFBOReadBack; @@ -246,6 +245,8 @@ public: QPaintEngineEx *active_engine; + QVariant nativeHandle; + static QOpenGLContext *setCurrentContext(QOpenGLContext *context); static void setGlobalShareContext(QOpenGLContext *context); @@ -276,6 +277,9 @@ public: #endif }; +Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context); +Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); + QT_END_NAMESPACE #endif // QT_NO_OPENGL diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp new file mode 100644 index 0000000000..a0261c2f04 --- /dev/null +++ b/src/gui/kernel/qopenglwindow.cpp @@ -0,0 +1,622 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qopenglwindow.h" +#include "qpaintdevicewindow_p.h" +#include <QtGui/QOpenGLFramebufferObject> +#include <QtGui/QOpenGLPaintDevice> +#include <QtGui/QOpenGLFunctions> +#include <QtGui/private/qopengltextureblitter_p.h> +#include <QtGui/private/qopenglextensions_p.h> +#include <QtGui/QMatrix4x4> +#include <QtGui/QOffscreenSurface> + +QT_BEGIN_NAMESPACE + +/*! + \class QOpenGLWindow + \inmodule QtGui + \since 5.4 + \brief The QOpenGLWindow class is a convenience subclass of QWindow to perform OpenGL painting. + + QOpenGLWindow is an enhanced QWindow that allows easily creating windows that + perform OpenGL rendering using an API that is compatible with QOpenGLWidget + and is similar to the legacy QGLWidget. Unlike QOpenGLWidget, QOpenGLWindow + has no dependency on the widgets module and offers better performance. + + A typical application will subclass QOpenGLWindow and reimplement the following + virtual functions: + + \list + + \li initializeGL() to perform OpenGL resource initialization + + \li resizeGL() to set up the transformation matrices and other window size dependent resources + + \li paintGL() to issue OpenGL commands or draw using QPainter + + \endlist + + To schedule a repaint, call the update() function. Note that this will not + immediately result in a call to paintGL(). Calling update() multiple times in + a row will not change the behavior in any way. + + This is a slot so it can be connected to a \l QTimer::timeout() signal to + perform animation. Note however that in the modern OpenGL world it is a much + better choice to rely on synchronization to the vertical refresh rate of the + display. See \l{QSurfaceFormat::setSwapInterval()}{setSwapInterval()} on a + description of the swap interval. With a swap interval of \c 1, which is the + case on most systems by default, the + \l{QOpenGLContext::swapBuffers()}{swapBuffers()} call, that is executed + internally by QOpenGLWindow after each repaint, will block and wait for + vsync. This means that whenever the swap is done, an update can be scheduled + again by calling update(), without relying on timers. + + To request a specific configuration for the context, use setFormat() + like for any other QWindow. This allows, among others, requesting a + given OpenGL version and profile, or enabling depth and stencil + buffers. + + Unlike QWindow, QOpenGLWindow allows opening a painter on itself and perform + QPainter-based drawing. + + QOpenGLWindow supports multiple update behaviors. The default, + \c NoPartialUpdate is equivalent to a regular, OpenGL-based QWindow or the + legacy QGLWidget. In contrast, \c PartialUpdateBlit and \c PartialUpdateBlend are + more in line with QOpenGLWidget's way of working, where there is always an + extra, dedicated framebuffer object present. These modes allow, by + sacrificing some performance, redrawing only a smaller area on each paint and + having the rest of the content preserved from of the previous frame. This is + useful for applications than render incrementally using QPainter, because + this way they do not have to redraw the entire window content on each + paintGL() call. + + For more information on graphics in Qt, see \l {Graphics}. + */ + +/*! + \enum QOpenGLWindow::UpdateBehavior + + This enum describes the update strategy of the QOpenGLWindow. + + \value NoPartialUpdate Indicates that the entire window surface will + redrawn on each update and so no additional framebuffers are needed. + This is the setting used in most cases and is equivalent to how drawing + directly via QWindow would function. + + \value PartialUpdateBlit Indicates that the drawing performed in paintGL() + does not cover the entire window. In this case an extra framebuffer object + is created under the hood, and rendering performed in paintGL() will target + this framebuffer. This framebuffer is then blitted onto the window surface's + default framebuffer after each paint. This allows having QPainter-based drawing + code in paintGL() which only repaints a smaller area at a time, because, unlike + NoPartialUpdate, the previous content is preserved. + + \value PartialUpdateBlend Similar to PartialUpdateBlit, but instead of using + framebuffer blits, the contents of the extra framebuffer is rendered by + drawing a textured quad with blending enabled. This, unlike PartialUpdateBlit, + allows alpha blended content and works even when the glBlitFramebuffer is + not available. Performance-wise this setting is likely to be somewhat slower + than PartialUpdateBlit. + */ + +/*! + \fn void QOpenGLWindow::frameSwapped() + + This signal is emitted after the potentially blocking + \l{QOpenGLContext::swapBuffers()}{buffer swap} has been done. Applications + that wish to continuously repaint synchronized to the vertical refresh, + should issue an update() upon this signal. This allows for a much smoother + experience compared to the traditional usage of timers. +*/ + +// GLES2 builds won't have these constants with the suffixless names +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER 0x8CA8 +#endif +#ifndef GL_DRAW_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#endif + +class QOpenGLWindowPaintDevice : public QOpenGLPaintDevice +{ +public: + QOpenGLWindowPaintDevice(QOpenGLWindow *window) : m_window(window) { } + void ensureActiveTarget() Q_DECL_OVERRIDE; + + QOpenGLWindow *m_window; +}; + +class QOpenGLWindowPrivate : public QPaintDeviceWindowPrivate +{ + Q_DECLARE_PUBLIC(QOpenGLWindow) +public: + QOpenGLWindowPrivate(QOpenGLWindow::UpdateBehavior updateBehavior) + : updateBehavior(updateBehavior) + , hasFboBlit(false) + { + } + + ~QOpenGLWindowPrivate() + { + Q_Q(QOpenGLWindow); + if (q->isValid()) { + q->makeCurrent(); // this works even when the platformwindow is destroyed + paintDevice.reset(0); + fbo.reset(0); + blitter.destroy(); + q->doneCurrent(); + } + } + + static QOpenGLWindowPrivate *get(QOpenGLWindow *w) { return w->d_func(); } + + void bindFBO() + { + if (updateBehavior > QOpenGLWindow::NoPartialUpdate) + fbo->bind(); + else + QOpenGLFramebufferObject::bindDefault(); + } + + void beginPaint(const QRegion ®ion) Q_DECL_OVERRIDE + { + Q_UNUSED(region); + Q_Q(QOpenGLWindow); + + if (!context) { + context.reset(new QOpenGLContext); + context->setFormat(q->requestedFormat()); + if (!context->create()) + qWarning("QOpenGLWindow::beginPaint: Failed to create context"); + if (!context->makeCurrent(q)) + qWarning("QOpenGLWindow::beginPaint: Failed to make context current"); + + paintDevice.reset(new QOpenGLWindowPaintDevice(q)); + if (updateBehavior == QOpenGLWindow::PartialUpdateBlit) + hasFboBlit = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit(); + + q->initializeGL(); + } else { + context->makeCurrent(q); + } + + if (updateBehavior > QOpenGLWindow::NoPartialUpdate) { + if (!fbo || fbo->size() != q->size() * q->devicePixelRatio()) { + QOpenGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + if (q->requestedFormat().samples() > 0) { + if (updateBehavior != QOpenGLWindow::PartialUpdateBlend) + fboFormat.setSamples(q->requestedFormat().samples()); + else + qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling"); + } + fbo.reset(new QOpenGLFramebufferObject(q->size() * q->devicePixelRatio(), fboFormat)); + markWindowAsDirty(); + } + } else { + markWindowAsDirty(); + } + + const int deviceWidth = q->width() * q->devicePixelRatio(); + const int deviceHeight = q->height() * q->devicePixelRatio(); + paintDevice->setSize(QSize(deviceWidth, deviceHeight)); + paintDevice->setDevicePixelRatio(q->devicePixelRatio()); + context->functions()->glViewport(0, 0, deviceWidth, deviceHeight); + + context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject()); + + q->paintUnderGL(); + + if (updateBehavior > QOpenGLWindow::NoPartialUpdate) + fbo->bind(); + } + + void endPaint() Q_DECL_OVERRIDE + { + Q_Q(QOpenGLWindow); + + if (updateBehavior > QOpenGLWindow::NoPartialUpdate) + fbo->release(); + + context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject()); + + if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) { + QOpenGLExtensions extensions(context.data()); + extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle()); + extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject()); + extensions.glBlitFramebuffer(0, 0, q->width(), q->height(), + 0, 0, q->width(), q->height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + } else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) { + if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) { + context->functions()->glEnable(GL_BLEND); + context->functions()->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + if (!blitter.isCreated()) + blitter.create(); + + QRect windowRect(QPoint(0, 0), fbo->size()); + QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect); + blitter.bind(); + blitter.blit(fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft); + blitter.release(); + + if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) + context->functions()->glDisable(GL_BLEND); + } + + q->paintOverGL(); + } + + void flush(const QRegion ®ion) Q_DECL_OVERRIDE + { + Q_UNUSED(region); + Q_Q(QOpenGLWindow); + context->swapBuffers(q); + emit q->frameSwapped(); + } + + QOpenGLWindow::UpdateBehavior updateBehavior; + bool hasFboBlit; + QScopedPointer<QOpenGLContext> context; + QScopedPointer<QOpenGLFramebufferObject> fbo; + QScopedPointer<QOpenGLWindowPaintDevice> paintDevice; + QOpenGLTextureBlitter blitter; + QColor backgroundColor; + QScopedPointer<QOffscreenSurface> offscreenSurface; +}; + +void QOpenGLWindowPaintDevice::ensureActiveTarget() +{ + QOpenGLWindowPrivate::get(m_window)->bindFBO(); +} + +/*! + Constructs a new QOpenGLWindow with the given \a parent and \a updateBehavior. + + \sa QOpenGLWindow::UpdateBehavior + */ +QOpenGLWindow::QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior, QWindow *parent) + : QPaintDeviceWindow(*(new QOpenGLWindowPrivate(updateBehavior)), parent) +{ + setSurfaceType(QSurface::OpenGLSurface); +} + +/*! + \return the update behavior for this QOpenGLWindow. +*/ +QOpenGLWindow::UpdateBehavior QOpenGLWindow::updateBehavior() const +{ + Q_D(const QOpenGLWindow); + return d->updateBehavior; +} + +/*! + \return \c true if the window's OpenGL resources, like the context, have + been successfully initialized. Note that the return value is always \c false + until the window becomes exposed (shown). +*/ +bool QOpenGLWindow::isValid() const +{ + Q_D(const QOpenGLWindow); + return d->context && d->context->isValid(); +} + +/*! + Prepares for rendering OpenGL content for this window by making the + corresponding context current and binding the framebuffer object, if there is + one, in that context context. + + It is not necessary to call this function in most cases, because it is called + automatically before invoking paintGL(). It is provided nonetheless to support + advanced, multi-threaded scenarios where a thread different than the GUI or main + thread may want to update the surface or framebuffer contents. See QOpenGLContext + for more information on threading related issues. + + This function is suitable for calling also when the underlying platform window + is already destroyed. This means that it is safe to call this function from + a QOpenGLWindow subclass' destructor. If there is no native window anymore, + an offscreen surface is used instead. This ensures that OpenGL resource + cleanup operations in the destructor will always work, as long as + this function is called first. + + \sa QOpenGLContext, context(), paintGL(), doneCurrent() + */ +void QOpenGLWindow::makeCurrent() +{ + Q_D(QOpenGLWindow); + + if (!isValid()) + return; + + // The platform window may be destroyed at this stage and therefore + // makeCurrent() may not safely be called with 'this'. + if (handle()) { + d->context->makeCurrent(this); + } else { + if (!d->offscreenSurface) { + d->offscreenSurface.reset(new QOffscreenSurface); + d->offscreenSurface->setFormat(d->context->format()); + d->offscreenSurface->create(); + } + d->context->makeCurrent(d->offscreenSurface.data()); + } + + d->bindFBO(); +} + +/*! + Releases the context. + + It is not necessary to call this function in most cases, since the widget + will make sure the context is bound and released properly when invoking + paintGL(). + + \sa makeCurrent() + */ +void QOpenGLWindow::doneCurrent() +{ + Q_D(QOpenGLWindow); + + if (!isValid()) + return; + + d->context->doneCurrent(); +} + +/*! + \return The QOpenGLContext used by this window or \c 0 if not yet initialized. + */ +QOpenGLContext *QOpenGLWindow::context() const +{ + Q_D(const QOpenGLWindow); + return d->context.data(); +} + +/*! + The framebuffer object handle used by this window. + + When the update behavior is set to \c NoPartialUpdate, there is no separate + framebuffer object. In this case the returned value is the ID of the + default framebuffer. + + Otherwise the value of the ID of the framebuffer object or \c 0 if not + yet initialized. + */ +GLuint QOpenGLWindow::defaultFramebufferObject() const +{ + Q_D(const QOpenGLWindow); + if (d->updateBehavior > NoPartialUpdate && d->fbo) + return d->fbo->handle(); + else if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) + return ctx->defaultFramebufferObject(); + else + return 0; +} + +extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); + +/*! + Returns a 32-bit RGB image of the framebuffer. + + \note This is a potentially expensive operation because it relies on + glReadPixels() to read back the pixels. This may be slow and can stall the + GPU pipeline. + + \note When used together with update behavior \c NoPartialUpdate, the returned + image may not contain the desired content when called after the front and back + buffers have been swapped (unless preserved swap is enabled in the underlying + windowing system interface). In this mode the function reads from the back + buffer and the contents of that may not match the content on the screen (the + front buffer). In this case the only place where this function can safely be + used is paintGL() or paintOverGL(). + */ +QImage QOpenGLWindow::grabFramebuffer() +{ + if (!isValid()) + return QImage(); + + makeCurrent(); + return qt_gl_read_framebuffer(size() * devicePixelRatio(), false, false); +} + +/*! + This virtual function is called once before the first call to paintGL() or + resizeGL(). Reimplement it in a subclass. + + This function should set up any required OpenGL resources and state. + + There is no need to call makeCurrent() because this has already been done + when this function is called. Note however that the framebuffer, in case + partial update mode is used, is not yet available at this stage, so avoid + issuing draw calls from here. Defer such calls to paintGL() instead. + + \sa paintGL(), resizeGL() + */ +void QOpenGLWindow::initializeGL() +{ +} + +/*! + This virtual function is called whenever the widget has been resized. + Reimplement it in a subclass. The new size is passed in \a w and \a h. + + \note This is merely a convenience function in order to provide an API that is + compatible with QOpenGLWidget. Unlike with QOpenGLWidget, derived classes are + free to choose to override resizeEvent() instead of this function. + + \note Avoid issuing OpenGL commands from this function as there may not be a + context current when it is invoked. If it cannot be avoided, call makeCurrent(). + + \note Scheduling updates from here is not necessary. The windowing systems + will send expose events that trigger an update automatically. + + \sa initializeGL(), paintGL() + */ +void QOpenGLWindow::resizeGL(int w, int h) +{ + Q_UNUSED(w); + Q_UNUSED(h); +} + +/*! + This virtual function is called whenever the window contents needs to be + painted. Reimplement it in a subclass. + + There is no need to call makeCurrent() because this has already + been done when this function is called. + + Before invoking this function, the context and the framebuffer, if there is + one, are bound, and the viewport is set up by a call to glViewport(). No + other state is set and no clearing or drawing is performed by the framework. + + \note When using a partial update behavior, like \c PartialUpdateBlend, the + output of the previous paintGL() call is preserved and, after the additional + drawing perfomed in the current invocation of the function, the content is + blitted or blended over the content drawn directly to the window in + paintUnderGL(). + + \sa initializeGL(), resizeGL(), paintUnderGL(), paintOverGL(), UpdateBehavior + */ +void QOpenGLWindow::paintGL() +{ +} + +/*! + The virtual function is called before each invocation of paintGL(). + + When the update mode is set to \c NoPartialUpdate, there is no difference + between this function and paintGL(), performing rendering in either of them + leads to the same result. + + The difference becomes significant when using \c PartialUpdateBlend, where an + extra framebuffer object is used. There, paintGL() targets this additional + framebuffer object, which preserves its contents, while paintUnderGL() and + paintOverGL() target the default framebuffer, i.e. directly the window + surface, the contents of which is lost after each displayed frame. + + \note Avoid relying on this function when the update behavior is + \c PartialUpdateBlit. This mode involves blitting the extra framebuffer used by + paintGL() onto the default framebuffer after each invocation of paintGL(), + thus overwriting all drawing generated in this function. + + \sa paintGL(), paintOverGL(), UpdateBehavior + */ +void QOpenGLWindow::paintUnderGL() +{ +} + +/*! + This virtual function is called after each invocation of paintGL(). + + When the update mode is set to NoPartialUpdate, there is no difference + between this function and paintGL(), performing rendering in either of them + leads to the same result. + + Like paintUnderGL(), rendering in this function targets the default + framebuffer of the window, regardless of the update behavior. It gets called + after paintGL() has returned and the blit (PartialUpdateBlit) or quad drawing + (PartialUpdateBlend) has been done. + + \sa paintGL(), paintUnderGL(), UpdateBehavior + */ +void QOpenGLWindow::paintOverGL() +{ +} + +/*! + Paint \a event handler. Calls paintGL(). + + \sa paintGL() + */ +void QOpenGLWindow::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + paintGL(); +} + +/*! + Resize \a event handler. Calls resizeGL(). + + \sa resizeGL() + */ +void QOpenGLWindow::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + resizeGL(width(), height()); +} + +/*! + \internal + */ +int QOpenGLWindow::metric(PaintDeviceMetric metric) const +{ + Q_D(const QOpenGLWindow); + + switch (metric) { + case PdmDepth: + if (d->paintDevice) + return d->paintDevice->depth(); + break; + case PdmDevicePixelRatio: + if (d->paintDevice) + return d->paintDevice->devicePixelRatio(); + break; + default: + break; + } + return QPaintDeviceWindow::metric(metric); + +} + +/*! + \internal + */ +QPaintDevice *QOpenGLWindow::redirected(QPoint *) const +{ + Q_D(const QOpenGLWindow); + if (QOpenGLContext::currentContext() == d->context.data()) + return d->paintDevice.data(); + return 0; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qclipboard_qpa.cpp b/src/gui/kernel/qopenglwindow.h index ff8a210cba..e30de3b6ac 100644 --- a/src/gui/kernel/qclipboard_qpa.cpp +++ b/src/gui/kernel/qopenglwindow.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -39,51 +39,68 @@ ** ****************************************************************************/ -#include "qclipboard.h" +#ifndef QOPENGLWINDOW_H +#define QOPENGLWINDOW_H -#ifndef QT_NO_CLIPBOARD +#include <QtCore/qglobal.h> -#include "qmimedata.h" -#include "private/qguiapplication_p.h" -#include <qpa/qplatformclipboard.h> -#include <qpa/qplatformintegration.h> +#ifndef QT_NO_OPENGL + +#include <QtGui/QPaintDeviceWindow> +#include <QtGui/QOpenGLContext> +#include <QtGui/QImage> QT_BEGIN_NAMESPACE -QT_USE_NAMESPACE +class QOpenGLWindowPrivate; -void QClipboard::clear(Mode mode) +class Q_GUI_EXPORT QOpenGLWindow : public QPaintDeviceWindow { - setMimeData(0, mode); -} + Q_OBJECT + Q_DECLARE_PRIVATE(QOpenGLWindow) -const QMimeData* QClipboard::mimeData(Mode mode) const -{ - QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); - if (!clipboard->supportsMode(mode)) return 0; - return clipboard->mimeData(mode); -} +public: + enum UpdateBehavior { + NoPartialUpdate, + PartialUpdateBlit, + PartialUpdateBlend + }; -void QClipboard::setMimeData(QMimeData* src, Mode mode) -{ - QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); - if (!clipboard->supportsMode(mode)) return; + explicit QOpenGLWindow(UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = 0); - clipboard->setMimeData(src,mode); -} + UpdateBehavior updateBehavior() const; + bool isValid() const; -bool QClipboard::supportsMode(Mode mode) const -{ - QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); - return clipboard->supportsMode(mode); -} + void makeCurrent(); + void doneCurrent(); -bool QClipboard::ownsMode(Mode mode) const -{ - QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); - return clipboard->ownsMode(mode); -} + QOpenGLContext *context() const; + + GLuint defaultFramebufferObject() const; -#endif // QT_NO_CLIPBOARD + QImage grabFramebuffer(); + +Q_SIGNALS: + void frameSwapped(); + +protected: + virtual void initializeGL(); + virtual void resizeGL(int w, int h); + virtual void paintGL(); + virtual void paintUnderGL(); + virtual void paintOverGL(); + + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + int metric(PaintDeviceMetric metric) const Q_DECL_OVERRIDE; + QPaintDevice *redirected(QPoint *) const Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QOpenGLWindow) +}; QT_END_NAMESPACE + +#endif // QT_NO_OPENGL + +#endif diff --git a/src/gui/kernel/qpaintdevicewindow.cpp b/src/gui/kernel/qpaintdevicewindow.cpp new file mode 100644 index 0000000000..9c6a255ca7 --- /dev/null +++ b/src/gui/kernel/qpaintdevicewindow.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpaintdevicewindow_p.h" + +#include <QtGui/QGuiApplication> +#include <QtGui/QScreen> + +QT_BEGIN_NAMESPACE + +/*! + \class QPaintDeviceWindow + \inmodule QtGui + \since 5.4 + \brief Convenience subclass of QWindow that is also a QPaintDevice. + + QPaintDeviceWindow is like a regular QWindow, with the added functionality + of being a paint device too. Whenever the content needs to be updated, + the virtual paintEvent() function is called. Subclasses, that reimplement + this function, can then simply open a QPainter on the window. + + \note This class cannot directly be used in applications. It rather serves + as a base for subclasses like QOpenGLWindow. + + \sa QOpenGLWindow +*/ + +/*! + Marks the entire window as dirty and schedules a repaint. + + \note Subsequent calls to this function before the next paint + event will get ignored. +*/ +void QPaintDeviceWindow::update() +{ + update(QRect(QPoint(0,0), size())); +} + +/*! + Marks the \a rect of the window as dirty and schedules a repaint. + + \note Subsequent calls to this function before the next paint + event will get ignored. +*/ +void QPaintDeviceWindow::update(const QRect &rect) +{ + Q_D(QPaintDeviceWindow); + d->dirtyRegion += rect; + d->triggerUpdate(); +} + +/*! + Marks the \a region of the window as dirty and schedules a repaint. + + \note Subsequent calls to this function before the next paint + event will get ignored. +*/ +void QPaintDeviceWindow::update(const QRegion ®ion) +{ + Q_D(QPaintDeviceWindow); + d->dirtyRegion += region; + d->triggerUpdate(); +} + +/*! + Handles paint events passed in the \a event parameter. + + The default implementation does nothing. Reimplement this function to + perform painting. If necessary, the dirty area is retrievable from + the \a event. +*/ +void QPaintDeviceWindow::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + // Do nothing +} + +/*! + \internal + */ +int QPaintDeviceWindow::metric(PaintDeviceMetric metric) const +{ + QScreen *screen = this->screen(); + if (!screen && QGuiApplication::primaryScreen()) + screen = QGuiApplication::primaryScreen(); + + switch (metric) { + case PdmWidth: + return width(); + case PdmWidthMM: + if (screen) + return width() * screen->physicalSize().width() / screen->geometry().width(); + break; + case PdmHeight: + return height(); + case PdmHeightMM: + if (screen) + return height() * screen->physicalSize().height() / screen->geometry().height(); + break; + case PdmDpiX: + if (screen) + return qRound(screen->logicalDotsPerInchX()); + break; + case PdmDpiY: + if (screen) + return qRound(screen->logicalDotsPerInchY()); + break; + case PdmPhysicalDpiX: + if (screen) + return qRound(screen->physicalDotsPerInchX()); + break; + case PdmPhysicalDpiY: + if (screen) + return qRound(screen->physicalDotsPerInchY()); + break; + case PdmDevicePixelRatio: + if (screen) + return screen->devicePixelRatio(); + break; + default: + break; + } + + return QPaintDevice::metric(metric); +} + +/*! + \internal + */ +void QPaintDeviceWindow::exposeEvent(QExposeEvent *exposeEvent) +{ + Q_UNUSED(exposeEvent); + Q_D(QPaintDeviceWindow); + if (isExposed()) { + d->markWindowAsDirty(); + // Do not rely on exposeEvent->region() as it has some issues for the + // time being, namely that it is sometimes in local coordinates, + // sometimes relative to the parent, depending on the platform plugin. + // We require local coords here. + d->doFlush(QRect(QPoint(0, 0), size())); + } +} + +/*! + \internal + */ +bool QPaintDeviceWindow::event(QEvent *event) +{ + Q_D(QPaintDeviceWindow); + + if (event->type() == QEvent::UpdateRequest) { + d->paintEventSent = false; + if (handle()) // platform window may be gone when the window is closed during app exit + d->handleUpdateEvent(); + return true; + } + + return QWindow::event(event); +} + +/*! + \internal + */ +QPaintDeviceWindow::QPaintDeviceWindow(QPaintDeviceWindowPrivate &dd, QWindow *parent) + : QWindow(dd, parent) +{ +} + +/*! + \internal + */ +QPaintEngine *QPaintDeviceWindow::paintEngine() const +{ + return 0; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformscreenpageflipper.h b/src/gui/kernel/qpaintdevicewindow.h index 232e37d24a..ee7d07254e 100644 --- a/src/gui/kernel/qplatformscreenpageflipper.h +++ b/src/gui/kernel/qpaintdevicewindow.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -39,54 +39,47 @@ ** ****************************************************************************/ -#ifndef QPLATFORMSCREENPAGEFLIPPER_H -#define QPLATFORMSCREENPAGEFLIPPER_H +#ifndef QPAINTDEVICEWINDOW_H +#define QPAINTDEVICEWINDOW_H -// -// W A R N I N G -// ------------- -// -// This file is part of the QPA API and is not meant to be used -// in applications. Usage of this API may make your code -// source and binary incompatible with future versions of Qt. -// - -#include <QtCore/QObject> +#include <QtGui/QWindow> +#include <QtGui/QPaintDevice> QT_BEGIN_NAMESPACE -class Q_GUI_EXPORT QPlatformScreenBuffer { -public: - QPlatformScreenBuffer(); - virtual ~QPlatformScreenBuffer(); +class QPaintDeviceWindowPrivate; +class QPaintEvent; + +class Q_GUI_EXPORT QPaintDeviceWindow : public QWindow, public QPaintDevice +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPaintDeviceWindow) - bool isDestroyed() const; - bool isReady() const; +public: + void update(const QRect &rect); + void update(const QRegion ®ion); - virtual void aboutToBeDisplayed(); - virtual void displayed(); - virtual void release() = 0; + using QWindow::width; + using QWindow::height; + using QWindow::devicePixelRatio; - virtual void *handle() const = 0; +public Q_SLOTS: + void update(); protected: - bool m_destroyed; - bool m_ready; -}; + virtual void paintEvent(QPaintEvent *event); -class Q_GUI_EXPORT QPlatformScreenPageFlipper : public QObject -{ - Q_OBJECT -public: - explicit QPlatformScreenPageFlipper(QObject *parent = 0); + int metric(PaintDeviceMetric metric) const Q_DECL_OVERRIDE; + void exposeEvent(QExposeEvent *) Q_DECL_OVERRIDE; + bool event(QEvent *event) Q_DECL_OVERRIDE; - virtual bool displayBuffer(QPlatformScreenBuffer *) = 0; + QPaintDeviceWindow(QPaintDeviceWindowPrivate &dd, QWindow *parent); -Q_SIGNALS: - void bufferDisplayed(QPlatformScreenBuffer *); - void bufferReleased(QPlatformScreenBuffer *); +private: + QPaintEngine *paintEngine() const Q_DECL_OVERRIDE; + Q_DISABLE_COPY(QPaintDeviceWindow) }; QT_END_NAMESPACE -#endif // QPLATFORMSCREENPAGEFLIPPER_H +#endif diff --git a/src/gui/kernel/qplatformscreenpageflipper.cpp b/src/gui/kernel/qpaintdevicewindow_p.h index 8665adc463..65313eda87 100644 --- a/src/gui/kernel/qplatformscreenpageflipper.cpp +++ b/src/gui/kernel/qpaintdevicewindow_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -39,83 +39,92 @@ ** ****************************************************************************/ -#include "qplatformscreenpageflipper.h" +#ifndef QPAINTDEVICEWINDOW_P_H +#define QPAINTDEVICEWINDOW_P_H -QT_BEGIN_NAMESPACE - -/*! - \class QPlatformScreenBuffer - \since 5.0 - \internal - \preliminary - \ingroup qpa - - \brief The QPlatformScreenBuffer class provides an abstraction for screen buffers. - */ -QPlatformScreenBuffer::QPlatformScreenBuffer() - : m_destroyed(false) - , m_ready(true) -{ - -} - -QPlatformScreenBuffer::~QPlatformScreenBuffer() -{ +#include <QtGui/QPaintDeviceWindow> +#include <QtCore/QCoreApplication> +#include <QtGui/private/qwindow_p.h> +#include <QtGui/QPaintEvent> -} - -bool QPlatformScreenBuffer::isDestroyed() const -{ - return m_destroyed; -} - -bool QPlatformScreenBuffer::isReady() const -{ - return m_ready; -} - -void QPlatformScreenBuffer::aboutToBeDisplayed() -{ -} - -void QPlatformScreenBuffer::displayed() -{ -} - - -/*! - \class QPlatformScreenPageFlipper - \since 5.0 - \internal - \preliminary - \ingroup qpa - - \brief The QPlatformScreenPageFlipper class provides an abstract interface for display buffer swapping - - Implement the displayBuffer() function to initiate a buffer swap. The - bufferDisplayed() signal should be emitted once the buffer is actually displayed on - the screen. The bufferReleased() signal should be emitted when the buffer data is no - longer owned by the display hardware. -*/ +QT_BEGIN_NAMESPACE -QPlatformScreenPageFlipper::QPlatformScreenPageFlipper(QObject *parent) - :QObject(parent) +class Q_GUI_EXPORT QPaintDeviceWindowPrivate : public QWindowPrivate { + Q_DECLARE_PUBLIC(QPaintDeviceWindow) + +public: + QPaintDeviceWindowPrivate() : paintEventSent(false) { } + + virtual void beginPaint(const QRegion ®ion) + { + Q_UNUSED(region); + } + + virtual void endPaint() + { + } + + virtual void flush(const QRegion ®ion) + { + Q_UNUSED(region); + } + + bool paint(const QRegion ®ion) + { + Q_Q(QPaintDeviceWindow); + QRegion toPaint = region & dirtyRegion; + if (toPaint.isEmpty()) + return false; + + // Clear the region now. The overridden functions may call update(). + dirtyRegion -= toPaint; + + beginPaint(toPaint); + + QPaintEvent paintEvent(toPaint); + q->paintEvent(&paintEvent); + + endPaint(); + + return true; + } + + void triggerUpdate() + { + Q_Q(QPaintDeviceWindow); + if (!paintEventSent) { + QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest)); + paintEventSent = true; + } + } + + void doFlush(const QRegion ®ion) + { + QRegion toFlush = region; + if (paint(toFlush)) + flush(toFlush); + } + + void handleUpdateEvent() + { + if (dirtyRegion.isEmpty()) + return; + doFlush(dirtyRegion); + } + + void markWindowAsDirty() + { + Q_Q(QPaintDeviceWindow); + dirtyRegion += QRect(QPoint(0, 0), q->size()); + } + +private: + QRegion dirtyRegion; + bool paintEventSent; +}; -} - -/*! - \fn bool QPlatformScreenPageFlipper::displayBuffer(QPlatformScreenBuffer *buffer) - - Implemented in subclasses to display \a buffer directly on the screen. Returns \c true - if it is possible to display the buffer, and \c false if the buffer cannot be displayed. - - If this function returns \c true, the buffer must not be modified or destroyed before the - bufferReleased() signal is emitted. The signal bufferDisplayed() is emitted when the buffer - is displayed on the screen. The two signals may be emitted in either order. - - This function is allowed to block. -*/ QT_END_NAMESPACE +#endif //QPAINTDEVICEWINDOW_P_H diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp index f284c20af5..52b0372ea8 100644 --- a/src/gui/kernel/qpalette.cpp +++ b/src/gui/kernel/qpalette.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -643,11 +643,22 @@ QPalette::QPalette(const QPalette &p) } /*! + \fn QPalette::QPalette(QPalette &&other) + \since 5.4 + + Move-constructs a QPalette instance, making it point at the same + object that \a other was pointing to. + + After being moved from, you can only assign to or destroy \a other. + Any other operation will result in undefined behavior. +*/ + +/*! Destroys the palette. */ QPalette::~QPalette() { - if(!d->ref.deref()) + if (d && !d->ref.deref()) delete d; } @@ -668,7 +679,7 @@ QPalette &QPalette::operator=(const QPalette &p) { p.d->ref.ref(); data = p.data; - if(!d->ref.deref()) + if (d && !d->ref.deref()) delete d; d = p.d; return *this; @@ -1141,9 +1152,33 @@ Q_GUI_EXPORT QPalette qt_fusionPalette() } #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const QPalette &) +QDebug operator<<(QDebug dbg, const QPalette &p) { - dbg.nospace() << "QPalette()"; + const char *colorGroupNames[] = {"Active", "Disabled", "Inactive"}; + const char *colorRoleNames[] = + {"WindowText", "Button", "Light", "Midlight", "Dark", "Mid", "Text", + "BrightText", "ButtonText", "Base", "Window", "Shadow", "Highlight", + "HighlightedText", "Link", "LinkVisited", "AlternateBase", "NoRole", + "ToolTipBase","ToolTipText" }; + QDebug nospace = dbg.nospace(); + const uint mask = p.resolve(); + nospace << "QPalette(resolve=" << hex << showbase << mask << ','; + for (int role = 0; role < (int)QPalette::NColorRoles; ++role) { + if (mask & (1<<role)) { + if (role) + nospace << ','; + nospace << colorRoleNames[role] << ":["; + for (int group = 0; group < (int)QPalette::NColorGroups; ++group) { + if (group) + nospace << ','; + const QRgb color = p.color(static_cast<QPalette::ColorGroup>(group), + static_cast<QPalette::ColorRole>(role)).rgba(); + nospace << colorGroupNames[group] << ':' << color; + } + nospace << ']'; + } + } + nospace << ')' << noshowbase << dec; return dbg.space(); } #endif diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h index 8d9754d388..8c344be1e6 100644 --- a/src/gui/kernel/qpalette.h +++ b/src/gui/kernel/qpalette.h @@ -70,6 +70,8 @@ public: ~QPalette(); QPalette &operator=(const QPalette &palette); #ifdef Q_COMPILER_RVALUE_REFS + QPalette(QPalette &&other) Q_DECL_NOTHROW + : d(other.d), data(other.data) { other.d = Q_NULLPTR; } inline QPalette &operator=(QPalette &&other) { for_faster_swapping_dont_use = other.for_faster_swapping_dont_use; diff --git a/src/gui/kernel/qpixelformat.cpp b/src/gui/kernel/qpixelformat.cpp new file mode 100644 index 0000000000..90ab2db93e --- /dev/null +++ b/src/gui/kernel/qpixelformat.cpp @@ -0,0 +1,569 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpixelformat.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QPixelFormat + \inmodule QtGui + \since 5.4 + \brief QPixelFormat is a class for describing different pixel + layouts in graphics buffers + + In Qt there is a often a need to represent the layout of the pixels in a + graphics buffer. Internally QPixelFormat stores everything in a 64 bit + datastructure. This gives performance but also some limitations. + + QPixelFormat can describe 5 color channels and 1 alpha channel, each can use + 6 bits to describe the size of the color channel. + + The position of the alpha channel is described with a separate enum. This is + to make it possible to describe QImage formats like ARGB32, and also + describe typical OpenGL formats like RBGA8888. + + How pixels are suppose to be read is determined by the TypeInterpretation + enum. It describes if color values are suppose to be read byte per byte, + or if a pixel is suppose to be read as a complete int and then masked. + \sa TypeInterpretation + + There is no support for describing YUV's macro pixels. Instead a list of YUV + formats has been made. When a QPixelFormat is describing a YUV format, the + bitsPerPixel value has been deduced by the YUV Layout enum. Also, the color + channels should all be set to zero except the fifth color channel that + should store the bitsPerPixel value. +*/ + +/*! + \enum QPixelFormat::ColorModel + + This enum type is used to describe the color model of the pixelformat. + + \value RGB The color model is RGB. + + \value BGR This is logically the opposite endian version of RGB. However, + for ease of use it has its own model. + + \value Indexed The color model uses a color palette. + + \value Grayscale The color model is Grayscale. + + \value CMYK The color model is CMYK. + + \value HSL The color model is HSL. + + \value HSV The color model is HSV. + + \value YUV The color model is YUV. +*/ + +/*! + \enum QPixelFormat::AlphaUsage + + This enum describes if the alpha channel is used or not. Sometimes the + pixelformat will have a size for the alpha channel, but the pixel format + does actually not use the alpha channel. For example RGB32 is such a + format. The RGB channels are 8 bits each, and there is no alpha channel. + But the complete size for each pixel is 32. Therefore the alpha channel size + is 8, but the alpha channel is ignored. Its important to note that in such + situations the position of the alpha channel is significant. + + \value IgnoresAlpha The alpha channel is not used. + + \value UsesAlpha The alpha channel is used. +*/ + +/*! + \enum QPixelFormat::AlphaPosition + + This enum type is used to describe the alpha channels position relative to the + color channels. + + \value AtBeginning The alpha channel will be put in front of the color + channels . E.g. ARGB. + + \value AtEnd The alpha channel will be put in the back of the color + channels. E.g. RGBA. +*/ + +/*! + \enum QPixelFormat::AlphaPremultiplied + + This enum type describes the boolean state if the alpha channel is multiplied + into the color channels or not. + + \value NotPremultiplied The alpha channel is not multiplied into the color channels. + + \value Premultiplied The alpha channel is multiplied into the color channels. +*/ + +/*! + \enum QPixelFormat::TypeInterpretation + + This enum describes how each pixel is interpreted. If a pixel is read as a + full 32 bit unsigned integer and then each channel is masked out, or if + each byte is read as unsigned char values. Typically QImage formats + interpret one pixel as an unsigned integer and then the color channels are + masked out. OpenGL on the other hand typically interpreted pixels "one byte + after the other", Ie. unsigned byte. + + QImage also have the format Format_RGBA8888 (and its derivatives), where + the pixels are interpreted as unsigned bytes. OpenGL has extensions that makes it + possible to upload pixel buffers in an unsigned integer format. + + \image qpixelformat-argb32buffer.png An unsigned integer ARGB32 pixel. + + The image above shows a ARGB pixel in memory read as an unsigned integer. + However, if this pixel was read byte for byte on a little endian system the + first byte would be the byte containing the B-channel. The next byte would + be the G-channel, then the R-channel and finally the A-channel. This shows + that on little endian systems, how each pixel is interpreted is significant + for integer formats. This is not the case on big endian systems. + + \value UnsignedInteger + \value UnsignedShort + \value UnsignedByte + \value FloatingPoint +*/ + +/*! + \enum QPixelFormat::ByteOrder + + This enum describes the ByteOrder of the pixel format. This enum is mostly + ignored but have some use cases for YUV formats. BGR formats have their own + color model, and should not be described by using the opposite endianness + on an RGB format. + + \value LittleEndian The byte order is little endian. + \value BigEndian The byte order is big endian. + \value CurrentSystemEndian This enum will not be stored, but is converted in + the constructor to the endian enum that matches + the enum of the current system. + +*/ + +/*! + \enum QPixelFormat::YUVLayout + + YUV is not represented by describing the size of the color channels. This is + because YUV often use macro pixels, making the concept of sperate color channels + invalid. Instead the different YUV layouts are described with this enum. + + \value YUV444 + \value YUV422 + \value YUV411 + \value YUV420P + \value YUV420SP + \value YV12 + \value UYVY + \value YUYV + \value NV12 + \value NV21 + \value IMC1 + \value IMC2 + \value IMC3 + \value IMC4 + \value Y8 + \value Y16 +*/ + +/*! + \fn QPixelFormat::QPixelFormat() + + Creates a null pixelformat. This format maps to QImage::Format_Invalid. +*/ + +/*! + \fn QPixelFormat::QPixelFormat(ColorModel colorModel, + uchar firstSize, + uchar secondSize, + uchar thirdSize, + uchar fourthSize, + uchar fifthSize, + uchar alphaSize, + AlphaUsage alphaUsage, + AlphaPosition alphaPosition, + AlphaPremultiplied premultiplied, + TypeInterpretation typeInterpretation, + ByteOrder byteOrder = CurrentSystemEndian, + uchar subEnum = 0) + + Creates a QPixelFormat which assigns its data to the attributes. + \a colorModel will be put into a buffer which is 4 bits long. + + \a firstSize \a secondSize \a thirdSize \a fourthSize \a fifthSize \a + alphaSize are all meant to represent the size of a channel. The channels will + be used for different uses dependent on the \a colorModel. For RGB the + firstSize will represent the Red channel. On CMYK it will represent the + value of the Cyan channel. + + \a alphaUsage represents if the alpha channel is used or not. + + \a alphaPosition is the position of the alpha channel. + + \a premultiplied represents if the alpha channel is already multiplied with + the color channels. + + \a typeInterpretation is how the pixel is interpreted. + + \a byteOrder represents the endianness of the pixelformat. This defaults to + CurrentSystemEndian. + + \a subEnum is used for colorModels that have to store some extra + information with supplying an extra enum. This is used by YUV to store the + YUV type The default value is 0. +*/ + +/*! + \fn QPixelFormat qPixelFormatRgba(uchar redSize, + uchar greenSize, + uchar blueSize, + uchar alphaSize, + QPixelFormat::AlphaUsage alphaUsage, + QPixelFormat::AlphaPosition alphaPosition, + QPixelFormat::AlphaPremultiplied premultiplied = QPixelFormat::NotPremultiplied, + QPixelFormat::TypeInterpretation typeInterpretation = QPixelFormat::UnsignedInteger) + \relates QPixelFormat + + Constructor function making an RGB pixelformat. \a redSize \a greenSize \a + blueSize represent the size of each color channel. \a alphaSize describes + the alpha channel size and its position is described with \a alphaPosition. + \a alphaUsage is used to determine if the alpha channel is used or not. + Setting the alpha channel size to 8 and alphaUsage to IgnoresAlpha is how + it is possible to create a 32 bit format where the rgb channels only use 24 + bits combined. \a premultiplied \a typeInterpretation are + accessible with accessors with the same name. + + \sa QPixelFormat::TypeInterpretation +*/ + +/*! + \fn QPixelFormat qPixelFormatGrayscale(uchar channelSize, + QPixelFormat::TypeInterpretation typeInterpretation = QPixelFormat::UnsignedInteger) + \relates QPixelFormat + + Constructor function for creating a Grayscale format. Monochrome formats can be + described by passing 1 to \a channelSize. Its also possible to define very + accurate grayscale formats using doubles to describe each pixel by passing 8 + as \a channelSize and FloatingPoint as \a typeInterpretation. + + \sa QPixelFormat::TypeInterpretation +*/ + +/*! + \fn QPixelFormat qPixelFormatCmyk(uchar channelSize, + uchar alphaSize = 0, + QPixelFormat::AlphaUsage alphaUsage = QPixelFormat::IgnoresAlpha, + QPixelFormat::AlphaPosition alphaPosition = QPixelFormat::AtBeginning, + QPixelFormat::TypeInterpretation typeInterpretation = QPixelFormat::UnsignedInteger) + \relates QPixelFormat + + Constructor function for creating CMYK formats. The channel count will be 4 or + 5 depending on if \a alphaSize is bigger than zero or not. The CMYK color + channels will all be set to the value of \a channelSize. + + \a alphaUsage \a alphaPosition and \a typeInterpretation are all accessible with + the accessors with the same name. + + \sa QPixelFormat::TypeInterpretation +*/ + +/*! + \fn QPixelFormat qPixelFormatHsl(uchar channelSize, + uchar alphaSize = 0, + QPixelFormat::AlphaUsage alphaUsage = QPixelFormat::IgnoresAlpha, + QPixelFormat::AlphaPosition alphaPosition = QPixelFormat::AtBeginning, + QPixelFormat::TypeInterpretation typeInterpretation = QPixelFormat::FloatingPoint) + \relates QPixelFormat + + Constructor function for creating HSL formats. The channel count will be 3 or 4 + depending on if \a alphaSize is bigger than 0. + + \a channelSize will set the hueSize saturationSize and lightnessSize to the same value. + + \a alphaUsage \a alphaPosition and \a typeInterpretation are all accessible with + the accessors with the same name. +*/ + +/*! + \fn QPixelFormat qPixelFormatHsv(uchar channelSize, + uchar alphaSize = 0, + QPixelFormat::AlphaUsage alphaUsage = QPixelFormat::IgnoresAlpha, + QPixelFormat::AlphaPosition alphaPosition = QPixelFormat::AtBeginning, + QPixelFormat::TypeInterpretation typeInterpretation = QPixelFormat::FloatingPoint) + \relates QPixelFormat + + Constructor function for creating HSV formats. The channel count will be 3 or 4 + depending on if \a alphaSize is bigger than 0. + + \a channelSize will set the hueSize saturationSize and brightnessSize to the same value. + + \a alphaUsage \a alphaPosition and \a typeInterpretation are all accessible with + the accessors with the same name. +*/ + +/*! + \fn QPixelFormat qPixelFormatYuv(QPixelFormat::YUVLayout yuvLayout, + uchar alphaSize = 0, + QPixelFormat::AlphaUsage alphaUsage = QPixelFormat::IgnoresAlpha, + QPixelFormat::AlphaPosition alphaPosition = QPixelFormat::AtBeginning, + QPixelFormat::AlphaPremultiplied premultiplied = QPixelFormat::NotPremultiplied, + QPixelFormat::TypeInterpretation typeInterpretation = QPixelFormat::UnsignedByte, + QPixelFormat::ByteOrder byteOrder = QPixelFormat::LittleEndian) + \relates QPixelFormat + + Constructor function for creating a QPixelFormat describing a YUV format with + \a yuvLayout. \a alphaSize describes the size of a potential alpha channel + and is position is described with \a alphaPosition. The "first" "second" .. + "fifth" channels are all set to 0. \a alphaUsage \a premultiplied \a + typeInterpretation and \a byteOrder will work as with other formats. +*/ + +/*! + \fn ColorModel QPixelFormat::colorModel() const + + Accessor function for getting the colorModel. +*/ + +/*! + \fn uchar QPixelFormat::channelCount() const + + Accessor function for getting the channelCount. Channel Count is deduced + by color channels with a size > 0 and if the size of the alpha channel is > 0. +*/ + +/*! + \fn uchar QPixelFormat::redSize() const + + Accessor function for the size of the red color channel. +*/ + +/*! + \fn uchar QPixelFormat::greenSize() const + + Accessor function for the size of the green color channel. +*/ + +/*! + \fn uchar QPixelFormat::blueSize() const + + Accessor function for the size of the blue color channel. +*/ + +/*! + \fn uchar QPixelFormat::cyanSize() const + + Accessor function for the cyan color channel. +*/ + +/*! + \fn uchar QPixelFormat::magentaSize() const + + Accessor function for the megenta color channel. +*/ + +/*! + \fn uchar QPixelFormat::yellowSize() const + + Accessor function for the yellow color channel. +*/ + +/*! + \fn uchar QPixelFormat::blackSize() const + + Accessor function for the black/key color channel. +*/ + +/*! + \fn uchar QPixelFormat::hueSize() const + + Accessor function for the hue channel size. +*/ + +/*! + \fn uchar QPixelFormat::saturationSize() const + + Accessor function for the saturation channel size. +*/ + +/*! + \fn uchar QPixelFormat::lightnessSize() const + + Accessor function for the lightness channel size. +*/ + +/*! + \fn uchar QPixelFormat::brightnessSize() const + + Accessor function for the brightness channel size. +*/ + +/*! + \fn uchar QPixelFormat::alphaSize() const + + Accessor function for the alpha channel size. +*/ + +/*! + \fn uchar QPixelFormat::bitsPerPixel() const + + Accessor function for the bits used per pixel. This function returns the + sum of the color channels + the size of the alpha channel. +*/ + +/*! + \fn AlphaPremultiplied QPixelFormat::premultiplied() const + + Accessor function for the AlphaPremultiplied enum. This indicates if the + alpha channel is multiplied in to the color channels. + +*/ + +/*! + \fn TypeInterpretation QPixelFormat::typeInterpretation() const + + Accessor function for the type representation of a color channel or a pixel. + + \sa TypeInterpretation +*/ + +/*! + \fn ByteOrder QPixelFormat::byteOrder() const + + The byte order is almost always set the the byte order of the current + system. However, it can be useful to describe some YUV formats. This + function should never return QPixelFormat::CurrentSystemEndian as this + value is translated to a endian value in the constructor. +*/ + +/*! + \fn AlphaUsage QPixelFormat::alphaUsage() const + + Accessor function for alphaUsage. +*/ + +/*! + \fn AlphaPosition QPixelFormat::alphaPosition() const + + Accessor function for alphaPosition. +*/ + +/*! + \fn YUVLayout QPixelFormat::yuvLayout() const + + Accessor function for the YUVLayout. It is difficult to describe the color + channels of a YUV pixel format since YUV color model uses macro pixels. + Instead the layout of the pixels are stored as an enum. +*/ + +/*! + \fn uchar QPixelFormat::subEnum() const + + Accessor for the datapart which contains subEnums + This is the same as the yuvLayout() function. + + \sa yuvLayout() + \internal +*/ + +Q_STATIC_ASSERT(sizeof(QPixelFormat) == sizeof(quint64)); + + +namespace QtPrivate { + QPixelFormat QPixelFormat_createYUV(QPixelFormat::YUVLayout yuvLayout, + uchar alphaSize, + QPixelFormat::AlphaUsage alphaUsage, + QPixelFormat::AlphaPosition alphaPosition, + QPixelFormat::AlphaPremultiplied premultiplied, + QPixelFormat::TypeInterpretation typeInterpretation, + QPixelFormat::ByteOrder byteOrder) + { + uchar bits_per_pixel = 0; + switch (yuvLayout) { + case QPixelFormat::YUV444: + bits_per_pixel = 24; + break; + case QPixelFormat::YUV422: + bits_per_pixel = 16; + break; + case QPixelFormat::YUV411: + case QPixelFormat::YUV420P: + case QPixelFormat::YUV420SP: + case QPixelFormat::YV12: + bits_per_pixel = 12; + break; + case QPixelFormat::UYVY: + case QPixelFormat::YUYV: + bits_per_pixel = 16; + break; + case QPixelFormat::NV12: + case QPixelFormat::NV21: + bits_per_pixel = 12; + break; + case QPixelFormat::IMC1: + case QPixelFormat::IMC2: + case QPixelFormat::IMC3: + case QPixelFormat::IMC4: + bits_per_pixel = 12; + break; + case QPixelFormat::Y8: + bits_per_pixel = 8; + break; + case QPixelFormat::Y16: + bits_per_pixel = 16; + break; + } + + return QPixelFormat(QPixelFormat::YUV, + 0, 0, 0, 0, + bits_per_pixel, + alphaSize, + alphaUsage, + alphaPosition, + premultiplied, + typeInterpretation, + byteOrder, + yuvLayout); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qpixelformat.h b/src/gui/kernel/qpixelformat.h new file mode 100644 index 0000000000..60bfbed824 --- /dev/null +++ b/src/gui/kernel/qpixelformat.h @@ -0,0 +1,391 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPIXELFORMAT_H +#define QPIXELFORMAT_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +class QPixelFormat +{ + // QPixelFormat basically is a glorified quint64, split into several fields. + // We could use bit-fields, but GCC at least generates horrible, horrible code for them, + // so we do the bit-twiddling ourselves. + enum FieldWidth { + ModelFieldWidth = 4, + FirstFieldWidth = 6, + SecondFieldWidth = FirstFieldWidth, + ThirdFieldWidth = FirstFieldWidth, + FourthFieldWidth = FirstFieldWidth, + FifthFieldWidth = FirstFieldWidth, + AlphaFieldWidth = FirstFieldWidth, + AlphaUsageFieldWidth = 1, + AlphaPositionFieldWidth = 1, + PremulFieldWidth = 1, + TypeInterpretationFieldWidth = 4, + ByteOrderFieldWidth = 2, + SubEnumFieldWidth = 6, + UnusedFieldWidth = 9, + + TotalFieldWidthByWidths = ModelFieldWidth + FirstFieldWidth + SecondFieldWidth + ThirdFieldWidth + + FourthFieldWidth + FifthFieldWidth + AlphaFieldWidth + AlphaUsageFieldWidth + + AlphaPositionFieldWidth + PremulFieldWidth + TypeInterpretationFieldWidth + + ByteOrderFieldWidth + SubEnumFieldWidth + UnusedFieldWidth + }; + + enum Field { + ModelField = 0, + // work around bug in old clang versions: when building webkit + // with XCode 4.6 and older this fails compilation, thus cast to int + FirstField = ModelField + int(ModelFieldWidth), + SecondField = FirstField + FirstFieldWidth, + ThirdField = SecondField + SecondFieldWidth, + FourthField = ThirdField + ThirdFieldWidth, + FifthField = FourthField + FourthFieldWidth, + AlphaField = FifthField + FifthFieldWidth, + AlphaUsageField = AlphaField + AlphaFieldWidth, + AlphaPositionField = AlphaUsageField + AlphaUsageFieldWidth, + PremulField = AlphaPositionField + AlphaPositionFieldWidth, + TypeInterpretationField = PremulField + PremulFieldWidth, + ByteOrderField = TypeInterpretationField + TypeInterpretationFieldWidth, + SubEnumField = ByteOrderField + ByteOrderFieldWidth, + UnusedField = SubEnumField + SubEnumFieldWidth, + + TotalFieldWidthByOffsets = UnusedField + UnusedFieldWidth + }; + + Q_STATIC_ASSERT(uint(TotalFieldWidthByWidths) == uint(TotalFieldWidthByOffsets)); + Q_STATIC_ASSERT(uint(TotalFieldWidthByWidths) == 8 * sizeof(quint64)); + + Q_DECL_CONSTEXPR inline uchar get(Field offset, FieldWidth width) const Q_DECL_NOTHROW + { return uchar((data >> uint(offset)) & ((Q_UINT64_C(1) << uint(width)) - Q_UINT64_C(1))); } + Q_DECL_CONSTEXPR static inline quint64 set(Field offset, FieldWidth width, uchar value) + { return (quint64(value) & ((Q_UINT64_C(1) << uint(width)) - Q_UINT64_C(1))) << uint(offset); } + +public: + enum ColorModel { + RGB, + BGR, + Indexed, + Grayscale, + CMYK, + HSL, + HSV, + YUV + }; + + enum AlphaUsage { + UsesAlpha, + IgnoresAlpha + }; + + enum AlphaPosition { + AtBeginning, + AtEnd + }; + + enum AlphaPremultiplied { + NotPremultiplied, + Premultiplied + }; + + enum TypeInterpretation { + UnsignedInteger, + UnsignedShort, + UnsignedByte, + FloatingPoint + }; + + enum YUVLayout { + YUV444, + YUV422, + YUV411, + YUV420P, + YUV420SP, + YV12, + UYVY, + YUYV, + NV12, + NV21, + IMC1, + IMC2, + IMC3, + IMC4, + Y8, + Y16 + }; + + enum ByteOrder { + LittleEndian, + BigEndian, + CurrentSystemEndian + }; + + Q_DECL_CONSTEXPR inline QPixelFormat() Q_DECL_NOTHROW : data(0) {} + Q_DECL_CONSTEXPR inline QPixelFormat(ColorModel colorModel, + uchar firstSize, + uchar secondSize, + uchar thirdSize, + uchar fourthSize, + uchar fifthSize, + uchar alphaSize, + AlphaUsage alphaUsage, + AlphaPosition alphaPosition, + AlphaPremultiplied premultiplied, + TypeInterpretation typeInterpretation, + ByteOrder byteOrder = CurrentSystemEndian, + uchar subEnum = 0) Q_DECL_NOTHROW; + + Q_DECL_CONSTEXPR inline ColorModel colorModel() const Q_DECL_NOTHROW { return ColorModel(get(ModelField, ModelFieldWidth)); } + Q_DECL_CONSTEXPR inline uchar channelCount() const Q_DECL_NOTHROW { return (get(FirstField, FirstFieldWidth) > 0) + + (get(SecondField, SecondFieldWidth) > 0) + + (get(ThirdField, ThirdFieldWidth) > 0) + + (get(FourthField, FourthFieldWidth) > 0) + + (get(FifthField, FifthFieldWidth) > 0) + + (get(AlphaField, AlphaFieldWidth) > 0); } + + Q_DECL_CONSTEXPR inline uchar redSize() const Q_DECL_NOTHROW { return get(FirstField, FirstFieldWidth); } + Q_DECL_CONSTEXPR inline uchar greenSize() const Q_DECL_NOTHROW { return get(SecondField, SecondFieldWidth); } + Q_DECL_CONSTEXPR inline uchar blueSize() const Q_DECL_NOTHROW { return get(ThirdField, ThirdFieldWidth); } + + Q_DECL_CONSTEXPR inline uchar cyanSize() const Q_DECL_NOTHROW { return get(FirstField, FirstFieldWidth); } + Q_DECL_CONSTEXPR inline uchar magentaSize() const Q_DECL_NOTHROW { return get(SecondField, SecondFieldWidth); } + Q_DECL_CONSTEXPR inline uchar yellowSize() const Q_DECL_NOTHROW { return get(ThirdField, ThirdFieldWidth); } + Q_DECL_CONSTEXPR inline uchar blackSize() const Q_DECL_NOTHROW { return get(FourthField, FourthFieldWidth); } + + Q_DECL_CONSTEXPR inline uchar hueSize() const Q_DECL_NOTHROW { return get(FirstField, FirstFieldWidth); } + Q_DECL_CONSTEXPR inline uchar saturationSize() const Q_DECL_NOTHROW { return get(SecondField, SecondFieldWidth); } + Q_DECL_CONSTEXPR inline uchar lightnessSize() const Q_DECL_NOTHROW { return get(ThirdField, ThirdFieldWidth); } + Q_DECL_CONSTEXPR inline uchar brightnessSize() const Q_DECL_NOTHROW { return get(ThirdField, ThirdFieldWidth); } + + Q_DECL_CONSTEXPR inline uchar alphaSize() const Q_DECL_NOTHROW { return get(AlphaField, AlphaFieldWidth); } + + Q_DECL_CONSTEXPR inline uchar bitsPerPixel() const Q_DECL_NOTHROW { return get(FirstField, FirstFieldWidth) + + get(SecondField, SecondFieldWidth) + + get(ThirdField, ThirdFieldWidth) + + get(FourthField, FourthFieldWidth) + + get(FifthField, FifthFieldWidth) + + get(AlphaField, AlphaFieldWidth); } + + Q_DECL_CONSTEXPR inline AlphaUsage alphaUsage() const Q_DECL_NOTHROW { return AlphaUsage(get(AlphaUsageField, AlphaUsageFieldWidth)); } + Q_DECL_CONSTEXPR inline AlphaPosition alphaPosition() const Q_DECL_NOTHROW { return AlphaPosition(get(AlphaPositionField, AlphaPositionFieldWidth)); } + Q_DECL_CONSTEXPR inline AlphaPremultiplied premultiplied() const Q_DECL_NOTHROW { return AlphaPremultiplied(get(PremulField, PremulFieldWidth)); } + Q_DECL_CONSTEXPR inline TypeInterpretation typeInterpretation() const Q_DECL_NOTHROW { return TypeInterpretation(get(TypeInterpretationField, TypeInterpretationFieldWidth)); } + Q_DECL_CONSTEXPR inline ByteOrder byteOrder() const Q_DECL_NOTHROW { return ByteOrder(get(ByteOrderField, ByteOrderFieldWidth)); } + + Q_DECL_CONSTEXPR inline YUVLayout yuvLayout() const Q_DECL_NOTHROW { return YUVLayout(get(SubEnumField, SubEnumFieldWidth)); } + Q_DECL_CONSTEXPR inline uchar subEnum() const Q_DECL_NOTHROW { return get(SubEnumField, SubEnumFieldWidth); } + +private: + Q_DECL_CONSTEXPR static inline ByteOrder resolveByteOrder(ByteOrder bo) + { return bo == CurrentSystemEndian ? Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? LittleEndian : BigEndian : bo ; } + +private: + quint64 data; + + friend Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline bool operator==(QPixelFormat fmt1, QPixelFormat fmt2) + { return fmt1.data == fmt2.data; } + + friend Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline bool operator!=(QPixelFormat fmt1, QPixelFormat fmt2) + { return !(fmt1 == fmt2); } +}; +Q_STATIC_ASSERT(sizeof(QPixelFormat) == sizeof(quint64)); +Q_DECLARE_TYPEINFO(QPixelFormat, Q_PRIMITIVE_TYPE); + + +namespace QtPrivate { + QPixelFormat Q_GUI_EXPORT QPixelFormat_createYUV(QPixelFormat::YUVLayout yuvLayout, + uchar alphaSize, + QPixelFormat::AlphaUsage alphaUsage, + QPixelFormat::AlphaPosition alphaPosition, + QPixelFormat::AlphaPremultiplied premultiplied, + QPixelFormat::TypeInterpretation typeInterpretation, + QPixelFormat::ByteOrder byteOrder); +} + +Q_DECL_CONSTEXPR +QPixelFormat::QPixelFormat(ColorModel mdl, + uchar firstSize, + uchar secondSize, + uchar thirdSize, + uchar fourthSize, + uchar fifthSize, + uchar alfa, + AlphaUsage usage, + AlphaPosition position, + AlphaPremultiplied premult, + TypeInterpretation typeInterp, + ByteOrder b_order, + uchar s_enum) Q_DECL_NOTHROW + : data(set(ModelField, ModelFieldWidth, uchar(mdl)) | + set(FirstField, FirstFieldWidth, firstSize) | + set(SecondField, SecondFieldWidth, secondSize) | + set(ThirdField, ThirdFieldWidth, thirdSize) | + set(FourthField, FourthFieldWidth, fourthSize) | + set(FifthField, FifthFieldWidth, fifthSize) | + set(AlphaField, AlphaFieldWidth, alfa) | + set(AlphaUsageField, AlphaUsageFieldWidth, uchar(usage)) | + set(AlphaPositionField, AlphaPositionFieldWidth, uchar(position)) | + set(PremulField, PremulFieldWidth, uchar(premult)) | + set(TypeInterpretationField, TypeInterpretationFieldWidth, uchar(typeInterp)) | + set(ByteOrderField, ByteOrderFieldWidth, uchar(resolveByteOrder(b_order))) | + set(SubEnumField, SubEnumFieldWidth, s_enum) | + set(UnusedField, UnusedFieldWidth, 0)) +{ +} + +Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatRgba(uchar red, + uchar green, + uchar blue, + uchar alfa, + QPixelFormat::AlphaUsage usage, + QPixelFormat::AlphaPosition position, + QPixelFormat::AlphaPremultiplied pmul=QPixelFormat::NotPremultiplied, + QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) Q_DECL_NOTHROW +{ + return QPixelFormat(QPixelFormat::RGB, + red, + green, + blue, + 0, + 0, + alfa, + usage, + position, + pmul, + typeInt); +} + +Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatGrayscale(uchar channelSize, + QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) Q_DECL_NOTHROW +{ + return QPixelFormat(QPixelFormat::Grayscale, + channelSize, + 0, + 0, + 0, + 0, + 0, + QPixelFormat::IgnoresAlpha, + QPixelFormat::AtBeginning, + QPixelFormat::NotPremultiplied, + typeInt); +} + +Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatCmyk(uchar channelSize, + uchar alfa=0, + QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha, + QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning, + QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) Q_DECL_NOTHROW +{ + return QPixelFormat(QPixelFormat::CMYK, + channelSize, + channelSize, + channelSize, + channelSize, + 0, + alfa, + usage, + position, + QPixelFormat::NotPremultiplied, + typeInt); +} + +Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatHsl(uchar channelSize, + uchar alfa=0, + QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha, + QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning, + QPixelFormat::TypeInterpretation typeInt=QPixelFormat::FloatingPoint) Q_DECL_NOTHROW +{ + return QPixelFormat(QPixelFormat::HSL, + channelSize, + channelSize, + channelSize, + 0, + 0, + alfa, + usage, + position, + QPixelFormat::NotPremultiplied, + typeInt); +} + +Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatHsv(uchar channelSize, + uchar alfa=0, + QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha, + QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning, + QPixelFormat::TypeInterpretation typeInt=QPixelFormat::FloatingPoint) Q_DECL_NOTHROW +{ + return QPixelFormat(QPixelFormat::HSV, + channelSize, + channelSize, + channelSize, + 0, + 0, + alfa, + usage, + position, + QPixelFormat::NotPremultiplied, + typeInt); +} + +inline QPixelFormat qPixelFormatYuv(QPixelFormat::YUVLayout layout, + uchar alfa=0, + QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha, + QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning, + QPixelFormat::AlphaPremultiplied p_mul=QPixelFormat::NotPremultiplied, + QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedByte, + QPixelFormat::ByteOrder b_order=QPixelFormat::LittleEndian) +{ + return QtPrivate::QPixelFormat_createYUV(layout, + alfa, + usage, + position, + p_mul, + typeInt, + b_order); +} + +QT_END_NAMESPACE + +#endif //QPIXELFORMAT_H diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index da192a8e25..f20482a859 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -271,13 +271,32 @@ QPlatformPixmap *QPlatformIntegration::createPlatformPixmap(QPlatformPixmap::Pix } #ifndef QT_NO_OPENGL +/*! + Factory function for QPlatformOpenGLContext. The \a context parameter is a pointer to + the context for which a platform-specific context backend needs to be + created. Configuration settings like the format, share context and screen have to be + taken from this QOpenGLContext and the resulting platform context is expected to be + backed by a native context that fulfills these criteria. + + If the context has native handles set, no new native context is expected to be created. + Instead, the provided handles have to be used. In this case the ownership of the handle + must not be taken and the platform implementation is not allowed to destroy the native + context. Configuration parameters like the format are also to be ignored. Instead, the + platform implementation is responsible for querying the configuriation from the provided + native context. + + Returns a pointer to a QPlatformOpenGLContext instance or \c NULL if the context could + not be created. + + \sa QOpenGLContext +*/ QPlatformOpenGLContext *QPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { Q_UNUSED(context); qWarning("This plugin does not support createPlatformOpenGLContext!"); return 0; } -#endif +#endif // QT_NO_OPENGL /*! Factory function for QPlatformSharedGraphicsCache. This function will return 0 if the platform diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h index b88f2a7e84..5731b4f56a 100644 --- a/src/gui/kernel/qplatformmenu.h +++ b/src/gui/kernel/qplatformmenu.h @@ -86,7 +86,7 @@ public: virtual void setChecked(bool isChecked) = 0; virtual void setShortcut(const QKeySequence& shortcut) = 0; virtual void setEnabled(bool enabled) = 0; - + virtual void setIconSize(int size) = 0; virtual void setNativeContents(WId item) { Q_UNUSED(item); } Q_SIGNALS: @@ -98,6 +98,8 @@ class Q_GUI_EXPORT QPlatformMenu : public QObject { Q_OBJECT public: + enum MenuType { DefaultMenu = 0, EditMenu }; + virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) = 0; virtual void removeMenuItem(QPlatformMenuItem *menuItem) = 0; virtual void syncMenuItem(QPlatformMenuItem *menuItem) = 0; @@ -112,11 +114,17 @@ public: virtual void setVisible(bool visible) = 0; virtual void setMinimumWidth(int width) { Q_UNUSED(width); } virtual void setFont(const QFont &font) { Q_UNUSED(font); } + virtual void setMenuType(MenuType type) { Q_UNUSED(type); } virtual void showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item) { + showPopup(parentWindow, QRect(pos, QSize()), item); + } + + virtual void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) + { Q_UNUSED(parentWindow); - Q_UNUSED(pos); + Q_UNUSED(targetRect); Q_UNUSED(item); setVisible(true); } diff --git a/src/gui/kernel/qplatformnativeinterface.cpp b/src/gui/kernel/qplatformnativeinterface.cpp index 6571a47849..2e5485f1c2 100644 --- a/src/gui/kernel/qplatformnativeinterface.cpp +++ b/src/gui/kernel/qplatformnativeinterface.cpp @@ -118,6 +118,12 @@ QPlatformNativeInterface::NativeResourceForBackingStoreFunction QPlatformNativeI return 0; } +QFunctionPointer QPlatformNativeInterface::platformFunction(const QByteArray &function) const +{ + Q_UNUSED(function); + return Q_NULLPTR; +} + /*! Contains generic window properties that the platform may utilize. */ diff --git a/src/gui/kernel/qplatformnativeinterface.h b/src/gui/kernel/qplatformnativeinterface.h index eaa24a9e55..58d13c4320 100644 --- a/src/gui/kernel/qplatformnativeinterface.h +++ b/src/gui/kernel/qplatformnativeinterface.h @@ -85,6 +85,8 @@ public: virtual NativeResourceForWindowFunction nativeResourceFunctionForWindow(const QByteArray &resource); virtual NativeResourceForBackingStoreFunction nativeResourceFunctionForBackingStore(const QByteArray &resource); + virtual QFunctionPointer platformFunction(const QByteArray &function) const; + virtual QVariantMap windowProperties(QPlatformWindow *window) const; virtual QVariant windowProperty(QPlatformWindow *window, const QString &name) const; virtual QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const; diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp index 6bf7915425..a7ff94ac4f 100644 --- a/src/gui/kernel/qplatformscreen.cpp +++ b/src/gui/kernel/qplatformscreen.cpp @@ -275,15 +275,6 @@ QPlatformScreen * QPlatformScreen::platformScreenForWindow(const QWindow *window */ /*! - Implemented in subclasses to return a page flipper object for the screen, or 0 if the - hardware does not support page flipping. The default implementation returns 0. - */ -QPlatformScreenPageFlipper *QPlatformScreen::pageFlipper() const -{ - return 0; -} - -/*! Reimplement this function in subclass to return the cursor of the screen. The default implementation returns 0. diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h index 085a147e8d..151a6386d9 100644 --- a/src/gui/kernel/qplatformscreen.h +++ b/src/gui/kernel/qplatformscreen.h @@ -71,7 +71,6 @@ class QPlatformOpenGLContext; class QPlatformScreenPrivate; class QPlatformWindow; class QPlatformCursor; -class QPlatformScreenPageFlipper; class QScreen; class QSurfaceFormat; @@ -115,7 +114,6 @@ public: virtual QString name() const { return QString(); } - virtual QPlatformScreenPageFlipper *pageFlipper() const; virtual QPlatformCursor *cursor() const; protected: diff --git a/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp b/src/gui/kernel/qplatformsystemtrayicon.cpp index bc37f99210..bc37f99210 100644 --- a/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp +++ b/src/gui/kernel/qplatformsystemtrayicon.cpp diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index d3d3d3c222..d1b1106b28 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -508,7 +508,11 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint) case MousePressAndHoldInterval: return QVariant(800); case MouseDoubleClickDistance: - return QVariant(5); + { + bool ok = false; + int dist = qgetenv("QT_DBL_CLICK_DIST").toInt(&ok); + return QVariant(ok ? dist : 5); + } } return QVariant(); } diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h index a2d14be0fb..ad2b4a2164 100644 --- a/src/gui/kernel/qplatformtheme.h +++ b/src/gui/kernel/qplatformtheme.h @@ -276,6 +276,7 @@ public: virtual QPlatformMenuItem* createPlatformMenuItem() const; virtual QPlatformMenu* createPlatformMenu() const; virtual QPlatformMenuBar* createPlatformMenuBar() const; + virtual void showPlatformMenuBar() {} virtual bool usePlatformNativeDialog(DialogType type) const; virtual QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const; diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index faaf418522..bb7b690992 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -474,6 +474,29 @@ QString QPlatformWindow::formatWindowTitle(const QString &title, const QString & } /*! + Helper function for finding the new screen for \a newGeometry in response to + a geometry changed event. Returns the new screen if the window was moved to + another virtual sibling. If the screen changes, the platform plugin should call + QWindowSystemInterface::handleWindowScreenChanged(). + \note: The current screen will always be returned for child windows since + they should never signal screen changes. + + \since 5.4 + \sa QWindowSystemInterface::handleWindowScreenChanged() +*/ +QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) const +{ + QPlatformScreen *currentScreen = screen(); + if (!parent() && !currentScreen->geometry().intersects(newGeometry)) { + Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) { + if (screen->geometry().intersects(newGeometry)) + return screen; + } + } + return currentScreen; +} + +/*! Reimplement this method to set whether the window demands attention (for example, by flashing the taskbar icon) depending on \a enabled. diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index 39bd8324a0..8f0e5ff352 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -139,6 +139,7 @@ public: protected: static QString formatWindowTitle(const QString &title, const QString &separator); + QPlatformScreen *screenForGeometry(const QRect &newGeometry) const; QScopedPointer<QPlatformWindowPrivate> d_ptr; private: diff --git a/src/gui/kernel/qrasterwindow.cpp b/src/gui/kernel/qrasterwindow.cpp new file mode 100644 index 0000000000..5f4d707f86 --- /dev/null +++ b/src/gui/kernel/qrasterwindow.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** + ** + ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/legal + ** + ** This file is part of the QtGui module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and Digia. For licensing terms and + ** conditions see http://qt.digia.com/licensing. For further information + ** use the contact form at http://qt.digia.com/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 2.1 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 2.1 requirements + ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Digia gives you certain additional + ** rights. These rights are described in the Digia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3.0 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 3.0 requirements will be + ** met: http://www.gnu.org/copyleft/gpl.html. + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include "qrasterwindow.h" + +#include <QtGui/private/qpaintdevicewindow_p.h> + +#include <QtGui/QBackingStore> +#include <QtGui/QPainter> + +QT_BEGIN_NAMESPACE + +/*! + \class QRasterWindow + \inmodule QtGui + \since 5.4 + \brief QRasterWindow is a convenience class for using QPainter on a QWindow + + QRasterWindow is a QWindow with a raster-based, non-OpenGL surface. On top of + the functionality offered by QWindow, QRasterWindow adds a virtual + paintEvent() function and the possibility to open a QPainter on itself. The + underlying paint engine will be the raster one, meaning that all drawing will + happen on the CPU. For performing accelerated, OpenGL-based drawing, use + QOpenGLWindow instead. + + Internally the class is thin wrapper for QWindow and QBackingStore + and is very similar to the \l{Raster Window Example}{Raster Window + Example} that uses these classes directly. + + \sa QPaintDeviceWindow::paintEvent(), QPaintDeviceWindow::update() +*/ + +class QRasterWindowPrivate : public QPaintDeviceWindowPrivate +{ + Q_DECLARE_PUBLIC(QRasterWindow) +public: + void beginPaint(const QRegion ®ion) Q_DECL_OVERRIDE + { + Q_Q(QRasterWindow); + if (backingstore->size() != q->size()) { + backingstore->resize(q->size()); + markWindowAsDirty(); + } + backingstore->beginPaint(region); + } + + void endPaint() Q_DECL_OVERRIDE + { + backingstore->endPaint(); + } + + void flush(const QRegion ®ion) Q_DECL_OVERRIDE + { + Q_Q(QRasterWindow); + backingstore->flush(region, q); + } + + QScopedPointer<QBackingStore> backingstore; +}; + +/*! + Constructs a new QRasterWindow with \a parent. +*/ +QRasterWindow::QRasterWindow(QWindow *parent) + : QPaintDeviceWindow(*(new QRasterWindowPrivate), parent) +{ + setSurfaceType(QSurface::RasterSurface); + d_func()->backingstore.reset(new QBackingStore(this)); +} + +/*! + \internal +*/ +int QRasterWindow::metric(PaintDeviceMetric metric) const +{ + Q_D(const QRasterWindow); + + switch (metric) { + case PdmDepth: + return d->backingstore->paintDevice()->depth(); + case PdmDevicePixelRatio: + return d->backingstore->paintDevice()->devicePixelRatio(); + default: + break; + } + return QPaintDeviceWindow::metric(metric); +} + +/*! + \internal +*/ +QPaintDevice *QRasterWindow::redirected(QPoint *) const +{ + Q_D(const QRasterWindow); + return d->backingstore->paintDevice(); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qkeymapper_qpa.cpp b/src/gui/kernel/qrasterwindow.h index 3966909db1..93e8421c6b 100644 --- a/src/gui/kernel/qkeymapper_qpa.cpp +++ b/src/gui/kernel/qrasterwindow.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -39,44 +39,31 @@ ** ****************************************************************************/ -#include "qkeymapper_p.h" -#include <qdebug.h> -#include <private/qevent_p.h> -#include <private/qlocale_p.h> -#include <private/qguiapplication_p.h> -#include <qpa/qplatformintegration.h> +#ifndef QRASTERWINDOW_H +#define QRASTERWINDOW_H -QT_BEGIN_NAMESPACE +#include <QtGui/QPaintDeviceWindow> -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE +class QRasterWindowPrivate; -QKeyMapperPrivate::QKeyMapperPrivate() +class Q_GUI_EXPORT QRasterWindow : public QPaintDeviceWindow { - keyboardInputLocale = QLocale::system(); - keyboardInputDirection = keyboardInputLocale.textDirection(); -} + Q_OBJECT + Q_DECLARE_PRIVATE(QRasterWindow) -QKeyMapperPrivate::~QKeyMapperPrivate() -{ - // clearMappings(); -} +public: + explicit QRasterWindow(QWindow *parent = 0); -void QKeyMapperPrivate::clearMappings() -{ -} +protected: + int metric(PaintDeviceMetric metric) const Q_DECL_OVERRIDE; + QPaintDevice *redirected(QPoint *) const Q_DECL_OVERRIDE; -QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e) -{ - QList<int> result = QGuiApplicationPrivate::platformIntegration()->possibleKeys(e); - if (!result.isEmpty()) - return result; - - if (e->key() && (e->key() != Qt::Key_unknown)) - result << int(e->key() + e->modifiers()); - else if (!e->text().isEmpty()) - result << int(e->text().at(0).unicode() + e->modifiers()); - return result; -} +private: + Q_DISABLE_COPY(QRasterWindow) +}; QT_END_NAMESPACE + +#endif diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 70ee631fc8..90f48d4593 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -74,6 +74,16 @@ QScreen::QScreen(QPlatformScreen *screen) { } + +/*! + Destroys the screen. + */ +QScreen::~QScreen() +{ + if (qApp) + Q_EMIT qApp->screenRemoved(this); +} + /*! Get the platform screen handle. */ diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h index bdd5939657..4ee48ad5ad 100644 --- a/src/gui/kernel/qscreen.h +++ b/src/gui/kernel/qscreen.h @@ -69,11 +69,11 @@ class Q_GUI_EXPORT QScreen : public QObject Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(int depth READ depth CONSTANT) Q_PROPERTY(QSize size READ size NOTIFY geometryChanged) - Q_PROPERTY(QSize availableSize READ availableSize NOTIFY virtualGeometryChanged) + Q_PROPERTY(QSize availableSize READ availableSize NOTIFY availableGeometryChanged) Q_PROPERTY(QSize virtualSize READ virtualSize NOTIFY virtualGeometryChanged) Q_PROPERTY(QSize availableVirtualSize READ availableVirtualSize NOTIFY virtualGeometryChanged) Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged) - Q_PROPERTY(QRect availableGeometry READ availableGeometry NOTIFY virtualGeometryChanged) + Q_PROPERTY(QRect availableGeometry READ availableGeometry NOTIFY availableGeometryChanged) Q_PROPERTY(QRect virtualGeometry READ virtualGeometry NOTIFY virtualGeometryChanged) Q_PROPERTY(QRect availableVirtualGeometry READ availableVirtualGeometry NOTIFY virtualGeometryChanged) Q_PROPERTY(QSizeF physicalSize READ physicalSize NOTIFY physicalSizeChanged) @@ -89,6 +89,7 @@ class Q_GUI_EXPORT QScreen : public QObject Q_PROPERTY(qreal refreshRate READ refreshRate NOTIFY refreshRateChanged) public: + ~QScreen(); QPlatformScreen *handle() const; QString name() const; @@ -141,6 +142,7 @@ public: Q_SIGNALS: void geometryChanged(const QRect &geometry); + void availableGeometryChanged(const QRect &geometry); void physicalSizeChanged(const QSizeF &size); void physicalDotsPerInchChanged(qreal dpi); void logicalDotsPerInchChanged(qreal dpi); diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp index 2b8e611dff..f077abc6a2 100644 --- a/src/gui/kernel/qsurfaceformat.cpp +++ b/src/gui/kernel/qsurfaceformat.cpp @@ -196,6 +196,9 @@ public: /*! Constructs a default initialized QSurfaceFormat. + + \note By default OpenGL 2.0 is requested since this provides the highest + grade of portability between platforms and OpenGL implementations. */ QSurfaceFormat::QSurfaceFormat() : d(new QSurfaceFormatPrivate) { @@ -730,6 +733,43 @@ int QSurfaceFormat::swapInterval() const return d->swapInterval; } +Q_GLOBAL_STATIC(QSurfaceFormat, qt_default_surface_format) + +/*! + Sets the global default surface \a format. + + This format is used by default in QOpenGLContext, QWindow, QOpenGLWidget and + similar classes. + + It can always be overridden on a per-instance basis by using the class in + question's own setFormat() function. However, it is often more convenient to + set the format for all windows once at the start of the application. It also + guarantees proper behavior in cases where shared contexts are required, + because settings the format via this function guarantees that all contexts + and surfaces, even the ones created internally by Qt, will use the same + format. + + \since 5.4 + \sa defaultFormat() + */ +void QSurfaceFormat::setDefaultFormat(const QSurfaceFormat &format) +{ + *qt_default_surface_format() = format; +} + +/*! + Returns the global default surface format. + + When setDefaultFormat() is not called, this is a default-constructed QSurfaceFormat. + + \since 5.4 + \sa setDefaultFormat() + */ +QSurfaceFormat QSurfaceFormat::defaultFormat() +{ + return *qt_default_surface_format(); +} + /*! Returns \c true if all the options of the two QSurfaceFormat objects \a a and \a b are equal. diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h index 453beac5cd..05aba2f83c 100644 --- a/src/gui/kernel/qsurfaceformat.h +++ b/src/gui/kernel/qsurfaceformat.h @@ -138,6 +138,9 @@ public: int swapInterval() const; void setSwapInterval(int interval); + static void setDefaultFormat(const QSurfaceFormat &format); + static QSurfaceFormat defaultFormat(); + private: QSurfaceFormatPrivate *d; diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 6724d68c95..2cf4f41126 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -156,9 +156,7 @@ QWindow::QWindow(QScreen *targetScreen) , QSurface(QSurface::Window) { Q_D(QWindow); - d->screen = targetScreen; - if (!d->screen) - d->screen = QGuiApplication::primaryScreen(); + d->connectToScreen(targetScreen ? targetScreen : QGuiApplication::primaryScreen()); d->init(); } @@ -178,10 +176,8 @@ QWindow::QWindow(QWindow *parent) { Q_D(QWindow); d->parentWindow = parent; - if (parent) - d->screen = parent->screen(); - if (!d->screen) - d->screen = QGuiApplication::primaryScreen(); + if (!parent) + d->connectToScreen(QGuiApplication::primaryScreen()); d->init(); } @@ -203,10 +199,8 @@ QWindow::QWindow(QWindowPrivate &dd, QWindow *parent) { Q_D(QWindow); d->parentWindow = parent; - if (parent) - d->screen = parent->screen(); - if (!d->screen) - d->screen = QGuiApplication::primaryScreen(); + if (!parent) + d->connectToScreen(QGuiApplication::primaryScreen()); d->init(); } @@ -215,14 +209,8 @@ QWindow::QWindow(QWindowPrivate &dd, QWindow *parent) */ QWindow::~QWindow() { - if (QGuiApplicationPrivate::focus_window == this) - QGuiApplicationPrivate::focus_window = 0; - if (QGuiApplicationPrivate::currentMouseWindow == this) - QGuiApplicationPrivate::currentMouseWindow = 0; - if (QGuiApplicationPrivate::tabletPressTarget == this) - QGuiApplicationPrivate::tabletPressTarget = 0; - QGuiApplicationPrivate::window_list.removeAll(this); destroy(); + QGuiApplicationPrivate::window_list.removeAll(this); } void QWindowPrivate::init() @@ -231,12 +219,13 @@ void QWindowPrivate::init() // If your application aborts here, you are probably creating a QWindow // before the screen list is populated. - if (!screen) { + if (!parentWindow && !topLevelScreen) { qFatal("Cannot create window: no screens available"); exit(1); } - QObject::connect(screen, SIGNAL(destroyed(QObject*)), q, SLOT(screenDestroyed(QObject*))); QGuiApplicationPrivate::window_list.prepend(q); + + requestedFormat = QSurfaceFormat::defaultFormat(); } /*! @@ -353,23 +342,57 @@ void QWindowPrivate::updateVisibility() emit q->visibilityChanged(visibility); } -void QWindowPrivate::setScreen(QScreen *newScreen, bool recreate) +inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const +{ + Q_Q(const QWindow); + const QScreen *oldScreen = q->screen(); + return oldScreen != newScreen && platformWindow + && !(oldScreen && oldScreen->virtualSiblings().contains(newScreen)); +} + +inline void QWindowPrivate::disconnectFromScreen() +{ + if (topLevelScreen) { + Q_Q(QWindow); + QObject::disconnect(topLevelScreen, &QObject::destroyed, q, &QWindow::screenDestroyed); + topLevelScreen = 0; + } +} + +void QWindowPrivate::connectToScreen(QScreen *screen) { Q_Q(QWindow); - if (newScreen != screen) { - const bool shouldRecreate = recreate && platformWindow != 0 - && !(screen && screen->virtualSiblings().contains(newScreen)); + disconnectFromScreen(); + topLevelScreen = screen; + if (topLevelScreen) + QObject::connect(topLevelScreen, &QObject::destroyed, q, &QWindow::screenDestroyed); +} + +void QWindowPrivate::emitScreenChangedRecursion(QScreen *newScreen) +{ + Q_Q(QWindow); + emit q->screenChanged(newScreen); + foreach (QObject *child, q->children()) { + if (child->isWindowType()) + static_cast<QWindow *>(child)->d_func()->emitScreenChangedRecursion(newScreen); + } +} + +void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate) +{ + Q_Q(QWindow); + if (parentWindow) { + qWarning() << this << Q_FUNC_INFO << '(' << newScreen << "): Attempt to set a screen on a child window."; + return; + } + if (newScreen != topLevelScreen) { + const bool shouldRecreate = recreate && windowRecreationRequired(newScreen); if (shouldRecreate) q->destroy(); - if (screen) - q->disconnect(screen, SIGNAL(destroyed(QObject*)), q, SLOT(screenDestroyed(QObject*))); - screen = newScreen; - if (newScreen) { - q->connect(screen, SIGNAL(destroyed(QObject*)), q, SLOT(screenDestroyed(QObject*))); - if (shouldRecreate) - create(true); - } - emit q->screenChanged(newScreen); + connectToScreen(newScreen); + if (newScreen && shouldRecreate) + create(true); + emitScreenChangedRecursion(newScreen); } } @@ -455,11 +478,14 @@ void QWindow::setVisible(bool visible) QCoreApplication::removePostedEvents(qApp, QEvent::Quit); if (type() == Qt::Window) { - QString &firstWindowTitle = QGuiApplicationPrivate::instance()->firstWindowTitle; + QGuiApplicationPrivate *app_priv = QGuiApplicationPrivate::instance(); + QString &firstWindowTitle = app_priv->firstWindowTitle; if (!firstWindowTitle.isEmpty()) { setTitle(firstWindowTitle); firstWindowTitle = QString(); } + if (!app_priv->forcedWindowIcon.isNull()) + setIcon(app_priv->forcedWindowIcon); } QShowEvent showEvent; @@ -557,8 +583,20 @@ QWindow *QWindow::parent() const void QWindow::setParent(QWindow *parent) { Q_D(QWindow); + if (d->parentWindow == parent) + return; + + QScreen *newScreen = parent ? parent->screen() : screen(); + if (d->windowRecreationRequired(newScreen)) { + qWarning() << this << Q_FUNC_INFO << '(' << parent << "): Cannot change screens (" << screen() << newScreen << ')'; + return; + } QObject::setParent(parent); + if (parent) + d->disconnectFromScreen(); + else + d->connectToScreen(newScreen); if (d->platformWindow) { if (parent && parent->d_func()->platformWindow) { @@ -644,7 +682,13 @@ void QWindow::setModality(Qt::WindowModality modality) this function after create() has been called will not re-resolve the surface format of the native surface. - \sa create(), destroy() + When the format is not explicitly set via this function, the format returned + by QSurfaceFormat::defaultFormat() will be used. This means that when having + multiple windows, individual calls to this function can be replaced by one + single call to QSurfaceFormat::setDefaultFormat() before creating the first + window. + + \sa create(), destroy(), QSurfaceFormat::setDefaultFormat() */ void QWindow::setFormat(const QSurfaceFormat &format) { @@ -1532,21 +1576,36 @@ void QWindow::resize(const QSize &newSize) void QWindow::destroy() { Q_D(QWindow); + if (!d->platformWindow) + return; + QObjectList childrenWindows = children(); for (int i = 0; i < childrenWindows.size(); i++) { QObject *object = childrenWindows.at(i); if (object->isWindowType()) { QWindow *w = static_cast<QWindow*>(object); - QGuiApplicationPrivate::window_list.removeAll(w); w->destroy(); } } + + if (QGuiApplicationPrivate::focus_window == this) + QGuiApplicationPrivate::focus_window = parent(); + if (QGuiApplicationPrivate::currentMouseWindow == this) + QGuiApplicationPrivate::currentMouseWindow = parent(); + if (QGuiApplicationPrivate::tabletPressTarget == this) + QGuiApplicationPrivate::tabletPressTarget = parent(); + + bool wasVisible = isVisible(); + setVisible(false); delete d->platformWindow; d->resizeEventPending = true; d->receivedExpose = false; d->exposed = false; d->platformWindow = 0; + + if (wasVisible) + d->maybeQuitOnLastWindowClosed(); } /*! @@ -1613,15 +1672,14 @@ bool QWindow::setMouseGrabEnabled(bool grab) /*! Returns the screen on which the window is shown. - The value returned will not change when the window is moved - between virtual screens (as returned by QScreen::virtualSiblings()). + For child windows, this returns the screen of the corresponding top level window. \sa setScreen(), QScreen::virtualSiblings() */ QScreen *QWindow::screen() const { Q_D(const QWindow); - return d->screen; + return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen; } /*! @@ -1632,6 +1690,8 @@ QScreen *QWindow::screen() const Note that if the screen is part of a virtual desktop of multiple screens, the window can appear on any of the screens returned by QScreen::virtualSiblings(). + This function only works for top level windows. + \sa screen(), QScreen::virtualSiblings() */ void QWindow::setScreen(QScreen *newScreen) @@ -1639,13 +1699,15 @@ void QWindow::setScreen(QScreen *newScreen) Q_D(QWindow); if (!newScreen) newScreen = QGuiApplication::primaryScreen(); - d->setScreen(newScreen, true /* recreate */); + d->setTopLevelScreen(newScreen, true /* recreate */); } void QWindow::screenDestroyed(QObject *object) { Q_D(QWindow); - if (object == static_cast<QObject *>(d->screen)) { + if (d->parentWindow) + return; + if (object == static_cast<QObject *>(d->topLevelScreen)) { const bool wasVisible = isVisible(); setScreen(0); // destroy() might have hidden our window, show it again. @@ -1801,15 +1863,13 @@ bool QWindow::close() if (parent()) return false; - if (QGuiApplicationPrivate::focus_window == this) - QGuiApplicationPrivate::focus_window = 0; - if (QGuiApplicationPrivate::currentMouseWindow == this) - QGuiApplicationPrivate::currentMouseWindow = 0; + if (!d->platformWindow) + return true; - QGuiApplicationPrivate::window_list.removeAll(this); - destroy(); - d->maybeQuitOnLastWindowClosed(); - return true; + bool accepted = false; + QWindowSystemInterface::handleCloseEvent(this, &accepted); + QWindowSystemInterface::flushWindowSystemEvents(); + return accepted; } /*! @@ -1955,15 +2015,10 @@ bool QWindow::event(QEvent *ev) break; #endif - case QEvent::Close: { - Q_D(QWindow); - bool wasVisible = isVisible(); - if (ev->isAccepted()) { + case QEvent::Close: + if (ev->isAccepted()) destroy(); - if (wasVisible) - d->maybeQuitOnLastWindowClosed(); - } - break; } + break; case QEvent::Expose: exposeEvent(static_cast<QExposeEvent *>(ev)); @@ -2175,8 +2230,10 @@ Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window) void QWindowPrivate::maybeQuitOnLastWindowClosed() { - Q_Q(QWindow); + if (!QCoreApplication::instance()) + return; + Q_Q(QWindow); // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent bool quitOnClose = QGuiApplication::quitOnLastWindowClosed() && !q->parent(); @@ -2335,7 +2392,7 @@ void QWindowPrivate::setCursor(const QCursor *newCursor) hasCursor = false; } // Only attempt to set cursor and emit signal if there is an actual platform cursor - if (screen->handle()->cursor()) { + if (q->screen()->handle()->cursor()) { applyCursor(); QEvent event(QEvent::CursorChange); QGuiApplication::sendEvent(q, &event); @@ -2346,7 +2403,7 @@ void QWindowPrivate::applyCursor() { Q_Q(QWindow); if (platformWindow) { - if (QPlatformCursor *platformCursor = screen->handle()->cursor()) { + if (QPlatformCursor *platformCursor = q->screen()->handle()->cursor()) { QCursor *c = QGuiApplication::overrideCursor(); if (!c && hasCursor) c = &cursor; diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index 51d78bb9cd..cd789a6b71 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -95,11 +95,12 @@ public: , modality(Qt::NonModal) , blockedByModalWindow(false) , transientParent(0) - , screen(0) + , topLevelScreen(0) #ifndef QT_NO_CURSOR , cursor(Qt::ArrowCursor) , hasCursor(false) #endif + , compositing(false) { isWindow = true; } @@ -131,8 +132,12 @@ public: void updateVisibility(); void _q_clearAlert(); - void setScreen(QScreen *newScreen, bool recreate); + bool windowRecreationRequired(QScreen *newScreen) const; void create(bool recursive); + void setTopLevelScreen(QScreen *newScreen, bool recreate); + void connectToScreen(QScreen *topLevelScreen); + void disconnectFromScreen(); + void emitScreenChangedRecursion(QScreen *newScreen); virtual void clearFocusObject(); @@ -166,12 +171,14 @@ public: bool blockedByModalWindow; QPointer<QWindow> transientParent; - QScreen *screen; + QScreen *topLevelScreen; #ifndef QT_NO_CURSOR QCursor cursor; bool hasCursor; #endif + + bool compositing; }; diff --git a/src/gui/kernel/qwindowdefs_win.h b/src/gui/kernel/qwindowdefs_win.h index fea995a0f5..0dd027e585 100644 --- a/src/gui/kernel/qwindowdefs_win.h +++ b/src/gui/kernel/qwindowdefs_win.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -107,7 +107,7 @@ Q_DECLARE_HANDLE(HRGN); #ifndef HMONITOR Q_DECLARE_HANDLE(HMONITOR); #endif -#ifndef HRESULT +#ifndef _HRESULT_DEFINED typedef long HRESULT; #endif diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 49ff8bcb0d..59766d0bb2 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -133,11 +133,11 @@ void QWindowSystemInterface::handleWindowScreenChanged(QWindow *tlw, QScreen *sc QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState) +void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate) { Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)); QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e = - new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState); + new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState, forcePropagate); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } @@ -493,17 +493,10 @@ void QWindowSystemInterface::handleScreenOrientationChange(QScreen *screen, Qt:: QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -void QWindowSystemInterface::handleScreenGeometryChange(QScreen *screen, const QRect &geometry) +void QWindowSystemInterface::handleScreenGeometryChange(QScreen *screen, const QRect &geometry, const QRect &availableGeometry) { QWindowSystemInterfacePrivate::ScreenGeometryEvent *e = - new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screen, geometry); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); -} - -void QWindowSystemInterface::handleScreenAvailableGeometryChange(QScreen *screen, const QRect &availableGeometry) -{ - QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e = - new QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent(screen, availableGeometry); + new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screen, geometry, availableGeometry); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } @@ -629,24 +622,42 @@ void QWindowSystemInterface::handleFileOpenEvent(const QUrl &url) QGuiApplicationPrivate::processWindowSystemEvent(&e); } -void QWindowSystemInterface::handleTabletEvent(QWindow *w, ulong timestamp, bool down, const QPointF &local, const QPointF &global, - int device, int pointerType, qreal pressure, int xTilt, int yTilt, +void QWindowSystemInterface::handleTabletEvent(QWindow *w, ulong timestamp, const QPointF &local, const QPointF &global, + int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, qint64 uid, Qt::KeyboardModifiers modifiers) { QWindowSystemInterfacePrivate::TabletEvent *e = - new QWindowSystemInterfacePrivate::TabletEvent(w, timestamp, down, local, global, device, pointerType, pressure, + new QWindowSystemInterfacePrivate::TabletEvent(w, timestamp, local, global, device, pointerType, buttons, pressure, xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } +void QWindowSystemInterface::handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global, + int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, + qreal tangentialPressure, qreal rotation, int z, qint64 uid, + Qt::KeyboardModifiers modifiers) +{ + ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleTabletEvent(w, time, local, global, device, pointerType, buttons, pressure, + xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); +} + +void QWindowSystemInterface::handleTabletEvent(QWindow *w, ulong timestamp, bool down, const QPointF &local, const QPointF &global, + int device, int pointerType, qreal pressure, int xTilt, int yTilt, + qreal tangentialPressure, qreal rotation, int z, qint64 uid, + Qt::KeyboardModifiers modifiers) +{ + handleTabletEvent(w, timestamp, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure, + xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); +} + void QWindowSystemInterface::handleTabletEvent(QWindow *w, bool down, const QPointF &local, const QPointF &global, int device, int pointerType, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, qint64 uid, Qt::KeyboardModifiers modifiers) { - ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleTabletEvent(w, time, down, local, global, device, pointerType, pressure, + handleTabletEvent(w, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure, xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); } diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 71feb1bcb7..c681185c35 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -138,6 +138,7 @@ public: static void handleTouchCancelEvent(QWindow *w, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier); static void handleTouchCancelEvent(QWindow *w, ulong timestamp, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier); + // rect is relative to parent static void handleGeometryChange(QWindow *w, const QRect &newRect, const QRect &oldRect = QRect()); static void handleCloseEvent(QWindow *w, bool *accepted = 0); static void handleEnterEvent(QWindow *w, const QPointF &local = QPointF(), const QPointF& global = QPointF()); @@ -148,8 +149,9 @@ public: static void handleWindowStateChanged(QWindow *w, Qt::WindowState newState); static void handleWindowScreenChanged(QWindow *w, QScreen *newScreen); - static void handleApplicationStateChanged(Qt::ApplicationState newState); + static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false); + // region is in local coordinates, do not confuse with geometry which is parent-relative static void handleExposeEvent(QWindow *tlw, const QRegion ®ion); #ifndef QT_NO_DRAGANDDROP @@ -162,8 +164,7 @@ public: // Changes to the screen static void handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation newOrientation); - static void handleScreenGeometryChange(QScreen *screen, const QRect &newGeometry); - static void handleScreenAvailableGeometryChange(QScreen *screen, const QRect &newAvailableGeometry); + static void handleScreenGeometryChange(QScreen *screen, const QRect &newGeometry, const QRect &newAvailableGeometry); static void handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal newDpiX, qreal newDpiY); static void handleScreenRefreshRateChange(QScreen *screen, qreal newRefreshRate); @@ -172,14 +173,22 @@ public: static void handleFileOpenEvent(const QString& fileName); static void handleFileOpenEvent(const QUrl &url); + static void handleTabletEvent(QWindow *w, ulong timestamp, const QPointF &local, const QPointF &global, + int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, + qreal tangentialPressure, qreal rotation, int z, qint64 uid, + Qt::KeyboardModifiers modifiers = Qt::NoModifier); + static void handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global, + int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, + qreal tangentialPressure, qreal rotation, int z, qint64 uid, + Qt::KeyboardModifiers modifiers = Qt::NoModifier); static void handleTabletEvent(QWindow *w, ulong timestamp, bool down, const QPointF &local, const QPointF &global, int device, int pointerType, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, qint64 uid, - Qt::KeyboardModifiers modifiers = Qt::NoModifier); + Qt::KeyboardModifiers modifiers = Qt::NoModifier); // ### remove in Qt 6 static void handleTabletEvent(QWindow *w, bool down, const QPointF &local, const QPointF &global, int device, int pointerType, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, qint64 uid, - Qt::KeyboardModifiers modifiers = Qt::NoModifier); + Qt::KeyboardModifiers modifiers = Qt::NoModifier); // ### remove in Qt 6 static void handleTabletEnterProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid); static void handleTabletEnterProximityEvent(int device, int pointerType, qint64 uid); static void handleTabletLeaveProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 8e503bbf3d..87f40e2b04 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -176,11 +176,12 @@ public: class ApplicationStateChangedEvent : public WindowSystemEvent { public: - ApplicationStateChangedEvent(Qt::ApplicationState newState) - : WindowSystemEvent(ApplicationStateChanged), newState(newState) + ApplicationStateChangedEvent(Qt::ApplicationState newState, bool forcePropagate = false) + : WindowSystemEvent(ApplicationStateChanged), newState(newState), forcePropagate(forcePropagate) { } Qt::ApplicationState newState; + bool forcePropagate; }; class FlushEventsEvent : public WindowSystemEvent { @@ -278,17 +279,10 @@ public: class ScreenGeometryEvent : public WindowSystemEvent { public: - ScreenGeometryEvent(QScreen *s, const QRect &g) - : WindowSystemEvent(ScreenGeometry), screen(s), geometry(g) { } + ScreenGeometryEvent(QScreen *s, const QRect &g, const QRect &ag) + : WindowSystemEvent(ScreenGeometry), screen(s), geometry(g), availableGeometry(ag) { } QPointer<QScreen> screen; QRect geometry; - }; - - class ScreenAvailableGeometryEvent : public WindowSystemEvent { - public: - ScreenAvailableGeometryEvent(QScreen *s, const QRect &g) - : WindowSystemEvent(ScreenAvailableGeometry), screen(s), availableGeometry(g) { } - QPointer<QScreen> screen; QRect availableGeometry; }; @@ -337,19 +331,19 @@ public: class TabletEvent : public InputEvent { public: - static void handleTabletEvent(QWindow *w, bool down, const QPointF &local, const QPointF &global, - int device, int pointerType, qreal pressure, int xTilt, int yTilt, + static void handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global, + int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, qint64 uid, Qt::KeyboardModifiers modifiers = Qt::NoModifier); - TabletEvent(QWindow *w, ulong time, bool down, const QPointF &local, const QPointF &global, - int device, int pointerType, qreal pressure, int xTilt, int yTilt, qreal tpressure, + TabletEvent(QWindow *w, ulong time, const QPointF &local, const QPointF &global, + int device, int pointerType, Qt::MouseButtons b, qreal pressure, int xTilt, int yTilt, qreal tpressure, qreal rotation, int z, qint64 uid, Qt::KeyboardModifiers mods) : InputEvent(w, time, Tablet, mods), - down(down), local(local), global(global), device(device), pointerType(pointerType), + buttons(b), local(local), global(global), device(device), pointerType(pointerType), pressure(pressure), xTilt(xTilt), yTilt(yTilt), tangentialPressure(tpressure), rotation(rotation), z(z), uid(uid) { } - bool down; + Qt::MouseButtons buttons; QPointF local; QPointF global; int device; |