From 8fcab70408628f730860d3861a06fc519d069f5e Mon Sep 17 00:00:00 2001 From: Jian Liang Date: Sat, 14 Dec 2013 10:59:35 +0800 Subject: [PATCH 01/24] Avoid crash due to accessing deleted QWidgetWindow object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change childWidget->windowHandle() to childWidget->internalWinId() in q_createNativeChildrenAndSetParent() to determine whether should we call childWidget->winId(). This is because in some circumstances Qt will crash due to accessing deleted QWidgetWindow object if we use windowHandle(). Think about the following scenario: 1) create a widget A without parent and add two child widgets B and C to A 2) create a native widget D as the child of B, note that when we set Qt::WA_NativeWindow attribute to it, its QWidgetWindow will be created which means its windowHandle() is not null. 3) create a top level widget E as the child of C and show it. This will make Qt call createWinId() to A and then q_createNativeChildrenAndSetParent() will be called to create A's native children recursively and finally make D's QWidgetWindow object become a child of A's QWidgetWindow object. Please note here that B will not become a native widget just because at that moment windowHandle() of D is not null and Qt will not call winId() to its parent B 4) Set A's parent to another widget which has been shown, setParent_sys() will be called to A and then Qt will call destroy() to A. in destroy() Qt will try to call destroy() to its children recursively with a condition that the child has Qt::WA_NativeWindow been set. But D's parent B is not a native widget right now so B and D is not destroyed. Qt will then deleted the QWidgetWindow object of A, since E's QWidgetWindow object is a child of A's QWidgetWindow object, it will also be deleted. Now E hold a deleted pointer of QWidgetWindow object. This is the source of crash later. Task-number: QTBUG-35600 Change-Id: I97a20a68e626ee62b15bb4eae580e26f8948923b Reviewed-by: Friedemann Kleint Reviewed-by: Jørgen Lind --- src/widgets/kernel/qwidget_qpa.cpp | 2 +- .../qwidget_window/tst_qwidget_window.cpp | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 3b6127e4e7..3281e0c6f7 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -70,7 +70,7 @@ void q_createNativeChildrenAndSetParent(const QWidget *parentWidget) const QWidget *childWidget = qobject_cast(children.at(i)); if (childWidget) { // should not be necessary if (childWidget->testAttribute(Qt::WA_NativeWindow)) { - if (!childWidget->windowHandle()) + if (!childWidget->internalWinId()) childWidget->winId(); if (childWidget->windowHandle()) { QWindow *parentWindow = childWidget->nativeParentWidget()->windowHandle(); diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 1bbbfd610e..d6b7fc20ed 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -94,6 +94,8 @@ private slots: #ifndef QT_NO_DRAGANDDROP void tst_dnd(); #endif + + void tst_qtbug35600(); }; void tst_QWidget_window::initTestCase() @@ -568,5 +570,33 @@ void tst_QWidget_window::tst_dnd() } #endif +void tst_QWidget_window::tst_qtbug35600() +{ + QWidget w; + w.show(); + + QWidget *wA = new QWidget; + QHBoxLayout *layoutA = new QHBoxLayout; + + QWidget *wB = new QWidget; + layoutA->addWidget(wB); + + QWidget *wC = new QWidget; + layoutA->addWidget(wC); + + wA->setLayout(layoutA); + + QWidget *wD = new QWidget; + wD->setAttribute(Qt::WA_NativeWindow); + wD->setParent(wB); + + QWidget *wE = new QWidget(wC, Qt::Tool | Qt::FramelessWindowHint | Qt::WindowTransparentForInput); + wE->show(); + + wA->setParent(&w); + + // QTBUG-35600: program may crash here or on exit +} + QTEST_MAIN(tst_QWidget_window) #include "tst_qwidget_window.moc" From 48ecb2d434d68abc39645b261cc9c1b0551a703e Mon Sep 17 00:00:00 2001 From: Kurt Pattyn Date: Thu, 26 Dec 2013 16:15:26 +0100 Subject: [PATCH 02/24] =?UTF-8?q?Fix=20=E2=80=98looses=20precision?= =?UTF-8?q?=E2=80=99=20warning=20in=20public=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I935e6f278e539f8e6aaca0bc381371ec85aa5c67 Reviewed-by: Olivier Goffart --- src/corelib/kernel/qmetatype.h | 6 +++--- src/corelib/tools/qlist.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 745487627e..83801a20c5 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -876,7 +876,7 @@ struct CapabilitiesImpl template struct ContainerAPI : CapabilitiesImpl { - static int size(const T *t) { return std::distance(t->begin(), t->end()); } + static int size(const T *t) { return int(std::distance(t->begin(), t->end())); } }; template @@ -1102,8 +1102,8 @@ public: template static int sizeImpl(const void *p) - { return std::distance(static_cast(p)->begin(), - static_cast(p)->end()); } + { return int(std::distance(static_cast(p)->begin(), + static_cast(p)->end())); } template static void findImpl(const void *container, const void *p, void **iterator) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 333ce72849..16f058b001 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -262,7 +262,7 @@ public: inline const_iterator &operator-=(int j) { i-=j; return *this; } inline const_iterator operator+(int j) const { return const_iterator(i+j); } inline const_iterator operator-(int j) const { return const_iterator(i-j); } - inline int operator-(const_iterator j) const { return i - j.i; } + inline int operator-(const_iterator j) const { return int(i - j.i); } }; friend class const_iterator; From 5ee3d1e45621da51faaab08cf13d16f22b314309 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 Dec 2013 14:18:03 -0800 Subject: [PATCH 03/24] XCB: Don't recalculate the DPI if we have a forced DPI setting logicalDpi() already has the logic to check m_forcedDpi, so let's reuse it. I hope it's not a problem that we send a signal that it changed when nothing changed. [ChangeLog][Platform Specific Changes][X11 / XCB]Fixed a bug that caused Qt applications to think the screen DPI had changed when it had not, after connecting or disconnecting monitors. Task-number: QTBUG-32683 Change-Id: I45dd27de5109e65e7599915f11cfdb633a65a67c Reviewed-by: Robin Burchell Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbscreen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 5fcaf18aef..b1ef3182ba 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -373,9 +373,9 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry()); QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry()); QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation); - QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), - Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width(), - Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height()); + + QDpi ldpi = logicalDpi(); + QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second); } void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) From ecf11d62fc6f57cccf6f3326e768b1c7cabbd0b3 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 23 Dec 2013 10:17:06 +0100 Subject: [PATCH 04/24] xcb: added env variables to show input devices and events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit export QT_XCB_DEBUG_XINPUT_DEVICES=anything to show detected input devices at startup export QT_XCB_DEBUG_XINPUT=anything to log mouse, touch and tablet events Change-Id: Id14844b68ad376740f82a36aab2c59c84d2017ab Task-number: QTBUG-35583 Reviewed-by: Jørgen Lind --- src/plugins/platforms/xcb/qxcbconnection.cpp | 10 +++ src/plugins/platforms/xcb/qxcbconnection.h | 2 + .../platforms/xcb/qxcbconnection_xi2.cpp | 89 +++++++++---------- 3 files changed, 56 insertions(+), 45 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index c00b4d551b..4f42bb1785 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -262,6 +262,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , has_input_shape(false) , has_touch_without_mouse_emulation(false) , has_xkb(false) + , debug_xinput_devices(false) + , debug_xinput(false) , m_buttons(0) , m_focusWindow(0) , m_systemTrayTracker(0) @@ -749,6 +751,8 @@ void QXcbConnection::handleButtonPress(xcb_generic_event_t *ev) // the rest we need to manage ourselves m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); m_buttons |= translateMouseButton(event->detail); + if (Q_UNLIKELY(debug_xinput)) + qDebug("xcb: pressed mouse button %d, button state %X", event->detail, static_cast(m_buttons)); } void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev) @@ -759,6 +763,8 @@ void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev) // the rest we need to manage ourselves m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); m_buttons &= ~translateMouseButton(event->detail); + if (Q_UNLIKELY(debug_xinput)) + qDebug("xcb: released mouse button %d, button state %X", event->detail, static_cast(m_buttons)); } #ifndef QT_NO_XKB @@ -814,6 +820,10 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) handleButtonRelease(event); HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); case XCB_MOTION_NOTIFY: + if (Q_UNLIKELY(debug_xinput)) { + xcb_motion_notify_event_t *mev = (xcb_motion_notify_event_t *)event; + qDebug("xcb: moved mouse to %4d, %4d; button state %X", mev->event_x, mev->event_y, static_cast(m_buttons)); + } #ifdef QT_NO_XKB m_keyboard->updateXKBStateFromCore(((xcb_motion_notify_event_t *)event)->state); #endif diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index ff7a6dd606..ba056a8006 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -574,6 +574,8 @@ private: bool has_input_shape; bool has_touch_without_mouse_emulation; bool has_xkb; + bool debug_xinput_devices; + bool debug_xinput; Qt::MouseButtons m_buttons; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index b144d953a7..6869baad95 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -44,10 +44,7 @@ #include "qxcbwindow.h" #include "qtouchdevice.h" #include -//#define XI2_DEBUG -#ifdef XI2_DEBUG #include -#endif #ifdef XCB_USE_XINPUT2 @@ -73,6 +70,8 @@ struct XInput2DeviceData { void QXcbConnection::initializeXInput2() { + debug_xinput = qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT"); + debug_xinput_devices = qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT_DEVICES"); #ifndef QT_NO_TABLETEVENT m_tabletData.clear(); #endif @@ -87,8 +86,11 @@ void QXcbConnection::initializeXInput2() m_xi2Enabled = true; } if (m_xi2Enabled) { -#ifdef XI2_DEBUG - qDebug("XInput version %d.%d is supported", xiMajor, m_xi2Minor); + if (Q_UNLIKELY(debug_xinput_devices)) +#ifdef XCB_USE_XINPUT22 + qDebug("XInput version %d.%d is available and Qt supports 2.2 or greater", xiMajor, m_xi2Minor); +#else + qDebug("XInput version %d.%d is available and Qt supports 2.0", xiMajor, m_xi2Minor); #endif int deviceCount = 0; XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount); @@ -96,9 +98,8 @@ void QXcbConnection::initializeXInput2() // Only non-master pointing devices are relevant here. if (devices[i].use != XISlavePointer) continue; -#ifdef XI2_DEBUG - qDebug() << "input device "<< devices[i].name; -#endif + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << "input device "<< devices[i].name; #ifndef QT_NO_TABLETEVENT TabletData tabletData; #endif @@ -107,9 +108,8 @@ void QXcbConnection::initializeXInput2() case XIValuatorClass: { XIValuatorClassInfo *vci = reinterpret_cast(devices[i].classes[c]); const int valuatorAtom = qatom(vci->label); -#ifdef XI2_DEBUG - qDebug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms); -#endif + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms); #ifndef QT_NO_TABLETEVENT if (valuatorAtom < QXcbAtom::NAtoms) { TabletData::ValuatorClassInfo info; @@ -136,26 +136,23 @@ void QXcbConnection::initializeXInput2() tabletData.pointerType = QTabletEvent::Eraser; m_tabletData.append(tabletData); isTablet = true; -#ifdef XI2_DEBUG - qDebug() << " it's a tablet with pointer type" << tabletData.pointerType; -#endif + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug() << " it's a tablet with pointer type" << tabletData.pointerType; } #endif // QT_NO_TABLETEVENT if (!isTablet) { XInput2DeviceData *dev = deviceForId(devices[i].deviceid); -#ifdef XI2_DEBUG - if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchScreen) - qDebug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d", - dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), - dev->qtTouchDevice->maximumTouchPoints()); - else if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchPad) - qDebug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", - dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), - dev->qtTouchDevice->maximumTouchPoints(), - dev->size.width(), dev->size.height()); -#else - Q_UNUSED(dev); -#endif // XI2_DEBUG + if (Q_UNLIKELY(debug_xinput_devices)) { + if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchScreen) + qDebug(" it's a touchscreen with type %d capabilities 0x%X max touch points %d", + dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), + dev->qtTouchDevice->maximumTouchPoints()); + else if (dev && dev->qtTouchDevice->type() == QTouchDevice::TouchPad) + qDebug(" it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f", + dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(), + dev->qtTouchDevice->maximumTouchPoints(), + dev->size.width(), dev->size.height()); + } } } XIFreeDeviceInfo(devices); @@ -236,9 +233,8 @@ XInput2DeviceData *QXcbConnection::deviceForId(int id) case XITouchClass: { XITouchClassInfo *tci = reinterpret_cast(classinfo); maxTouchPoints = tci->num_touches; -#ifdef XI2_DEBUG - qDebug(" has touch class with mode %d", tci->mode); -#endif + if (Q_UNLIKELY(debug_xinput_devices)) + qDebug(" has touch class with mode %d", tci->mode); switch (tci->mode) { case XIModeRelative: type = QTouchDevice::TouchPad; @@ -324,13 +320,11 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) #ifdef XCB_USE_XINPUT22 if (xiEvent->evtype == XI_TouchBegin || xiEvent->evtype == XI_TouchUpdate || xiEvent->evtype == XI_TouchEnd) { xXIDeviceEvent* xiDeviceEvent = reinterpret_cast(event); -#ifdef XI2_DEBUG - qDebug("XI2 event type %d seq %d detail %d pos 0x%X,0x%X %f,%f root pos %f,%f", - event->event_type, xiEvent->sequenceNumber, xiDeviceEvent->detail, - xiDeviceEvent->event_x, xiDeviceEvent->event_y, - fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), - fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y) ); -#endif + if (Q_UNLIKELY(debug_xinput)) + qDebug("XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f", + event->event_type, xiEvent->sequenceNumber, xiDeviceEvent->detail, + fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), + fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y) ); if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) { XInput2DeviceData *dev = deviceForId(xiEvent->deviceid); @@ -356,10 +350,9 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) double value; if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value)) continue; -#ifdef XI2_DEBUG - qDebug(" valuator %20s value %lf from range %lf -> %lf", - atomName(vci->label).constData(), value, vci->min, vci->max ); -#endif + if (Q_UNLIKELY(debug_xinput)) + qDebug(" valuator %20s value %lf from range %lf -> %lf", + atomName(vci->label).constData(), value, vci->min, vci->max ); if (vci->label == atom(QXcbAtom::RelX)) { nx = valuatorNormalized(value, vci); } else if (vci->label == atom(QXcbAtom::RelY)) { @@ -435,10 +428,9 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) touchPoint.area = QRectF(x - w/2, y - h/2, w, h); touchPoint.normalPosition = QPointF(nx, ny); -#ifdef XI2_DEBUG - qDebug() << " tp " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition << - " area " << touchPoint.area << " pressure " << touchPoint.pressure; -#endif + if (Q_UNLIKELY(debug_xinput)) + qDebug() << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition << + " area " << touchPoint.area << " pressure " << touchPoint.pressure; QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiEvent->time, dev->qtTouchDevice, m_touchPoints.values()); if (touchPoint.state == Qt::TouchPointReleased) // If a touchpoint was released, we can forget it, because the ID won't be reused. @@ -560,6 +552,13 @@ void QXcbConnection::xi2ReportTabletEvent(const TabletData &tabletData, void *ev } } + if (Q_UNLIKELY(debug_xinput)) + qDebug("XI2 tablet event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f pressure %4.2lf tilt %d, %d rotation %6.2lf", + ev->type, ev->sequenceNumber, ev->detail, + fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), + fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), + pressure, xTilt, yTilt, rotation); + QWindowSystemInterface::handleTabletEvent(window, tabletData.down, local, global, QTabletEvent::Stylus, tabletData.pointerType, pressure, xTilt, yTilt, 0, From fe4ebf12696a8e438fa6609552774d1becb14c25 Mon Sep 17 00:00:00 2001 From: Christoph Cullmann Date: Mon, 23 Dec 2013 16:24:10 +0100 Subject: [PATCH 05/24] fix compile of qt without egl available move the dpy to the place where it is used inside the egl ifdef guard fixes compilation on old distros not having egl Change-Id: I7eebe5305f3a584c0c5da2ea7b9099fdd994249d Reviewed-by: David Faure --- src/plugins/platforms/xcb/qxcbconnection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 4f42bb1785..24734a8240 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -278,7 +278,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra m_xlib_display = dpy; } #else - EGLNativeDisplayType dpy = EGL_DEFAULT_DISPLAY; m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreen); #endif //XCB_USE_XLIB @@ -286,6 +285,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra qFatal("QXcbConnection: Could not connect to display %s", m_displayName.constData()); #ifdef XCB_USE_EGL + EGLNativeDisplayType dpy = EGL_DEFAULT_DISPLAY; EGLDisplay eglDisplay = eglGetDisplay(dpy); m_egl_display = eglDisplay; EGLint major, minor; From d9b7d60df02178c640fb0a5c609cedad95c5c009 Mon Sep 17 00:00:00 2001 From: Sze Howe Koh Date: Sun, 29 Dec 2013 08:45:45 +0800 Subject: [PATCH 06/24] Doc: Polish Qt::ConnectionType descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Shorten Qt::AutoConnection description, rearrange to match the order of the subsequent rows. - Note the thread used in Qt::DirectConnection - "Emitter's thread" is ambiguous -- a signal is not necessarily emitted from the thread that the emitter lives in. - Misusing Qt::BlockingQueuedConnection WILL (not "can") cause a deadlock. Qt even issues an error message before it freezes. - Remove the \note command -- it breaks the table and displays the note in a new paragraph. Change-Id: Ib60cb665e0cd23e1e072402ec5d8be344b8454f7 Reviewed-by: Olivier Goffart Reviewed-by: Topi Reiniö Reviewed-by: Giuseppe D'Angelo --- src/corelib/global/qnamespace.qdoc | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 90f38fd51c..ae377e124b 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -509,15 +509,14 @@ delivery at a later time. \value AutoConnection - (default) If the signal is emitted from a different thread than the - receiving object, the signal is queued, behaving as - Qt::QueuedConnection. Otherwise, the slot is invoked directly, - behaving as Qt::DirectConnection. The type of connection is + \b (Default) If the receiver \l{QObject#Thread Affinity}{lives in} the + thread that emits the signal, Qt::DirectConnection is used. Otherwise, + Qt::QueuedConnection is used. The connection type is determined when the signal is emitted. \value DirectConnection - The slot is invoked immediately, when the signal is - emitted. + The slot is invoked immediately when the signal is + emitted. The slot is executed in the signalling thread. \value QueuedConnection The slot is invoked when control returns to the event loop @@ -525,11 +524,10 @@ receiver's thread. \value BlockingQueuedConnection - Same as QueuedConnection, except the current thread blocks - until the slot returns. This connection type should only be - used where the emitter and receiver are in different - threads. \note Violating this rule can cause your - application to deadlock. + Same as Qt::QueuedConnection, except that the signalling thread blocks + until the slot returns. This connection must \e not be used if the + receiver lives in the signalling thread, or else the application + will deadlock. \value UniqueConnection This is a flag that can be combined with any one of the above From 0336202749257d48b5356b92a724e0451e2c16c7 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Fri, 20 Dec 2013 15:14:31 +0000 Subject: [PATCH 07/24] Add mtdev configure test Change-Id: If989b479ed4babf902099c54be59ae73512820d5 Reviewed-by: Laszlo Agocs --- config.tests/unix/mtdev/mtdev.c | 49 +++++++++++++++++++++++++++++++ config.tests/unix/mtdev/mtdev.pro | 6 ++++ configure | 24 +++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 config.tests/unix/mtdev/mtdev.c create mode 100644 config.tests/unix/mtdev/mtdev.pro diff --git a/config.tests/unix/mtdev/mtdev.c b/config.tests/unix/mtdev/mtdev.c new file mode 100644 index 0000000000..f2e38145d8 --- /dev/null +++ b/config.tests/unix/mtdev/mtdev.c @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd, author: +** Contact: http://www.qt-project.org/legal +** +** This file is part of the config.tests 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 + +int main(int, char **) +{ + mtdev m; + mtdev_open(&m, 0); + return 0; +} diff --git a/config.tests/unix/mtdev/mtdev.pro b/config.tests/unix/mtdev/mtdev.pro new file mode 100644 index 0000000000..4555bf416c --- /dev/null +++ b/config.tests/unix/mtdev/mtdev.pro @@ -0,0 +1,6 @@ +SOURCES = mtdev.c + +CONFIG += link_pkgconfig +PKGCONFIG_PRIVATE += mtdev + +CONFIG -= qt diff --git a/configure b/configure index 28316c47dc..dad9fdd907 100755 --- a/configure +++ b/configure @@ -595,6 +595,7 @@ CFG_XVIDEO=auto CFG_XINERAMA=runtime CFG_XFIXES=runtime CFG_ZLIB=auto +CFG_MTDEV=auto CFG_SQLITE=qt CFG_GIF=auto CFG_PNG=yes @@ -1588,6 +1589,13 @@ while [ "$#" -gt 0 ]; do # No longer supported: #[ "$VAL" = "no" ] && CFG_LIBPNG=no ;; + mtdev) + if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then + CFG_MTDEV="$VAL" + else + UNKNOWN_OPT=yes + fi + ;; sqlite) if [ "$VAL" = "system" ]; then CFG_SQLITE=system @@ -2296,6 +2304,9 @@ Third Party Libraries: + -system-zlib ....... Use zlib from the operating system. See http://www.gzip.org/zlib + -no-mtdev ......... Do not compile mtdev support. + + -mtdev ............. Enable mtdev support. + -no-gif ............ Do not compile GIF reading support. -no-libpng ......... Do not compile PNG support. @@ -4396,6 +4407,17 @@ if [ "$CFG_ZLIB" = "auto" ]; then fi fi +if [ "$CFG_MTDEV" != "no" ]; then + if compileTest unix/mtdev "mtdev"; then + CFG_MTDEV=yes + else + CFG_MTDEV=no + fi +fi +if [ "$CFG_MTDEV" = "no" ]; then + QMakeVar add DEFINES QT_NO_MTDEV +fi + if [ "$CFG_LARGEFILE" = "auto" ]; then #Large files should be enabled for all Linux systems CFG_LARGEFILE=yes @@ -5857,6 +5879,7 @@ elif [ "$CFG_ZLIB" = "system" ]; then QT_CONFIG="$QT_CONFIG system-zlib" fi +[ "$CFG_MTDEV" = "yes" ] && QT_CONFIG="$QT_CONFIG mtdev" [ "$CFG_NIS" = "yes" ] && QT_CONFIG="$QT_CONFIG nis" [ "$CFG_CUPS" = "yes" ] && QT_CONFIG="$QT_CONFIG cups" [ "$CFG_ICONV" = "yes" ] && QT_CONFIG="$QT_CONFIG iconv" @@ -6753,6 +6776,7 @@ report_support " TDS .................." "$CFG_SQL_tds" plugin "plugin" yes " report_support " udev ..................." "$CFG_LIBUDEV" report_support " xkbcommon .............." "$CFG_XKBCOMMON" system "system library" qt "bundled copy" report_support " zlib ..................." "$CFG_ZLIB" system "system library" yes "bundled copy" +report_support " mtdev .................." "$CFG_MTDEV" yes "system library" echo From e8d31d1b315c40ef0906579b429bc04279a1686d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sun, 29 Dec 2013 19:53:24 +0100 Subject: [PATCH 08/24] linuxfb: Make mouse cursor behavior match eglfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On non-Android systems hideCursor should default to false, just like it is done in eglfs. This is especially useful on udev-less systems where currently one has to resort to setting QT_QPA_FB_HIDECURSOR to "0" to enable the mouse cursor. This is not ideal. Defaulting to showing the cursor unless disabled by the environment variable or, in absence of that, the lack of a mouse reported by udev is a better choice. Change-Id: I7362ac47046179d5eb8ed8b44cf2c36c0fc23432 Reviewed-by: Jørgen Lind --- src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp index 4f9284da7f..735a43daf7 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp @@ -400,7 +400,11 @@ bool QLinuxFbScreen::initialize() mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat); QByteArray hideCursorVal = qgetenv("QT_QPA_FB_HIDECURSOR"); +#if !defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK) + bool hideCursor = false; +#else bool hideCursor = true; // default to true to prevent the cursor showing up with the subclass on Android +#endif if (hideCursorVal.isEmpty()) { #if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) QScopedPointer dis(QDeviceDiscovery::create(QDeviceDiscovery::Device_Mouse)); From 5923196bc3fbed67beb637fd36e1bdf2d6780e36 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Fri, 20 Dec 2013 15:14:42 +0000 Subject: [PATCH 09/24] mtdev: Change to use configure detection instead of requiring source hacking. This coincidentally fixes a case of accidental BIC in qevdevtouch_p.h, where not all users would necessarily define USE_MTDEV: having it centralized inside Qt makes this now, blessedly, impossible. Change-Id: I196a8f21742830705759aa917a823afdc94ba2b5 Done-with: Michael Brasser Reviewed-by: Laszlo Agocs --- src/platformsupport/input/evdevtouch/evdevtouch.pri | 6 ++++-- src/platformsupport/input/evdevtouch/qevdevtouch.cpp | 12 ++++++------ src/platformsupport/input/evdevtouch/qevdevtouch_p.h | 4 ++-- src/plugins/generic/evdevtouch/README | 5 +++-- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/platformsupport/input/evdevtouch/evdevtouch.pri b/src/platformsupport/input/evdevtouch/evdevtouch.pri index 16e1a981fa..402c276d4d 100644 --- a/src/platformsupport/input/evdevtouch/evdevtouch.pri +++ b/src/platformsupport/input/evdevtouch/evdevtouch.pri @@ -8,6 +8,8 @@ contains(QT_CONFIG, libudev) { LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV } -# DEFINES += USE_MTDEV +contains(CONFIG, mtdev) { + CONFIG += link_pkgconfig + PKGCONFIG_PRIVATE += mtdev +} -contains(DEFINES, USE_MTDEV): LIBS_PRIVATE += -lmtdev diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp index 89215557c1..d9468ae1b8 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp @@ -49,7 +49,7 @@ #include #include -#ifdef USE_MTDEV +#if !defined(QT_NO_MTDEV) extern "C" { #include } @@ -164,7 +164,7 @@ static inline bool testBit(long bit, const long *array) QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, QObject *parent) : QObject(parent), m_notify(0), m_fd(-1), d(0) -#ifdef USE_MTDEV +#if !defined(QT_NO_MTDEV) , m_mtdev(0) #endif { @@ -233,7 +233,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, return; } -#ifdef USE_MTDEV +#if !defined(QT_NO_MTDEV) m_mtdev = static_cast(calloc(1, sizeof(mtdev))); int mtdeverr = mtdev_open(m_mtdev, m_fd); if (mtdeverr) { @@ -245,7 +245,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, d = new QEvdevTouchScreenData(this, args); -#ifdef USE_MTDEV +#if !defined(QT_NO_MTDEV) const char *mtdevStr = "(mtdev)"; d->m_typeB = true; #else @@ -329,7 +329,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, QEvdevTouchScreenHandler::~QEvdevTouchScreenHandler() { -#ifdef USE_MTDEV +#if !defined(QT_NO_MTDEV) if (m_mtdev) { mtdev_close(m_mtdev); free(m_mtdev); @@ -347,7 +347,7 @@ void QEvdevTouchScreenHandler::readData() ::input_event buffer[32]; int n = 0; for (; ;) { -#ifdef USE_MTDEV +#if !defined(QT_NO_MTDEV) int result = mtdev_get(m_mtdev, m_fd, buffer, sizeof(buffer) / sizeof(::input_event)); if (result > 0) result *= sizeof(::input_event); diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch_p.h b/src/platformsupport/input/evdevtouch/qevdevtouch_p.h index be7dbfba14..dbd401c297 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouch_p.h +++ b/src/platformsupport/input/evdevtouch/qevdevtouch_p.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QSocketNotifier; class QEvdevTouchScreenData; -#ifdef USE_MTDEV +#if !defined(QT_NO_MTDEV) struct mtdev; #endif @@ -71,7 +71,7 @@ private: QSocketNotifier *m_notify; int m_fd; QEvdevTouchScreenData *d; -#ifdef USE_MTDEV +#if !defined(QT_NO_MTDEV) mtdev *m_mtdev; #endif }; diff --git a/src/plugins/generic/evdevtouch/README b/src/plugins/generic/evdevtouch/README index ad406254d1..833b511fd8 100644 --- a/src/plugins/generic/evdevtouch/README +++ b/src/plugins/generic/evdevtouch/README @@ -5,8 +5,9 @@ Single-touch devices reporting ABS_X and Y only are not supported by this plugin. Use tslib or evdevmouse instead. The protocol type will be detected automatically. -To enable libmtdev support uncomment the USE_MTDEV define in -src/platformsupport/input/evdevtouch/evdevtouch.pri. + +libmtdev is automatically detected based on library availability. To disable it, +pass -no-mtdev to configure. Tested with the following kernel drivers: bcm5974 (type A) From 6b0e7f111c5bc14edd03c53cb521b3a1278ca2e9 Mon Sep 17 00:00:00 2001 From: Kurt Pattyn Date: Sat, 21 Dec 2013 14:50:14 +0100 Subject: [PATCH 10/24] Windows platform plugin: Add missing case statement Change-Id: I9b9fc6cf000b262277711374e0a2fe119328849e Reviewed-by: Friedemann Kleint Reviewed-by: Konstantin Ritt --- src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 832ce24354..7ba48fe0cb 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -2132,6 +2132,9 @@ bool useHelper(QPlatformTheme::DialogType type) break; #endif case QPlatformTheme::FontDialog: + case QPlatformTheme::MessageDialog: + break; + default: break; } return false; @@ -2160,6 +2163,9 @@ QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type) break; #endif case QPlatformTheme::FontDialog: + case QPlatformTheme::MessageDialog: + break; + default: break; } return 0; From 56d141ae6bd3fbb6b100307a7a251e2026147f60 Mon Sep 17 00:00:00 2001 From: Alan Alpert <416365416c@gmail.com> Date: Fri, 13 Sep 2013 14:57:24 -0700 Subject: [PATCH 11/24] Improve QFileSelector doc Mostly just adding proper tags and sections, as well as a few grammatical fixes. Change-Id: I219517d740fa7385e923a9e09cb7e241378fcbdd Reviewed-by: Thiago Macieira Reviewed-by: Martin Smith --- src/corelib/io/qfileselector.cpp | 63 ++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index 72e4198fb0..0dbf5aa1e6 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -69,7 +69,7 @@ QFileSelectorPrivate::QFileSelectorPrivate() /*! \class QFileSelector \inmodule QtCore - \brief QFileSelector provides a convenient way of selecting file variants + \brief QFileSelector provides a convenient way of selecting file variants. \since 5.2 QFileSelector is a convenience for selecting file variants based on platform or device @@ -77,6 +77,10 @@ QFileSelectorPrivate::QFileSelectorPrivate() different variants more easily in some circumstances, such as when the correct variant cannot be determined during the deploy step. + \section1 Using QFileSelector + + If you always use the same file you do not need to use QFileSelector. + Consider the following example usage, where you want to use different settings files on different locales. You might select code between locales like this: @@ -115,7 +119,7 @@ QFileSelectorPrivate::QFileSelectorPrivate() QFile defaultsFile(selector.select("data/defaults.conf")); \endcode - The files to be selected are placed in directories named with a '+' and a selector name. In the above + The files to be selected are placed in directories named with a \c'+' and a selector name. In the above example you could have the platform configurations selected by placing them in the following locations: \code data/defaults.conf @@ -124,8 +128,6 @@ QFileSelectorPrivate::QFileSelectorPrivate() data/+ios/+en_GB/defaults.conf \endcode - If you always use the same file you do not need to use QFileSelector. - To find selected files, QFileSelector looks in the same directory as the base file. If there are any directories of the form + with an active selector, QFileSelector will prefer a file with the same file name from that directory over the base file. These directories can be nested to @@ -138,33 +140,43 @@ QFileSelectorPrivate::QFileSelectorPrivate() With those files available, you would select a different file on android and blackberry platforms, but only if the locale was en_GB. + QFileSelector will not attempt to select if the base file does not exist. For error handling in + the case no valid selectors are present, it is recommended to have a default or error-handling + file in the base file location even if you expect selectors to be present for all deployments. + + In a future version, some may be marked as deploy-time static and be moved during the + deployment step as an optimization. As selectors come with a performance cost, it is + recommended to avoid their use in circumstances involving performance-critical code. + + \section1 Adding selectors + Selectors normally available are \list - \li platform, one of: android, blackberry, ios, windows, osx, linux, generic_unix or unknown. + \li platform, any of the following strings which match the platform the application is running + on: android, blackberry, ios, mac, linux, wince, unix, windows. \li locale, same as QLocale::system().name(). \endlist - Further selectors will be added from the QT_FILE_SELECTORS environment variable, which when - set should be a set of colon (semi-colon on windows) separated selectors. Note that this - variable will only be read once, selectors may not update if the variable changes while the - application is running. + Further selectors will be added from the \c QT_FILE_SELECTORS environment variable, which + when set should be a set of comma separated selectors. Note that this variable will only be + read once; selectors may not update if the variable changes while the application is running. + The initial set of selectors are evaluated only once, on first use. - The initial set of selectors are evaluated only once, on first use. In a future - version, some may be marked as deploy-time static and be moved during the deployment step as an - optimization. As selectors come with a performance cost, it is recommended to avoid their use - in circumstances involving performance-critical code. + You can also add extra selectors at runtime for custom behavior. These will be used in any + future calls to select(). If the extra selectors list has been changed, calls to select() will + use the new list and may return differently. - Additionally you can add extra selectors at runtime to customize behavior further. These will - be used in any future calls to select(). If the extra selectors list has been changed, calls to - select() will use the new list and may return differently. + \section1 Conflict resolution when multiple selectors apply When multiple selectors could be applied to the same file, the first matching selector is chosen. The order selectors are checked in are: - 1. Selectors set via setExtraSelectors(), in the order they are in the list - 2. Selectors in the QT_FILE_SELECTORS environment variable, from left to right - 3. Locale - 4. Platform + \list 1 + \li Selectors set via setExtraSelectors(), in the order they are in the list + \li Selectors in the \c QT_FILE_SELECTORS environment variable, from left to right + \li Locale + \li Platform + \endlist Here is an example involving multiple selectors matching at the same time. It uses platform selectors, plus an extra selector named "admin" is set by the application based on user @@ -179,14 +191,11 @@ QFileSelectorPrivate::QFileSelectorPrivate() images/+admin/+linux/background.png \endcode - Because extra selectors are checked before platform the +admin/background.png will be chosen - on windows when the admin selector is set, and +windows/background.png will be chosen on - windows when the admin selector is not set. On linux, the +admin/+linux/background.png will be - chosen when admin is set, and the +linux/background.png when it is not. + Because extra selectors are checked before platform the \c{+admin/background.png} will be chosen + on Windows when the admin selector is set, and \c{+windows/background.png} will be chosen on + Windows when the admin selector is not set. On Linux, the \c{+admin/+linux/background.png} will be + chosen when admin is set, and the \c{+linux/background.png} when it is not. - QFileSelector will not attempt to select if the base file does not exist. For error handling in - the case no valid selectors are present, it is recommended to have a default or error-handling - file in the base file location even if you expect selectors to be present for all deployments. */ /*! From 82edcd4e12d2652d63ec0732d8053b2761562d3d Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Fri, 20 Dec 2013 19:34:06 +0100 Subject: [PATCH 12/24] Don't leak pending call objects when peer disconnects Unlike in regular connection to DBus server, we don't get pending call notifies when a peer drops the connection in peer-to-peer mode. Thus, we need to keep track of pending calls in such cases and get rid of them in ~QDBusConnectionPrivate(). Change-Id: I83e20db0bc7b2ebf509c7fdb1382ffc7d0ede9d3 Done-with: Kalle Vahlman Reviewed-by: Daniele E. Domenichelli Reviewed-by: Thiago Macieira --- src/dbus/qdbusconnection_p.h | 2 ++ src/dbus/qdbusintegrator.cpp | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 515eab6dfe..350e49a50d 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -178,6 +178,7 @@ public: typedef QMultiHash SignalHookHash; typedef QHash MetaObjectHash; typedef QHash MatchRefCountHash; + typedef QList PendingCallList; struct WatchedServiceData { WatchedServiceData() : refcount(0) {} @@ -316,6 +317,7 @@ public: MatchRefCountHash matchRefCounts; ObjectTreeNode rootNode; MetaObjectHash cachedMetaObjects; + PendingCallList pendingCalls; QMutex callDeliveryMutex; QDBusCallDeliveryEvent *callDeliveryState; // protected by the callDeliveryMutex mutex diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index d797fbfb99..77de09d197 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1092,6 +1092,9 @@ void QDBusConnectionPrivate::closeConnection() ; } } + + qDeleteAll(pendingCalls); + qDBusDebug() << this << "Disconnected"; } @@ -1834,6 +1837,8 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) QMutexLocker locker(&call->mutex); + connection->pendingCalls.removeOne(call); + QDBusMessage &msg = call->replyMessage; if (call->pending) { // decode the message @@ -2094,6 +2099,10 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM pcall->pending = pending; q_dbus_pending_call_set_notify(pending, qDBusResultReceived, pcall, 0); + // DBus won't notify us when a peer disconnects so we need to track these ourselves + if (mode == QDBusConnectionPrivate::PeerMode) + pendingCalls.append(pcall); + return pcall; } else { // we're probably disconnected at this point From 080096590b9bc30fcbaba1bb140f6aee20418e7a Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Tue, 31 Dec 2013 15:55:35 +0200 Subject: [PATCH 13/24] xcb platform: Fix build when both EGL and xcb-Xlib are used Fix a multiple define when Qt is configured to use both EGL and xcb-Xlib. Change-Id: I6fdb282f575842711b3b5d377bbdf3bc9909bf0c Reviewed-by: Christoph Cullmann Reviewed-by: David Faure --- src/plugins/platforms/xcb/qxcbconnection.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 24734a8240..3c4ab8d3e2 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -268,8 +268,13 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , m_focusWindow(0) , m_systemTrayTracker(0) { +#ifdef XCB_USE_EGL + EGLNativeDisplayType dpy = EGL_DEFAULT_DISPLAY; +#elif defined(XCB_USE_XLIB) + Display *dpy; +#endif #ifdef XCB_USE_XLIB - Display *dpy = XOpenDisplay(m_displayName.constData()); + dpy = XOpenDisplay(m_displayName.constData()); if (dpy) { m_primaryScreen = DefaultScreen(dpy); m_connection = XGetXCBConnection(dpy); @@ -285,7 +290,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra qFatal("QXcbConnection: Could not connect to display %s", m_displayName.constData()); #ifdef XCB_USE_EGL - EGLNativeDisplayType dpy = EGL_DEFAULT_DISPLAY; EGLDisplay eglDisplay = eglGetDisplay(dpy); m_egl_display = eglDisplay; EGLint major, minor; From 631c3dbc800bb9b2e3b227c0a09523f0f7eef0b7 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 30 Dec 2013 03:53:40 -0800 Subject: [PATCH 14/24] qdoc: Fix Q_PROPERTY parsing When parsing Q_PROPERTY declarations, qdoc tries to always read an associated value for each matched keyword. This fails for property declarations including a CONSTANT or FINAL, as they have no associated values. This change fixes the above problem and makes the parsing more robust by checking the return value of matchProperty() and skipping to closing parenthesis in case of failure. Task-number: QTBUG-35722 Change-Id: Ia483b8e74aeef19b2e761b21473cd4f765cdca19 Reviewed-by: J-P Nurmi Reviewed-by: Martin Smith --- src/tools/qdoc/cppcodeparser.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index cec042f92b..bb403bd4d9 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -1916,6 +1916,16 @@ bool CppCodeParser::matchProperty(InnerNode *parent) QString key = previousLexeme(); QString value; + // Keywords with no associated values + if (key == "CONSTANT") { + property->setConstant(); + continue; + } + else if (key == "FINAL") { + property->setFinal(); + continue; + } + if (match(Tok_Ident) || match(Tok_Number)) { value = previousLexeme(); } @@ -1966,7 +1976,7 @@ bool CppCodeParser::matchProperty(InnerNode *parent) if (ok) property->setRevision(revision); else - parent->doc().location().warning(tr("Invalid revision number: %1").arg(value)); + location().warning(tr("Invalid revision number: %1").arg(value)); } else if (key == "SCRIPTABLE") { QString v = value.toLower(); if (v == "true") @@ -1978,10 +1988,6 @@ bool CppCodeParser::matchProperty(InnerNode *parent) property->setRuntimeScrFunc(value); } } - else if (key == "CONSTANT") - property->setConstant(); - else if (key == "FINAL") - property->setFinal(); } match(Tok_RightParen); return true; @@ -2061,7 +2067,11 @@ bool CppCodeParser::matchDeclList(InnerNode *parent) case Tok_Q_PROPERTY: case Tok_Q_PRIVATE_PROPERTY: case Tok_QDOC_PROPERTY: - matchProperty(parent); + if (!matchProperty(parent)) { + location().warning(tr("Failed to parse token %1 in property declaration").arg(lexeme())); + skipTo(Tok_RightParen); + match(Tok_RightParen); + } break; case Tok_Q_DECLARE_SEQUENTIAL_ITERATOR: readToken(); From 97c1b2d32ed06a186ce2f0f342c8d056ddb987a2 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 10 Dec 2013 15:47:46 +0100 Subject: [PATCH 15/24] Accessibility: Do not assert when a widget doesn't have a QAI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][QtGui] Fixed crash when sending accessibility updates when the corresponding widget does not have a corresponding QAccessibleInterface. This showed on Mac for example with QStatusBar. Task-number: QTBUG-35421 Change-Id: I94174e98e858b7a0122532ee5fcc8458a263bccd Reviewed-by: Jan Arve Sæther --- src/gui/accessible/qaccessible.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 5d28512697..dffdfa889a 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1313,6 +1313,8 @@ QAccessible::Id QAccessibleEvent::uniqueId() const if (!m_object) return m_uniqueId; QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(m_object); + if (!iface) + return 0; if (m_child != -1) iface = iface->child(m_child); return QAccessible::uniqueId(iface); From 2e8c3f744407607a522abe25abd21ec733365793 Mon Sep 17 00:00:00 2001 From: Jeff Tranter Date: Tue, 24 Dec 2013 11:44:39 -0500 Subject: [PATCH 16/24] Fix some typos in documentation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix some spelling and grammatical errors in comments that show up in Qt documentation. No changes to code. Change-Id: I2e946fda0bd9a2117f8e9b2fb300df9bf0a98a6c Reviewed-by: Thiago Macieira Reviewed-by: Topi Reiniö --- examples/widgets/doc/src/diagramscene.qdoc | 4 ++-- src/corelib/tools/qalgorithms.qdoc | 2 +- src/corelib/tools/qtimezone.cpp | 4 ++-- src/gui/image/qimage.cpp | 2 +- src/gui/image/qpixmap.cpp | 2 +- src/widgets/doc/src/modelview.qdoc | 4 ++-- src/widgets/graphicsview/qgraphicssceneevent.cpp | 4 ++-- src/widgets/styles/qstyleoption.cpp | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/widgets/doc/src/diagramscene.qdoc b/examples/widgets/doc/src/diagramscene.qdoc index 92048cdcaf..32168f59ee 100644 --- a/examples/widgets/doc/src/diagramscene.qdoc +++ b/examples/widgets/doc/src/diagramscene.qdoc @@ -507,7 +507,7 @@ \snippet graphicsview/diagramscene/diagramscene.cpp 5 - \c DiagramTextItems emit a signal when they loose focus, which is + \c DiagramTextItems emit a signal when they lose focus, which is connected to this slot. We remove the item if it has no text. If not, we would leak memory and confuse the user as the items will be edited when pressed on by the mouse. @@ -715,7 +715,7 @@ \snippet graphicsview/diagramscene/diagramtextitem.cpp 2 - \c DiagramScene uses the signal emitted when the text item looses + \c DiagramScene uses the signal emitted when the text item loses focus to remove the item if it is empty, i.e., it contains no text. diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc index 412b9cf3b2..40eb2ed41d 100644 --- a/src/corelib/tools/qalgorithms.qdoc +++ b/src/corelib/tools/qalgorithms.qdoc @@ -534,7 +534,7 @@ Use std::lower_bound instead. Performs a binary search of the range [\a begin, \a end) and - returns the position of the first ocurrence of \a value. If no + returns the position of the first occurrence of \a value. If no such item is found, returns the position where it should be inserted. diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index 5fec06b30a..a8ed8739c3 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -185,7 +185,7 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz); The method systemTimeZoneId() returns the current system IANA time zone ID which on OSX and Linux will always be correct. On Windows this ID is - translated from the the Windows system ID using an internal translation + translated from the Windows system ID using an internal translation table and the user's selected country. As a consequence there is a small chance any Windows install may have IDs not known by Qt, in which case "UTC" will be returned. @@ -771,7 +771,7 @@ QTimeZone::OffsetDataList QTimeZone::transitions(const QDateTime &fromDateTime, /*! Returns the current system time zone IANA ID. - On Windows this ID is translated from the the Windows ID using an internal + On Windows this ID is translated from the Windows ID using an internal translation table and the user's selected country. As a consequence there is a small chance any Windows install may have IDs not known by Qt, in which case "UTC" will be returned. diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 0916826529..12ab5eaffa 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1426,7 +1426,7 @@ qreal QImage::devicePixelRatio() const } /*! - Sets the the device pixel ratio for the image. This is the + Sets the device pixel ratio for the image. This is the ratio between image pixels and device-independent pixels. The default \a scaleFactor is 1.0. Setting it to something else has diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index a620d34553..6dced54d20 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -665,7 +665,7 @@ qreal QPixmap::devicePixelRatio() const } /*! - Sets the the device pixel ratio for the pixmap. This is the + Sets the device pixel ratio for the pixmap. This is the ratio between image pixels and device-independent pixels. The default \a scaleFactor is 1.0. Setting it to something else has diff --git a/src/widgets/doc/src/modelview.qdoc b/src/widgets/doc/src/modelview.qdoc index b2f9da9563..f094a58a91 100644 --- a/src/widgets/doc/src/modelview.qdoc +++ b/src/widgets/doc/src/modelview.qdoc @@ -463,7 +463,7 @@ We get the model index that corresponds to the selection by calling \l{QItemSelectionModel::currentIndex()}{treeView->selectionModel()->currentIndex()} - and we get the the field's string by using the model index. Then we just + and we get the field's string by using the model index. Then we just calculate the item's \c hierarchyLevel. Top level items do not have parents and the \l{QAbstractItemModel::}{parent()} method will return a default constructed \l{QModelIndex}{QModelIndex()}. This is why we use the @@ -548,7 +548,7 @@ the underlying data. The data can be looked up by calling \l{QModelIndex::data()}{index.data()}. The delegate's \l{QAbstractItemDelegate::}{sizeHint()} method is used to obtain each - star's dimensions, so the the cell will provide enough height and width to + star's dimensions, so the cell will provide enough height and width to accommodate the stars. Writing custom delegates is the right choice if you want to show your data diff --git a/src/widgets/graphicsview/qgraphicssceneevent.cpp b/src/widgets/graphicsview/qgraphicssceneevent.cpp index 8eb1395a45..631aa7bf19 100644 --- a/src/widgets/graphicsview/qgraphicssceneevent.cpp +++ b/src/widgets/graphicsview/qgraphicssceneevent.cpp @@ -874,7 +874,7 @@ void QGraphicsSceneContextMenuEvent::setPos(const QPointF &pos) /*! Returns the position of the mouse cursor in scene coordinates at the moment the - the context menu was requested. + context menu was requested. \sa pos(), screenPos() */ @@ -899,7 +899,7 @@ void QGraphicsSceneContextMenuEvent::setScenePos(const QPointF &pos) /*! Returns the position of the mouse cursor in screen coordinates at the moment the - the context menu was requested. + context menu was requested. \sa pos(), scenePos() */ diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp index 5fe071087e..5913b2f261 100644 --- a/src/widgets/styles/qstyleoption.cpp +++ b/src/widgets/styles/qstyleoption.cpp @@ -1116,7 +1116,7 @@ QStyleOptionToolBar::QStyleOptionToolBar(int version) The order of the positions within a line starts at the top of a vertical line, and from the left within a horizontal line. The - order of the positions for the lines is always from the the + order of the positions for the lines is always from the parent widget's boundary edges. \value Beginning The toolbar is located at the beginning of the line, From f9a47a6aa5a83a872c38173d10f9c29a81a2bd27 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Mon, 23 Dec 2013 18:08:04 +0200 Subject: [PATCH 17/24] Android: Don't show ActionBar at startup. Task-number: QTBUG-35151 Change-Id: Ie62e50032aaa647a86c4f03b1a3363e5ef6a1bbb Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../src/org/qtproject/qt5/android/QtActivityDelegate.java | 6 ++---- src/plugins/platforms/android/src/androidjnimenu.cpp | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 3bcd6eaea3..6198baeedc 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -348,6 +348,7 @@ public class QtActivityDelegate } m_activity = activity; + setActionBarVisibility(false); QtNative.setActivity(m_activity, this); QtNative.setClassLoader(classLoader); if (loaderParams.containsKey(STATIC_INIT_CLASSES_KEY)) { @@ -412,7 +413,6 @@ public class QtActivityDelegate m_applicationParameters = loaderParams.getString(APPLICATION_PARAMETERS_KEY); else m_applicationParameters = ""; - setActionBarVisibility(false); return true; } @@ -816,8 +816,7 @@ public class QtActivityDelegate { m_opionsMenuIsVisible = true; boolean res = QtNative.onPrepareOptionsMenu(menu); - if (!res || menu.size() == 0) - setActionBarVisibility(false); + setActionBarVisibility(res && menu.size() > 0); return res; } @@ -834,7 +833,6 @@ public class QtActivityDelegate public void resetOptionsMenu() { - setActionBarVisibility(true); if (Build.VERSION.SDK_INT > 10) { try { Activity.class.getMethod("invalidateOptionsMenu").invoke(m_activity); diff --git a/src/plugins/platforms/android/src/androidjnimenu.cpp b/src/plugins/platforms/android/src/androidjnimenu.cpp index 293af2b9cd..dbdd7c9b8e 100644 --- a/src/plugins/platforms/android/src/androidjnimenu.cpp +++ b/src/plugins/platforms/android/src/androidjnimenu.cpp @@ -156,11 +156,11 @@ namespace QtAndroidMenu foreach (QAndroidPlatformMenuBar *menuBar, menuBars) { if (menuBar->parentWindow() == window) { visibleMenuBar = menuBar; + resetMenuBar(); break; } } - resetMenuBar(); } void addMenuBar(QAndroidPlatformMenuBar *menuBar) From 58326e8585ea9fbd168321b5fa3f7d7aec93c924 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 27 Nov 2013 14:38:57 +0100 Subject: [PATCH 18/24] Android: Overwrite plugin cache when APK is updated To allow updating APKs with new versions of Qt, we need to delete the old cache when the APK is updated. This patch does two things: 1. Move the plugins (and imports/qml) into a directory called qt-reserved-files/ to better separate the cache from the rest of the application. The first time the files are put here, we will delete the old cache in /plugins, /imports and /qml if they exist to avoid leaving old files around forever. 2. Add versioning to the cache and flush it every time the APK is reinstalled. Potentially, the libraries in the APK can change for every reinstall, so this is the safest approach. Task-number: QTBUG-35129 [ChangeLog][Android][QTBUG-35129] Update deployed plugins and imports when APK is updated on the device. Change-Id: Ie38b639db2cfba8a521acc875c4afd5e07df3efd Reviewed-by: Paul Olav Tvete --- .../qt5/android/bindings/QtActivity.java | 126 ++++++++++++++++-- 1 file changed, 116 insertions(+), 10 deletions(-) diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java index a10e58bb87..6762717d91 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -32,6 +32,8 @@ import java.io.OutputStream; import java.io.InputStream; import java.io.FileOutputStream; import java.io.FileInputStream; +import java.io.DataOutputStream; +import java.io.DataInputStream; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -50,6 +52,7 @@ import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.content.res.Resources.Theme; import android.content.res.AssetManager; @@ -382,6 +385,9 @@ public class QtActivity extends Activity InputStream inputStream = assetsManager.open(source); OutputStream outputStream = new FileOutputStream(destinationFile); copyFile(inputStream, outputStream); + + inputStream.close(); + outputStream.close(); } private static void createBundledBinary(String source, String destination) @@ -401,13 +407,66 @@ public class QtActivity extends Activity InputStream inputStream = new FileInputStream(source); OutputStream outputStream = new FileOutputStream(destinationFile); copyFile(inputStream, outputStream); + + inputStream.close(); + outputStream.close(); } - private void extractBundledPluginsAndImports(String localPrefix) + private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion) + { + File versionFile = new File(pluginsPrefix + "cache.version"); + + long cacheVersion = 0; + if (versionFile.exists() && versionFile.canRead()) { + try { + DataInputStream inputStream = new DataInputStream(new FileInputStream(versionFile)); + cacheVersion = inputStream.readLong(); + inputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (cacheVersion != packageVersion) { + deleteRecursively(new File(pluginsPrefix)); + return true; + } else { + return false; + } + } + + private void extractBundledPluginsAndImports(String pluginsPrefix) throws IOException { ArrayList libs = new ArrayList(); + String dataDir = getApplicationInfo().dataDir + "/"; + + long packageVersion = -1; + try { + PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0); + packageVersion = packageInfo.lastUpdateTime; + } catch (Exception e) { + e.printStackTrace(); + } + + if (!cleanCacheIfNecessary(pluginsPrefix, packageVersion)) + return; + + { + File versionFile = new File(pluginsPrefix + "cache.version"); + + File parentDirectory = versionFile.getParentFile(); + if (!parentDirectory.exists()) + parentDirectory.mkdirs(); + + versionFile.createNewFile(); + + DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(versionFile)); + outputStream.writeLong(packageVersion); + outputStream.close(); + } + { String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY; java.util.Set keys = m_activityInfo.metaData.keySet(); @@ -416,8 +475,8 @@ public class QtActivity extends Activity for (String bundledImportBinary : list) { String[] split = bundledImportBinary.split(":"); - String sourceFileName = localPrefix + "lib/" + split[0]; - String destinationFileName = localPrefix + split[1]; + String sourceFileName = dataDir + "lib/" + split[0]; + String destinationFileName = pluginsPrefix + split[1]; createBundledBinary(sourceFileName, destinationFileName); } } @@ -431,7 +490,7 @@ public class QtActivity extends Activity for (String fileName : list) { String[] split = fileName.split(":"); String sourceFileName = split[0]; - String destinationFileName = localPrefix + split[1]; + String destinationFileName = pluginsPrefix + split[1]; copyAsset(sourceFileName, destinationFileName); } } @@ -439,6 +498,45 @@ public class QtActivity extends Activity } } + private void deleteRecursively(File directory) + { + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) + deleteRecursively(file); + else + file.delete(); + } + + directory.delete(); + } + } + + private void cleanOldCacheIfNecessary(String oldLocalPrefix, String localPrefix) + { + File newCache = new File(localPrefix); + if (!newCache.exists()) { + { + File oldPluginsCache = new File(oldLocalPrefix + "plugins/"); + if (oldPluginsCache.exists() && oldPluginsCache.isDirectory()) + deleteRecursively(oldPluginsCache); + } + + { + File oldImportsCache = new File(oldLocalPrefix + "imports/"); + if (oldImportsCache.exists() && oldImportsCache.isDirectory()) + deleteRecursively(oldImportsCache); + } + + { + File oldQmlCache = new File(oldLocalPrefix + "qml/"); + if (oldQmlCache.exists() && oldQmlCache.isDirectory()) + deleteRecursively(oldQmlCache); + } + } + } + private void startApp(final boolean firstStart) { try { @@ -464,11 +562,15 @@ public class QtActivity extends Activity if (m_activityInfo.metaData.containsKey("android.app.libs_prefix")) localPrefix = m_activityInfo.metaData.getString("android.app.libs_prefix"); + String pluginsPrefix = localPrefix; + boolean bundlingQtLibs = false; if (m_activityInfo.metaData.containsKey("android.app.bundle_local_qt_libs") && m_activityInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) { localPrefix = getApplicationInfo().dataDir + "/"; - extractBundledPluginsAndImports(localPrefix); + pluginsPrefix = localPrefix + "qt-reserved-files/"; + cleanOldCacheIfNecessary(localPrefix, pluginsPrefix); + extractBundledPluginsAndImports(pluginsPrefix); bundlingQtLibs = true; } @@ -484,8 +586,12 @@ public class QtActivity extends Activity if (m_activityInfo.metaData.containsKey("android.app.load_local_libs")) { String[] extraLibs = m_activityInfo.metaData.getString("android.app.load_local_libs").split(":"); for (String lib : extraLibs) { - if (lib.length() > 0) - libraryList.add(localPrefix + lib); + if (lib.length() > 0) { + if (lib.startsWith("lib/")) + libraryList.add(localPrefix + lib); + else + libraryList.add(pluginsPrefix + lib); + } } } @@ -513,9 +619,9 @@ public class QtActivity extends Activity } loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList); loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES - + "\tQML2_IMPORT_PATH=" + localPrefix + "/qml" - + "\tQML_IMPORT_PATH=" + localPrefix + "/imports" - + "\tQT_PLUGIN_PATH=" + localPrefix + "/plugins"); + + "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml" + + "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports" + + "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins"); Intent intent = getIntent(); if (intent != null) { From c6b285a79ddb0266ce270207b4b98945c6ca0cfa Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Wed, 11 Dec 2013 16:49:59 +0100 Subject: [PATCH 19/24] Android: let fullscreen use entire screen API level 19 (Android 4.4) introduces "immersive" mode which lets the app use the entire screen. Change-Id: I12f6aebaf1303cdc5b6bfb51944e895351fa2406 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qt5/android/QtActivityDelegate.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 6198baeedc..07b517d3d0 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -139,9 +139,41 @@ public class QtActivityDelegate if (m_fullScreen = enterFullScreen) { m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + if (Build.VERSION.SDK_INT >= 19) { + try { + int ui_flag_immersive_sticky = View.class.getDeclaredField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY").getInt(null); + int ui_flag_layout_stable = View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_STABLE").getInt(null); + int ui_flag_layout_hide_navigation = View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION").getInt(null); + int ui_flag_layout_fullscreen = View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN").getInt(null); + int ui_flag_hide_navigation = View.class.getDeclaredField("SYSTEM_UI_FLAG_HIDE_NAVIGATION").getInt(null); + int ui_flag_fullscreen = View.class.getDeclaredField("SYSTEM_UI_FLAG_FULLSCREEN").getInt(null); + + Method m = View.class.getMethod("setSystemUiVisibility", int.class); + m.invoke(m_activity.getWindow().getDecorView(), + ui_flag_layout_stable + | ui_flag_layout_hide_navigation + | ui_flag_layout_fullscreen + | ui_flag_hide_navigation + | ui_flag_fullscreen + | ui_flag_immersive_sticky + | View.INVISIBLE); + } catch (Exception e) { + e.printStackTrace(); + } + } } else { m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + if (Build.VERSION.SDK_INT >= 19) { + try { + int ui_flag_visible = View.class.getDeclaredField("SYSTEM_UI_FLAG_VISIBLE").getInt(null); + Method m = View.class.getMethod("setSystemUiVisibility", int.class); + m.invoke(m_activity.getWindow().getDecorView(), + ui_flag_visible); + } catch (Exception e) { + e.printStackTrace(); + } + } } } @@ -696,6 +728,12 @@ public class QtActivityDelegate QtNative.updateApplicationState(ApplicationActive); QtNative.clearLostActions(); QtNative.updateWindow(); + + if (m_fullScreen) { + // Suspending the app clears the immersive mode, so we need to set it again. + m_fullScreen = false; // Force the setFullScreen() call below to actually do something + setFullScreen(true); + } } } } From 56ddf858f396038d8df0e25bdc3726e8d6886387 Mon Sep 17 00:00:00 2001 From: Ivan Komissarov Date: Tue, 31 Dec 2013 13:27:32 +0400 Subject: [PATCH 20/24] Add missed header to qfileselector.cpp. Change-Id: I2fd6fb2ae1663730a008221f6beeef19a5307246 Reviewed-by: David Faure --- src/corelib/io/qfileselector.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index 0dbf5aa1e6..92d3564a0f 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -51,6 +51,10 @@ #include #include +#ifdef Q_OS_UNIX +#include +#endif + QT_BEGIN_NAMESPACE //Environment variable to allow tooling full control of file selectors From a79f8a3a6774875fc16fd63461e04c2791a8d03d Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 17 Dec 2013 10:47:12 +0100 Subject: [PATCH 21/24] Cocoa: fix single punctuation input via CJK input method 2d05d3bd2815c220474b3c07bf3f2ef7417d3070 was not correct. On OS X, when user uses CJK input method, only types single punctuation, it was converted to CJK ones, and not showed in composing text. Task-number: QTBUG-35700 Change-Id: I919edb3f5165bf943c0d90d06a788a2f335bb1ba Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qnsview.mm | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 1c15c3b561..e183f93c6c 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1342,11 +1342,6 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) { Q_UNUSED(replacementRange) - if (m_sendKeyEvent && m_composingText.isEmpty()) { - // don't send input method events for simple text input (let handleKeyEvent send key events instead) - return; - } - QString commitString; if ([aString length]) { if ([aString isKindOfClass:[NSAttributedString class]]) { From 286c41c32f26691056ccac6e9276921e1bf930da Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Fri, 3 Jan 2014 08:53:57 +0100 Subject: [PATCH 22/24] Accessibility Linux: Fix atspi getActions to return action name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][Accessibility] On Linux action names were returned as empty strings in AT-SPI getActions, now returns the proper names. Change-Id: I75a469a0b8a5789cd54ce1b489ed5012654bb265 Reviewed-by: Jan Arve Sæther --- src/platformsupport/linuxaccessibility/atspiadaptor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index 231576ed01..8850f18bab 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -1729,6 +1729,7 @@ QSpiActionArray AtSpiAdaptor::getActions(QAccessibleActionInterface *actionInter QSpiAction action; QStringList keyBindings; + action.name = actionName; action.description = actionInterface->localizedActionDescription(actionName); keyBindings = actionInterface->keyBindingsForAction(actionName); From 753b472cb851bf12033b1e3ae663b4bdd056d1ef Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 3 Jan 2014 12:27:02 +0100 Subject: [PATCH 23/24] REG: Fix support for strings spanning multiple font engines E.g. in the case where the first char in a font got a font engine index != 0, and the second character got font engine index == 0, we would not count the second character as a separate glyph run. The result would be that its glyph indexes would refer to font #0, but the font used to render them would be the same as for the first character, i.e. random. Task-number: QTBUG-35740 [ChangeLog][Text][QTBUG-35740] Fixed regression when shaping some strings containing characters from multiple fonts. Change-Id: I668804045c8b276787c7b256bc87916c467f3f59 Reviewed-by: Konstantin Ritt --- src/gui/text/qtextengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 4e1c8c4c4a..06c5e24920 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -954,12 +954,12 @@ void QTextEngine::shapeText(int item) const itemBoundaries.append(i); itemBoundaries.append(glyph_pos); - lastEngine = engineIdx; QFontEngine *actualFontEngine = static_cast(fontEngine)->engine(engineIdx); si.ascent = qMax(actualFontEngine->ascent(), si.ascent); si.descent = qMax(actualFontEngine->descent(), si.descent); si.leading = qMax(actualFontEngine->leading(), si.leading); } + lastEngine = engineIdx; if (QChar::isHighSurrogate(string[i]) && i + 1 < itemLength && QChar::isLowSurrogate(string[i + 1])) ++i; } From aff3e3c4a20aae52fdafaede8dfcbde2bc990104 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 3 Jan 2014 12:18:19 +0100 Subject: [PATCH 24/24] Make texture glyph cache more robust against missing glyphs This fixes failing assertions in the CI system. All the callers of lockedAlphaMapForGlyph always check the return value for being null as well as the image itself, so we need to do the same here as well before calling unlockAlphaMapForGlyph. This is proposed to stable because commit f9399d69add411adf757e3390488ff57655833b7 also landed in stable. Change-Id: I0a4f4fbb1727e5b4ad497b08177d14c81abd2dd0 Reviewed-by: Lars Knoll Reviewed-by: Gunnar Sletta --- src/gui/painting/qtextureglyphcache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index b953f8d81f..e340c1e613 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -160,7 +160,7 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const // proper metrics will be cached and used later. if (fontEngine->hasInternalCaching()) { QImage *locked = fontEngine->lockedAlphaMapForGlyph(glyph, subPixelPosition, format); - if (locked) + if (locked && !locked->isNull()) fontEngine->unlockAlphaMapForGlyph(); }