From 76adb6c29f9284a3d7cceb8fb09c3bb7c4cd5e1b Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 21 Apr 2016 01:39:27 +0200 Subject: [PATCH 01/16] xcb: Use the state of the key event to process it Instead of the global state Task-number: QTBUG-48795 Change-Id: Ic2c545718adb68df41730e5a3bf25adb374ffce3 Reviewed-by: Frederik Gladhorn Reviewed-by: Edward Welbourne Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 72 +++++++++++++--------- src/plugins/platforms/xcb/qxcbkeyboard.h | 2 + 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 28de86b8ba2..e0fcc01fb41 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -742,8 +742,7 @@ void QXcbKeyboard::updateKeymap() // update xkb state object xkb_state_unref(xkb_state); xkb_state = new_state; - if (!connection()->hasXKB()) - updateXKBMods(); + updateXKBMods(); checkForLatinLayout(); } @@ -768,32 +767,37 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state) } #endif +void QXcbKeyboard::updateXKBStateFromState(struct xkb_state *kb_state, quint16 state) +{ + const quint32 modsDepressed = xkb_state_serialize_mods(kb_state, XKB_STATE_MODS_DEPRESSED); + const quint32 modsLatched = xkb_state_serialize_mods(kb_state, XKB_STATE_MODS_LATCHED); + const quint32 modsLocked = xkb_state_serialize_mods(kb_state, XKB_STATE_MODS_LOCKED); + const quint32 xkbMask = xkbModMask(state); + + const quint32 latched = modsLatched & xkbMask; + const quint32 locked = modsLocked & xkbMask; + quint32 depressed = modsDepressed & xkbMask; + // set modifiers in depressed if they don't appear in any of the final masks + depressed |= ~(depressed | latched | locked) & xkbMask; + + const xkb_state_component newState + = xkb_state_update_mask(kb_state, + depressed, + latched, + locked, + 0, + 0, + (state >> 13) & 3); // bits 13 and 14 report the state keyboard group + + if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) { + //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)"); + } +} + void QXcbKeyboard::updateXKBStateFromCore(quint16 state) { if (m_config && !connection()->hasXKB()) { - const quint32 modsDepressed = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED); - const quint32 modsLatched = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); - const quint32 modsLocked = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); - const quint32 xkbMask = xkbModMask(state); - - const quint32 latched = modsLatched & xkbMask; - const quint32 locked = modsLocked & xkbMask; - quint32 depressed = modsDepressed & xkbMask; - // set modifiers in depressed if they don't appear in any of the final masks - depressed |= ~(depressed | latched | locked) & xkbMask; - - const xkb_state_component newState - = xkb_state_update_mask(xkb_state, - depressed, - latched, - locked, - 0, - 0, - (state >> 13) & 3); // bits 13 and 14 report the state keyboard group - - if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) { - //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)"); - } + updateXKBStateFromState(xkb_state, state); } } @@ -1455,7 +1459,16 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, if (type == QEvent::KeyPress) targetWindow->updateNetWmUserTime(time); - xcb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, code); + // Have a temporary keyboard state filled in from state + // this way we allow for synthetic events to have different state + // from the current state i.e. you can have Alt+Ctrl pressed + // and receive a synthetic key event that has neither Alt nor Ctrl pressed + struct xkb_state *kb_state = xkb_state_new(xkb_keymap); + if (!kb_state) + return; + updateXKBStateFromState(kb_state, state); + + xcb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code); QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext(); QMetaMethod method; @@ -1474,11 +1487,13 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, Q_ARG(uint, code), Q_ARG(uint, state), Q_ARG(bool, type == QEvent::KeyPress)); - if (retval) + if (retval) { + xkb_state_unref(kb_state); return; + } } - QString string = lookupString(xkb_state, code); + QString string = lookupString(kb_state, code); // Ιf control modifier is set we should prefer latin character, this is // used for standard shortcuts in checks like "key == QKeySequence::Copy", @@ -1547,6 +1562,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers, code, sym, state, string, isAutoRepeat); } + xkb_state_unref(kb_state); } QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code) const diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index 457a27affb1..dc27511b56e 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -98,6 +98,8 @@ protected: void checkForLatinLayout(); private: + void updateXKBStateFromState(struct xkb_state *kb_state, quint16 state); + bool m_config; xcb_keycode_t m_autorepeat_code; From 29d64bc8e06d6809ac0c68b7b5459a8a51667769 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 15 Sep 2016 17:31:25 +0200 Subject: [PATCH 02/16] QEvdevKeyboardHandler: use RAII in create()/ctor Coverity somewhat rightfully complained that the FD may be leaked in certain cases, e.g. when the new-expression throws. Yes, the plugin is compiled with exceptions disabled, but the code is still a bug waiting to happen, because it's too easy to just add an early return to the function and leak the FD that way. Fix by writing a small RAII class for FDs (can't use QSharedPointer, since it's not a pointer we're dealing with). It's quite generically named, in anticipation that it might come in handy elsewhere, too. Coverity-Id: 89046 Change-Id: I83d1ed3f11219065d2248c129ed191a651f617c7 Reviewed-by: Thiago Macieira --- .../evdevkeyboard/qevdevkeyboardhandler.cpp | 34 ++++++++++--------- .../evdevkeyboard/qevdevkeyboardhandler_p.h | 17 ++++++++-- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp index 089cc130327..3363859dae8 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -52,8 +52,15 @@ Q_LOGGING_CATEGORY(qLcEvdevKeyMap, "qt.qpa.input.keymap") // simple builtin US keymap #include "qevdevkeyboard_defaultmap_p.h" -QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool disableZap, bool enableCompose, const QString &keymapFile) - : m_device(device), m_fd(fd), m_notify(Q_NULLPTR), +void QFdContainer::reset() Q_DECL_NOTHROW +{ + if (m_fd >= 0) + qt_safe_close(m_fd); + m_fd = -1; +} + +QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, QFdContainer &fd, bool disableZap, bool enableCompose, const QString &keymapFile) + : m_device(device), m_fd(fd.release()), m_notify(Q_NULLPTR), m_modifiers(0), m_composing(0), m_dead_unicode(0xffff), m_no_zap(disableZap), m_do_compose(enableCompose), m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0) @@ -68,16 +75,13 @@ QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool unloadKeymap(); // socket notifier for events on the keyboard device - m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + m_notify = new QSocketNotifier(m_fd.get(), QSocketNotifier::Read, this); connect(m_notify, SIGNAL(activated(int)), this, SLOT(readKeycode())); } QEvdevKeyboardHandler::~QEvdevKeyboardHandler() { unloadKeymap(); - - if (m_fd >= 0) - qt_safe_close(m_fd); } QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device, @@ -111,13 +115,12 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device, qCDebug(qLcEvdevKey) << "Opening keyboard at" << device; - int fd; - fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); - if (fd >= 0) { - ::ioctl(fd, EVIOCGRAB, grab); + QFdContainer fd(qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0)); + if (fd.get() >= 0) { + ::ioctl(fd.get(), EVIOCGRAB, grab); if (repeatDelay > 0 && repeatRate > 0) { int kbdrep[2] = { repeatDelay, repeatRate }; - ::ioctl(fd, EVIOCSREP, kbdrep); + ::ioctl(fd.get(), EVIOCSREP, kbdrep); } return new QEvdevKeyboardHandler(device, fd, disableZap, enableCompose, keymapFile); @@ -137,7 +140,7 @@ void QEvdevKeyboardHandler::switchLed(int led, bool state) led_ie.code = led; led_ie.value = state; - qt_safe_write(m_fd, &led_ie, sizeof(led_ie)); + qt_safe_write(m_fd.get(), &led_ie, sizeof(led_ie)); } void QEvdevKeyboardHandler::readKeycode() @@ -146,7 +149,7 @@ void QEvdevKeyboardHandler::readKeycode() int n = 0; forever { - int result = qt_safe_read(m_fd, reinterpret_cast(buffer) + n, sizeof(buffer) - n); + int result = qt_safe_read(m_fd.get(), reinterpret_cast(buffer) + n, sizeof(buffer) - n); if (result == 0) { qWarning("evdevkeyboard: Got EOF from the input device"); @@ -159,8 +162,7 @@ void QEvdevKeyboardHandler::readKeycode() if (errno == ENODEV) { delete m_notify; m_notify = Q_NULLPTR; - qt_safe_close(m_fd); - m_fd = -1; + m_fd.reset(); } return; } @@ -471,7 +473,7 @@ void QEvdevKeyboardHandler::unloadKeymap() //Set locks according to keyboard leds quint16 ledbits[1]; memset(ledbits, 0, sizeof(ledbits)); - if (::ioctl(m_fd, EVIOCGLED(sizeof(ledbits)), ledbits) < 0) { + if (::ioctl(m_fd.get(), EVIOCGLED(sizeof(ledbits)), ledbits) < 0) { qWarning("evdevkeyboard: Failed to query led states"); switchLed(LED_NUML,false); switchLed(LED_CAPSL, false); diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h index 84c251c3c2b..b08f30b6eec 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h @@ -123,12 +123,25 @@ inline QDataStream &operator<<(QDataStream &ds, const QEvdevKeyboardMap::Composi return ds << c.first << c.second << c.result; } +class QFdContainer +{ + int m_fd; + Q_DISABLE_COPY(QFdContainer); +public: + explicit QFdContainer(int fd = -1) Q_DECL_NOTHROW : m_fd(fd) {} + ~QFdContainer() { reset(); } + + int get() const Q_DECL_NOTHROW { return m_fd; } + + int release() Q_DECL_NOTHROW { int result = m_fd; m_fd = -1; return result; } + void reset() Q_DECL_NOTHROW; +}; class QEvdevKeyboardHandler : public QObject { Q_OBJECT public: - QEvdevKeyboardHandler(const QString &device, int fd, bool disableZap, bool enableCompose, const QString &keymapFile); + QEvdevKeyboardHandler(const QString &device, QFdContainer &fd, bool disableZap, bool enableCompose, const QString &keymapFile); ~QEvdevKeyboardHandler(); enum KeycodeAction { @@ -181,7 +194,7 @@ private: void switchLed(int, bool); QString m_device; - int m_fd; + QFdContainer m_fd; QSocketNotifier *m_notify; // keymap handling From 8082c0dc81b50c44a0cf1984cb2c484b007c64a4 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 18 Sep 2016 16:44:19 +0200 Subject: [PATCH 03/16] QBrush: Fix UB (non-virtual dtor) in QBrush::detach() As the d-pointer, QBrush uses a QScopedPointer with a custom deleter that checks for QBrushData::style and casts the QBrushData pointer down to corresponding subclasses before calling delete on them. In QBrush::detach(), however, any of the three brush data classes were held in a QScopedPointer _without_ the custom deleter, invoking UB when that scoped pointer would ever get to be the one that deleted the payload instead of handing it over to the objects d-pointer. Found by making dtors protected following a Coverity report wrongly marked as 'dismissed' (these static checks are not included in this patch, since they are binary-incompatible), to find out where Coverity could possibly see a problem. Also replace the d.reset(x.take()) that allowed this mismatch to compile with d.swap(x), which nicely ensures that x and d are of the same type. Coverity-Id: 11772 Change-Id: I85e2c205df9291bd7508b6c90f7b03fbe8c3bcd2 Reviewed-by: Thiago Macieira --- src/gui/painting/qbrush.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 9e039b7ae44..ee42f2b5111 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -579,7 +579,7 @@ void QBrush::detach(Qt::BrushStyle newStyle) if (newStyle == d->style && d->ref.load() == 1) return; - QScopedPointer x; + QScopedPointer x; switch(newStyle) { case Qt::TexturePattern: { QTexturedBrushData *tbd = new QTexturedBrushData; @@ -595,28 +595,30 @@ void QBrush::detach(Qt::BrushStyle newStyle) } case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: - case Qt::ConicalGradientPattern: - x.reset(new QGradientBrushData); + case Qt::ConicalGradientPattern: { + QGradientBrushData *gbd = new QGradientBrushData; switch (d->style) { case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: case Qt::ConicalGradientPattern: - static_cast(x.data())->gradient = + gbd->gradient = static_cast(d.data())->gradient; break; default: break; } + x.reset(gbd); break; + } default: x.reset(new QBrushData); break; } - x->ref.store(1); + x->ref.store(1); // must be first lest the QBrushDataPointerDeleter turns into a no-op x->style = newStyle; x->color = d->color; x->transform = d->transform; - d.reset(x.take()); + d.swap(x); } From bcbc8120b30a3d94d6a131ad936a8270657ffd96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 25 Aug 2016 13:02:47 +0200 Subject: [PATCH 04/16] multiwindow: Use showNormal() instead of show() to ensure normal geometry Change-Id: Ice607f536a620da5a70f2ba066f4983bb78c6288 Reviewed-by: Simon Hausmann --- tests/manual/qopenglwindow/multiwindow/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/manual/qopenglwindow/multiwindow/main.cpp b/tests/manual/qopenglwindow/multiwindow/main.cpp index caa15078d55..66ebb73c56f 100644 --- a/tests/manual/qopenglwindow/multiwindow/main.cpp +++ b/tests/manual/qopenglwindow/multiwindow/main.cpp @@ -187,7 +187,7 @@ int main(int argc, char **argv) QPoint position = availableGeometry.topLeft(); position += QPoint(col * windowWidth, row * windowHeight); w->setFramePosition(position); - w->show(); + w->showNormal(); } int r = app.exec(); From 6ce96fdbf59138bebadbd8157d8285327a1a3796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 25 Aug 2016 13:09:27 +0200 Subject: [PATCH 05/16] multiwindow: React to mouse press to allow debugging UI responsiveness The animated FPS counter should be enough to observe smooth animations, so we use the color of the window to visualize frame latency. Change-Id: I1171a1c4bdc261ca8655771290c6735357821781 Reviewed-by: Simon Hausmann --- .../manual/qopenglwindow/multiwindow/main.cpp | 53 +++++++------------ 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/tests/manual/qopenglwindow/multiwindow/main.cpp b/tests/manual/qopenglwindow/multiwindow/main.cpp index 66ebb73c56f..31688d717e9 100644 --- a/tests/manual/qopenglwindow/multiwindow/main.cpp +++ b/tests/manual/qopenglwindow/multiwindow/main.cpp @@ -31,14 +31,7 @@ ** ****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include +#include const char applicationDescription[] = "\n\ This application opens multiple windows and continuously schedules updates for\n\ @@ -67,40 +60,26 @@ class Window : public QOpenGLWindow { Q_OBJECT public: - Window(int n) : idx(n) { - r = g = b = fps = 0; - y = 0; + Window(int index) : windowNumber(index + 1), y(0), fps(0) { + + color = QColor::fromHsl((index * 30) % 360, 255, 127).toRgb(); + resize(200, 200); + setObjectName(QString("Window %1").arg(windowNumber)); + connect(this, SIGNAL(frameSwapped()), SLOT(frameSwapped())); fpsTimer.start(); } void paintGL() { QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); - f->glClearColor(r, g, b, 1); + f->glClearColor(color.redF(), color.greenF(), color.blueF(), 1); f->glClear(GL_COLOR_BUFFER_BIT); - switch (idx % 3) { - case 0: - r += 0.005f; - break; - case 1: - g += 0.005f; - break; - case 2: - b += 0.005f; - break; - } - if (r > 1) - r = 0; - if (g > 1) - g = 0; - if (b > 1) - b = 0; QPainter p(this); p.setPen(Qt::white); - p.drawText(QPoint(20, y), QString(QLatin1String("Window %1 (%2 FPS)")).arg(idx).arg(fps)); + p.drawText(QPoint(20, y), QString(QLatin1String("Window %1 (%2 FPS)")).arg(windowNumber).arg(fps)); y += 1; if (y > height() - 20) y = 20; @@ -118,9 +97,17 @@ public slots: } } +protected: + void mousePressEvent(QMouseEvent *event) { + qDebug() << this << event; + color.setHsl((color.hue() + 90) % 360, color.saturation(), color.lightness()); + color = color.toRgb(); + } + private: - int idx; - GLfloat r, g, b; + int windowNumber; + QColor color; + int y; int framesSwapped; @@ -163,7 +150,7 @@ int main(int argc, char **argv) int numberOfWindows = qMax(parser.value(numWindowsOption).toInt(), 1); QList windows; for (int i = 0; i < numberOfWindows; ++i) { - Window *w = new Window(i + 1); + Window *w = new Window(i); windows << w; if (i == 0 && parser.isSet(vsyncOneOption)) { From 44fec65624d3569144e40b394af499172c81a7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 31 Aug 2016 19:42:31 +0200 Subject: [PATCH 06/16] Update swap interval of QCocoaGLContext after creation QSurfaceFormat is recreated from scratch, and by not reading back the swap interval the QCocoaGLContext seemed to be vsynced even if it actually was not. Change-Id: I72ddaae9a4c695fe4c74d7b4b70ca9db84bcc084 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index b77ca071418..4ae81ef3ab9 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -323,6 +323,11 @@ void QCocoaGLContext::updateSurfaceFormat() [pixelFormat release]; + GLint swapInterval = -1; + [m_context getValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; + if (swapInterval >= 0) + m_format.setSwapInterval(swapInterval); + // Restore the original context CGLSetCurrentContext(oldContext); } From 880beb121e76b60cdfbd59d6a04fd600532c72bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 31 Aug 2016 18:21:18 +0200 Subject: [PATCH 07/16] multiwindow: Call update() after swap Change-Id: Ic2c26339bce9fe92b2ccc730c72f53ce94397b78 Reviewed-by: Simon Hausmann --- tests/manual/qopenglwindow/multiwindow/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/manual/qopenglwindow/multiwindow/main.cpp b/tests/manual/qopenglwindow/multiwindow/main.cpp index 31688d717e9..17442dbae54 100644 --- a/tests/manual/qopenglwindow/multiwindow/main.cpp +++ b/tests/manual/qopenglwindow/multiwindow/main.cpp @@ -83,8 +83,6 @@ public: y += 1; if (y > height() - 20) y = 20; - - update(); } public slots: @@ -95,6 +93,8 @@ public slots: framesSwapped = 0; fpsTimer.restart(); } + + update(); } protected: From efdecff085d6e9d8c738bd681757c8cc18a3a451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 31 Aug 2016 18:15:52 +0200 Subject: [PATCH 08/16] multiwindow: Replace per window fps timers with unified approach The FPS is now calculated and output on the command line in a single place. The animated fps counter has been replaced with a vertical line which should make it easier to observe tearing issues when vsync is disabled. Change-Id: Id356fc1958c048d85aba48edfed59124454038d4 Reviewed-by: Simon Hausmann --- .../manual/qopenglwindow/multiwindow/main.cpp | 64 +++++++++++++------ 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/tests/manual/qopenglwindow/multiwindow/main.cpp b/tests/manual/qopenglwindow/multiwindow/main.cpp index 17442dbae54..8b17226366a 100644 --- a/tests/manual/qopenglwindow/multiwindow/main.cpp +++ b/tests/manual/qopenglwindow/multiwindow/main.cpp @@ -60,7 +60,7 @@ class Window : public QOpenGLWindow { Q_OBJECT public: - Window(int index) : windowNumber(index + 1), y(0), fps(0) { + Window(int index) : windowNumber(index + 1), x(0), framesSwapped(0) { color = QColor::fromHsl((index * 30) % 360, 255, 127).toRgb(); @@ -69,7 +69,6 @@ public: setObjectName(QString("Window %1").arg(windowNumber)); connect(this, SIGNAL(frameSwapped()), SLOT(frameSwapped())); - fpsTimer.start(); } void paintGL() { @@ -77,23 +76,14 @@ public: f->glClearColor(color.redF(), color.greenF(), color.blueF(), 1); f->glClear(GL_COLOR_BUFFER_BIT); - QPainter p(this); - p.setPen(Qt::white); - p.drawText(QPoint(20, y), QString(QLatin1String("Window %1 (%2 FPS)")).arg(windowNumber).arg(fps)); - y += 1; - if (y > height() - 20) - y = 20; + QPainter painter(this); + painter.drawLine(x, 0, x, height()); + x = ++x % width(); } public slots: void frameSwapped() { ++framesSwapped; - if (fpsTimer.elapsed() > 1000) { - fps = qRound(framesSwapped * (1000.0 / fpsTimer.elapsed())); - framesSwapped = 0; - fpsTimer.restart(); - } - update(); } @@ -107,14 +97,46 @@ protected: private: int windowNumber; QColor color; - - int y; + int x; int framesSwapped; - QElapsedTimer fpsTimer; - int fps; + friend void printFps(); }; +static const qreal kFpsInterval = 500; + +void printFps() +{ + static QElapsedTimer timer; + if (!timer.isValid()) { + timer.start(); + return; + } + + const qreal frameFactor = (kFpsInterval / timer.elapsed()) * (1000.0 / kFpsInterval); + + QDebug output = qDebug().nospace(); + + qreal averageFps = 0; + const QWindowList windows = QGuiApplication::topLevelWindows(); + for (int i = 0; i < windows.size(); ++i) { + Window *w = qobject_cast(windows.at(i)); + Q_ASSERT(w); + + int fps = qRound(w->framesSwapped * frameFactor); + output << (i + 1) << "=" << fps << ", "; + + averageFps += fps; + w->framesSwapped = 0; + } + averageFps = qRound(averageFps / windows.size()); + qreal msPerFrame = 1000.0 / averageFps; + + output << "avg=" << averageFps << ", ms=" << msPerFrame; + + timer.restart(); +} + int main(int argc, char **argv) { QGuiApplication app(argc, argv); @@ -177,6 +199,12 @@ int main(int argc, char **argv) w->showNormal(); } + QTimer fpsTimer; + fpsTimer.setInterval(kFpsInterval); + fpsTimer.setTimerType(Qt::PreciseTimer); + QObject::connect(&fpsTimer, &QTimer::timeout, &printFps); + fpsTimer.start(); + int r = app.exec(); qDeleteAll(windows); return r; From fecee98836842af1693696c547405af3f740e0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 25 Aug 2016 15:04:54 +0200 Subject: [PATCH 09/16] multiwindow: Base vsync debug output on actual surface format Allows us to detect cases where the requested vsync combination was not possible to fulfill. Change-Id: Ie8f3665129f7a1ab7fcefb94b2298d54520b753a Reviewed-by: Simon Hausmann --- .../manual/qopenglwindow/multiwindow/main.cpp | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tests/manual/qopenglwindow/multiwindow/main.cpp b/tests/manual/qopenglwindow/multiwindow/main.cpp index 8b17226366a..89a94f3b3eb 100644 --- a/tests/manual/qopenglwindow/multiwindow/main.cpp +++ b/tests/manual/qopenglwindow/multiwindow/main.cpp @@ -88,6 +88,18 @@ public slots: } protected: + void exposeEvent(QExposeEvent *event) { + if (!isExposed()) + return; + + QSurfaceFormat format = context()->format(); + qDebug() << this << format.swapBehavior() << "with Vsync =" << (format.swapInterval() ? "ON" : "OFF"); + if (format.swapInterval() != requestedFormat().swapInterval()) + qWarning() << "WARNING: Did not get requested swap interval of" << requestedFormat().swapInterval() << "for" << this; + + QOpenGLWindow::exposeEvent(event); + } + void mousePressEvent(QMouseEvent *event) { qDebug() << this << event; color.setHsl((color.hue() + 90) % 360, color.saturation(), color.lightness()); @@ -158,14 +170,9 @@ int main(int argc, char **argv) parser.process(app); - QSurfaceFormat fmt; - if (parser.isSet(noVsyncOption)) { - qDebug("swap interval 0 (no throttling)"); - fmt.setSwapInterval(0); - } else { - qDebug("swap interval 1 (sync to vblank)"); - } - QSurfaceFormat::setDefaultFormat(fmt); + QSurfaceFormat defaultSurfaceFormat; + defaultSurfaceFormat.setSwapInterval(parser.isSet(noVsyncOption) ? 0 : 1); + QSurfaceFormat::setDefaultFormat(defaultSurfaceFormat); QRect availableGeometry = app.primaryScreen()->availableGeometry(); @@ -176,12 +183,11 @@ int main(int argc, char **argv) windows << w; if (i == 0 && parser.isSet(vsyncOneOption)) { - qDebug("swap interval 1 for first window only"); - QSurfaceFormat vsyncedSurfaceFormat = fmt; + QSurfaceFormat vsyncedSurfaceFormat = defaultSurfaceFormat; vsyncedSurfaceFormat.setSwapInterval(1); w->setFormat(vsyncedSurfaceFormat); - fmt.setSwapInterval(0); - QSurfaceFormat::setDefaultFormat(fmt); + defaultSurfaceFormat.setSwapInterval(0); + QSurfaceFormat::setDefaultFormat(defaultSurfaceFormat); } static int windowWidth = w->width() + 20; From e30d0e462f32d787a9d72acfef7026fb5019bb75 Mon Sep 17 00:00:00 2001 From: Frederik Schwarzer Date: Wed, 17 Aug 2016 13:27:03 +0200 Subject: [PATCH 10/16] QAbstractProxyModel: fix sentence structure in apidoc Change-Id: Ib3371549ecb80da326260b1df431f20e7a04f07e Reviewed-by: Giuseppe D'Angelo --- src/corelib/itemmodels/qabstractproxymodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp index dbbbbb8ff47..c33b0a56b8c 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.cpp +++ b/src/corelib/itemmodels/qabstractproxymodel.cpp @@ -77,7 +77,7 @@ QT_BEGIN_NAMESPACE /*! \property QAbstractProxyModel::sourceModel - \brief the source model this proxy model. + \brief the source model of this proxy model. */ //detects the deletion of the source model From d3389a6d460a7d51a9672247366c60504f427b29 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 6 Sep 2016 14:36:20 +0200 Subject: [PATCH 11/16] iOS: let quiview conform to API signature changes in iOS 10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the iOS 10 SDK, method signatures has been annotated with NS_ASSUME_NONNULL macros and 'nullable' keywords. This means that certain methods should not be called with argumens that can be null, or in this case, set to 0 explicitly. The result will be compiler warnings. This patch will rewrite the explicit call we do to touchesCancelled so that we send an empty set instead of 0. Change-Id: I50aa80b91312397d17e0e380815adff87cee852b Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qioswindow.mm | 2 +- src/plugins/platforms/ios/quiview.mm | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index a1576eba8ef..68afed20341 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -85,7 +85,7 @@ QIOSWindow::~QIOSWindow() // practice this doesn't seem to happen when removing the view from its superview. To ensure that // Qt's internal state for touch and mouse handling is kept consistent, we therefor have to force // cancellation of all touch events. - [m_view touchesCancelled:0 withEvent:0]; + [m_view touchesCancelled:[NSSet set] withEvent:0]; clearAccessibleCache(); m_view->m_qioswindow = 0; diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 4dd43be465f..dce30988461 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -417,7 +417,8 @@ // We do this by assuming that there are no cases where a // sub-set of the active touch events are intentionally cancelled. - if (touches && (static_cast([touches count]) != m_activeTouches.count())) + NSInteger count = static_cast([touches count]); + if (count != 0 && count != m_activeTouches.count()) qWarning("Subset of active touches cancelled by UIKit"); m_activeTouches.clear(); From e32ecdb28079a60f86aca0eee648c11f7993b460 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 6 Sep 2016 11:00:21 +0200 Subject: [PATCH 12/16] iOS: explicit synthesize properties as readwrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The synthesized properties were defined as (read only) methods in the UIViewController API in iOS9, and we extended them into readwrite properties in our own sub class to enable some local bookkeeping in addition to normal overriding. But in iOS10, Apple has changed the methods into being readonly properties instead. The difference then is that automatic property synthesizing will ignore our local readwrite declarations, and use the declarations in the super class instead. And this will lead to a runtime crash on iOS10 since no setter methods are generated. This patch will instead explicit synthesize the affected properties to ensure that both getters and setters will be generated. Change-Id: Iac330e991b8a0fe335e383e1f7d9ff30c0ce1559 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosviewcontroller.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index ed76161b876..a4460a6737f 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -222,6 +222,10 @@ @implementation QIOSViewController +@synthesize prefersStatusBarHidden; +@synthesize preferredStatusBarUpdateAnimation; +@synthesize preferredStatusBarStyle; + - (id)initWithQIOSScreen:(QIOSScreen *)screen { if (self = [self init]) { From 8347b54b9738e29807c3c7913bda8fe7cf3f7dba Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 21 Jun 2016 13:19:02 +0200 Subject: [PATCH 13/16] iOS: open menu on popup regardless of visibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It should be possible to show a menu by calling showPopup, even if visible is set to false. After all, it's only logical that visibility is false before showing it. And whether or not the menu is enabled should not matter as well. Change-Id: I9a2b453c8c6e88c47812c652d99e4b4a9c7524a7 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosmenu.mm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index 612f8c43a27..3e97b1161c7 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -344,7 +344,7 @@ QIOSMenu::QIOSMenu() : QPlatformMenu() , m_tag(0) , m_enabled(true) - , m_visible(true) + , m_visible(false) , m_text(QString()) , m_menuType(DefaultMenu) , m_effectiveMenuType(DefaultMenu) @@ -437,7 +437,7 @@ void QIOSMenu::handleItemSelected(QIOSMenuItem *menuItem) void QIOSMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) { - if (m_currentMenu == this || !m_visible || !m_enabled || !parentWindow) + if (m_currentMenu == this || !parentWindow) return; emit aboutToShow(); @@ -464,6 +464,8 @@ void QIOSMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, c toggleShowUsingUIPickerView(true); break; } + + m_visible = true; } void QIOSMenu::dismiss() @@ -485,6 +487,7 @@ void QIOSMenu::dismiss() } m_currentMenu = 0; + m_visible = false; } void QIOSMenu::toggleShowUsingUIMenuController(bool show) From 9f2c260f881b384ae719c60ea9833feb42251058 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Sun, 27 Sep 2015 01:26:28 +0200 Subject: [PATCH 14/16] Add missing test for QReguarExpression for QTextDocument::findMultiple Change-Id: Ia9b3eb21a178da4ae2844dba37b7e1cc669d6b50 Reviewed-by: Simon Hausmann --- .../text/qtextdocument/tst_qtextdocument.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp index bb20d99e307..3c9de9d211c 100644 --- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp +++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp @@ -468,6 +468,24 @@ void tst_QTextDocument::findMultiple() cursor = doc->find(expr, cursor); QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar")); QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); + + QRegularExpression regularExpression("bar"); + + cursor.movePosition(QTextCursor::End); + cursor = doc->find(regularExpression, cursor, QTextDocument::FindBackward); + QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar")); + QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); + cursor = doc->find(regularExpression, cursor, QTextDocument::FindBackward); + QCOMPARE(cursor.selectionStart(), text.indexOf("bar")); + QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); + + cursor.movePosition(QTextCursor::Start); + cursor = doc->find(regularExpression, cursor); + QCOMPARE(cursor.selectionStart(), text.indexOf("bar")); + QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); + cursor = doc->find(regularExpression, cursor); + QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar")); + QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); } void tst_QTextDocument::basicIsModifiedChecks() From 23e76a12b9419e1b213cbacf625d3a0b1921dd92 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Sun, 28 Aug 2016 17:33:35 +0200 Subject: [PATCH 15/16] Doc: add macOS example of QAbstractNativeEventFilter implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a sample native event filter that can be easily integrated in a project. Task-number: QTBUG-53209 Change-Id: Iedf6df33a3de5b01dc7871cca5e7897a5b485733 Reviewed-by: Topi Reiniö --- ...orelib_kernel_qabstractnativeeventfilter.h | 49 ++++++++++++++++ ...relib_kernel_qabstractnativeeventfilter.mm | 57 +++++++++++++++++++ ...elib_kernel_qabstractnativeeventfilter.pro | 5 ++ .../kernel/qabstractnativeeventfilter.cpp | 15 ++++- 4 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h create mode 100644 src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.mm create mode 100644 src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.pro diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h new file mode 100644 index 00000000000..6666bc56c5b --- /dev/null +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Samuel Gaist +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +#include + +class MyCocoaEventFilter : public QAbstractNativeEventFilter +{ +public: + bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE; +}; +//! [0] diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.mm b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.mm new file mode 100644 index 00000000000..8abd5762596 --- /dev/null +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.mm @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Samuel Gaist +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +#include "mycocoaeventfilter.h" + +#import + +bool CocoaNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *) +{ + if (eventType == "mac_generic_NSEvent") { + NSEvent *event = static_cast(message); + if ([event type] == NSKeyDown) { + // Handle key event + qDebug() << QString::fromNSString([event characters]); + } + } + return false; +} +//! [0] diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.pro b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.pro new file mode 100644 index 00000000000..8f447be5141 --- /dev/null +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractnativeeventfilter.pro @@ -0,0 +1,5 @@ +#! [0] +HEADERS += mycocoaeventfilter.h +OBJECTIVE_SOURCES += mycocoaeventfilter.mm +LIBS += -framework AppKit +#! [0] diff --git a/src/corelib/kernel/qabstractnativeeventfilter.cpp b/src/corelib/kernel/qabstractnativeeventfilter.cpp index 9892cc7333f..15e6d17c18c 100644 --- a/src/corelib/kernel/qabstractnativeeventfilter.cpp +++ b/src/corelib/kernel/qabstractnativeeventfilter.cpp @@ -90,7 +90,7 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter() In both cases, the \a message can be casted to a MSG pointer. The \a result pointer is only used on Windows, and corresponds to the LRESULT pointer. - On Mac, \a eventType is set to "mac_generic_NSEvent", and the \a message can be casted to an EventRef. + On macOS, \a eventType is set to "mac_generic_NSEvent", and the \a message can be casted to an NSEvent pointer. On Blackberry (not plain QNX) \a eventType is set to "bps_event_t", and the \a message can be casted to a bps_event_t pointer. @@ -99,8 +99,19 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter() the \a message out, i.e. stop it being handled further, return true; otherwise return false. - Example: + \b {Linux example} \snippet code/src_corelib_kernel_qabstractnativeeventfilter.cpp 0 + + \b {macOS example} + + mycocoaeventfilter.h: + \snippet code/src_corelib_kernel_qabstractnativeeventfilter.h 0 + + mycocoaeventfilter.mm: + \snippet code/src_corelib_kernel_qabstractnativeeventfilter.mm 0 + + myapp.pro: + \snippet code/src_corelib_kernel_qabstractnativeeventfilter.pro 0 */ QT_END_NAMESPACE From 25e9bde2d665866f7a9a40d1ed3aa8fabcf2ac2f Mon Sep 17 00:00:00 2001 From: Takumi ASAKI Date: Thu, 14 Jul 2016 14:47:05 +0900 Subject: [PATCH 16/16] Bearer/ConnMan: Fix getTechnologies() is not called Change-Id: I4e39c971198583af815f5bcecaad4a9c52e5d2dd Reviewed-by: Lorn Potter --- src/plugins/bearer/connman/qconnmanservice_linux.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/bearer/connman/qconnmanservice_linux.cpp b/src/plugins/bearer/connman/qconnmanservice_linux.cpp index 40bab4fda6d..64c416a81d3 100644 --- a/src/plugins/bearer/connman/qconnmanservice_linux.cpp +++ b/src/plugins/bearer/connman/qconnmanservice_linux.cpp @@ -246,6 +246,8 @@ QStringList QConnmanManagerInterface::getServices() bool QConnmanManagerInterface::requestScan(const QString &type) { bool scanned = false; + if (technologiesMap.isEmpty()) + getTechnologies(); Q_FOREACH (QConnmanTechnologyInterface *tech, technologiesMap) { if (tech->type() == type) { tech->scan();