diff options
-rw-r--r-- | configure.ac | 27 | ||||
-rw-r--r-- | vcl/CustomTarget_kde4_moc.mk | 3 | ||||
-rw-r--r-- | vcl/unx/kde4/KDESalInstance.cxx | 2 | ||||
-rw-r--r-- | vcl/unx/kde4/KDEXLib.cxx | 14 | ||||
-rw-r--r-- | vcl/unx/kde4/KDEXLib.hxx | 4 | ||||
-rw-r--r-- | vcl/unx/kde4/tst_exclude_posted_events.hxx | 70 |
6 files changed, 112 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac index d77291eee689..507678adb3f4 100644 --- a/configure.ac +++ b/configure.ac @@ -11275,6 +11275,33 @@ int main(int argc, char *argv[]) # Remove meta object data rm -f "${TSTBASE}."* + AC_MSG_CHECKING([whether Qt avoids QClipboard recursion caused by posted events]) + + # Prepare meta object data + TSTBASE="tst_exclude_posted_events" + TSTMOC="${SRC_ROOT}/vcl/unx/kde4/${TSTBASE}" + ln -fs "${TSTMOC}.hxx" + $MOC4 "${TSTBASE}.hxx" -o "${TSTBASE}.moc" + + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include "tst_exclude_posted_events.moc" + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + exit(tst_excludePostedEvents()); + return 0; +} + ]])],[ + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + AC_MSG_WARN([native KDE4 file pickers will be disabled at runtime - fix your Qt4 library!]) + ]) + + # Remove meta object data + rm -f "${TSTBASE}."* + LIBS=$save_LIBS CXXFLAGS=$save_CXXFLAGS AC_LANG_POP([C++]) diff --git a/vcl/CustomTarget_kde4_moc.mk b/vcl/CustomTarget_kde4_moc.mk index 9e417548da4b..16d1561944c6 100644 --- a/vcl/CustomTarget_kde4_moc.mk +++ b/vcl/CustomTarget_kde4_moc.mk @@ -12,7 +12,8 @@ $(eval $(call gb_CustomTarget_CustomTarget,vcl/unx/kde4)) $(call gb_CustomTarget_get_target,vcl/unx/kde4) : \ $(call gb_CustomTarget_get_workdir,vcl/unx/kde4)/KDEXLib.moc \ $(call gb_CustomTarget_get_workdir,vcl/unx/kde4)/KDE4FilePicker.moc \ - $(call gb_CustomTarget_get_workdir,vcl/unx/kde4)/tst_exclude_socket_notifiers.moc + $(call gb_CustomTarget_get_workdir,vcl/unx/kde4)/tst_exclude_socket_notifiers.moc \ + $(call gb_CustomTarget_get_workdir,vcl/unx/kde4)/tst_exclude_posted_events.moc $(call gb_CustomTarget_get_workdir,vcl/unx/kde4)/%.moc : \ $(SRCDIR)/vcl/unx/kde4/%.hxx \ diff --git a/vcl/unx/kde4/KDESalInstance.cxx b/vcl/unx/kde4/KDESalInstance.cxx index 023d79051741..094cd2055cd5 100644 --- a/vcl/unx/kde4/KDESalInstance.cxx +++ b/vcl/unx/kde4/KDESalInstance.cxx @@ -35,7 +35,7 @@ uno::Reference< ui::dialogs::XFilePicker2 > KDESalInstance::createFilePicker( const uno::Reference< uno::XComponentContext >& xMSF ) { KDEXLib* kdeXLib = static_cast<KDEXLib*>( mpXLib ); - if (kdeXLib->haveQt4SocketExcludeFix()) + if (kdeXLib->allowKdeDialogs()) return uno::Reference< ui::dialogs::XFilePicker2 >( kdeXLib->createFilePicker(xMSF) ); else diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx index 24557bc6fed7..f6c15b06076c 100644 --- a/vcl/unx/kde4/KDEXLib.cxx +++ b/vcl/unx/kde4/KDEXLib.cxx @@ -47,13 +47,14 @@ #if KDE_HAVE_GLIB #include "KDE4FilePicker.hxx" #include "tst_exclude_socket_notifiers.moc" +#include "tst_exclude_posted_events.moc" #endif KDEXLib::KDEXLib() : SalXLib(), m_bStartupDone(false), m_pApplication(0), m_pFreeCmdLineArgs(0), m_pAppCmdLineArgs(0), m_nFakeCmdLineArgs( 0 ), m_frameWidth( -1 ), m_isGlibEventLoopType(false), - m_haveQt4SocketExcludeFix(false) + m_allowKdeDialogs(false) { // the timers created here means they belong to the main thread. // As the timeoutTimer runs the LO event queue, which may block on a dialog, @@ -187,9 +188,14 @@ void KDEXLib::Init() #if KDE_HAVE_GLIB m_isGlibEventLoopType = QAbstractEventDispatcher::instance()->inherits( "QEventDispatcherGlib" ); - if (m_isGlibEventLoopType && (0 == tst_processEventsExcludeSocket())) + // Using KDE dialogs (and their nested event loops) works only with a proper event loop integration + // that will release SolarMutex when waiting for more events. + // Moreover there are bugs in Qt event loop code that allow QClipboard recursing because the event + // loop processes also events that it should not at that point, so no dialogs in that case either. + if (m_isGlibEventLoopType && (0 == tst_processEventsExcludeSocket()) && tst_excludePostedEvents() == 0 ) // See http://bugreports.qt.nokia.com/browse/QTBUG-37380 - m_haveQt4SocketExcludeFix = true; + // https://bugreports.qt-project.org/browse/QTBUG-34614 + m_allowKdeDialogs = true; #endif setupEventLoop(); @@ -238,7 +244,7 @@ void KDEXLib::setupEventLoop() { old_gpoll = g_main_context_get_poll_func( NULL ); g_main_context_set_poll_func( NULL, gpoll_wrapper ); - if( m_haveQt4SocketExcludeFix ) + if( m_allowKdeDialogs ) m_pApplication->clipboard()->setProperty( "useEventLoopWhenWaiting", true ); return; } diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx index e45543d47f26..1f2a2dd1f436 100644 --- a/vcl/unx/kde4/KDEXLib.hxx +++ b/vcl/unx/kde4/KDEXLib.hxx @@ -53,7 +53,7 @@ class KDEXLib : public QObject, public SalXLib QTimer userEventTimer; int m_frameWidth; bool m_isGlibEventLoopType; - bool m_haveQt4SocketExcludeFix; + bool m_allowKdeDialogs; private: void setupEventLoop(); @@ -88,7 +88,7 @@ class KDEXLib : public QObject, public SalXLib virtual void PostUserEvent() SAL_OVERRIDE; void doStartup(); - bool haveQt4SocketExcludeFix() { return m_haveQt4SocketExcludeFix; } + bool allowKdeDialogs() { return m_allowKdeDialogs; } public Q_SLOTS: com::sun::star::uno::Reference< com::sun::star::ui::dialogs::XFilePicker2 > diff --git a/vcl/unx/kde4/tst_exclude_posted_events.hxx b/vcl/unx/kde4/tst_exclude_posted_events.hxx new file mode 100644 index 000000000000..777907cd34e0 --- /dev/null +++ b/vcl/unx/kde4/tst_exclude_posted_events.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + * + * This code is based on the SocketEventsTester from the Qt4 test suite. + */ + +#pragma once + +#include <qcoreapplication.h> +#include <qeventloop.h> +#include <qtimer.h> + +const QEvent::Type eventType = QEvent::User; + +class Test + : public QObject +{ + Q_OBJECT + public: + Test(); + virtual bool event( QEvent* e ); + bool processed; +}; + +Test::Test() + : processed( false ) +{ +} + +bool Test::event( QEvent* e ) +{ + if( e->type() == eventType ) + processed = true; + return QObject::event( e ); +} + +#define QVERIFY(a) \ + if (!a) return 1; + +static int tst_excludePostedEvents() +{ + Test test; + QCoreApplication::postEvent( &test, new QEvent( eventType )); + QEventLoop loop; + QTimer::singleShot(200, &loop, SLOT(quit())); + loop.processEvents(QEventLoop::ExcludeUserInputEvents + | QEventLoop::ExcludeSocketNotifiers +// | QEventLoop::WaitForMoreEvents + | QEventLoop::X11ExcludeTimers); + QVERIFY( !test.processed ); + QTimer::singleShot(200, &loop, SLOT(quit())); + loop.exec(); + QVERIFY( test.processed ); + return 0; +} |