disable KFileDialog usage if QClipboard can recurse
Change-Id: If23a365b96c1634c2f8940f6ece973089dc3151f
This commit is contained in:
27
configure.ac
27
configure.ac
@@ -11275,6 +11275,33 @@ int main(int argc, char *argv[])
|
|||||||
# Remove meta object data
|
# Remove meta object data
|
||||||
rm -f "${TSTBASE}."*
|
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
|
LIBS=$save_LIBS
|
||||||
CXXFLAGS=$save_CXXFLAGS
|
CXXFLAGS=$save_CXXFLAGS
|
||||||
AC_LANG_POP([C++])
|
AC_LANG_POP([C++])
|
||||||
|
@@ -12,7 +12,8 @@ $(eval $(call gb_CustomTarget_CustomTarget,vcl/unx/kde4))
|
|||||||
$(call gb_CustomTarget_get_target,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)/KDEXLib.moc \
|
||||||
$(call gb_CustomTarget_get_workdir,vcl/unx/kde4)/KDE4FilePicker.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 : \
|
$(call gb_CustomTarget_get_workdir,vcl/unx/kde4)/%.moc : \
|
||||||
$(SRCDIR)/vcl/unx/kde4/%.hxx \
|
$(SRCDIR)/vcl/unx/kde4/%.hxx \
|
||||||
|
@@ -35,7 +35,7 @@ uno::Reference< ui::dialogs::XFilePicker2 > KDESalInstance::createFilePicker(
|
|||||||
const uno::Reference< uno::XComponentContext >& xMSF )
|
const uno::Reference< uno::XComponentContext >& xMSF )
|
||||||
{
|
{
|
||||||
KDEXLib* kdeXLib = static_cast<KDEXLib*>( mpXLib );
|
KDEXLib* kdeXLib = static_cast<KDEXLib*>( mpXLib );
|
||||||
if (kdeXLib->haveQt4SocketExcludeFix())
|
if (kdeXLib->allowKdeDialogs())
|
||||||
return uno::Reference< ui::dialogs::XFilePicker2 >(
|
return uno::Reference< ui::dialogs::XFilePicker2 >(
|
||||||
kdeXLib->createFilePicker(xMSF) );
|
kdeXLib->createFilePicker(xMSF) );
|
||||||
else
|
else
|
||||||
|
@@ -47,13 +47,14 @@
|
|||||||
#if KDE_HAVE_GLIB
|
#if KDE_HAVE_GLIB
|
||||||
#include "KDE4FilePicker.hxx"
|
#include "KDE4FilePicker.hxx"
|
||||||
#include "tst_exclude_socket_notifiers.moc"
|
#include "tst_exclude_socket_notifiers.moc"
|
||||||
|
#include "tst_exclude_posted_events.moc"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
KDEXLib::KDEXLib() :
|
KDEXLib::KDEXLib() :
|
||||||
SalXLib(), m_bStartupDone(false), m_pApplication(0),
|
SalXLib(), m_bStartupDone(false), m_pApplication(0),
|
||||||
m_pFreeCmdLineArgs(0), m_pAppCmdLineArgs(0), m_nFakeCmdLineArgs( 0 ),
|
m_pFreeCmdLineArgs(0), m_pAppCmdLineArgs(0), m_nFakeCmdLineArgs( 0 ),
|
||||||
m_frameWidth( -1 ), m_isGlibEventLoopType(false),
|
m_frameWidth( -1 ), m_isGlibEventLoopType(false),
|
||||||
m_haveQt4SocketExcludeFix(false)
|
m_allowKdeDialogs(false)
|
||||||
{
|
{
|
||||||
// the timers created here means they belong to the main thread.
|
// 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,
|
// 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
|
#if KDE_HAVE_GLIB
|
||||||
m_isGlibEventLoopType = QAbstractEventDispatcher::instance()->inherits( "QEventDispatcherGlib" );
|
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
|
// See http://bugreports.qt.nokia.com/browse/QTBUG-37380
|
||||||
m_haveQt4SocketExcludeFix = true;
|
// https://bugreports.qt-project.org/browse/QTBUG-34614
|
||||||
|
m_allowKdeDialogs = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setupEventLoop();
|
setupEventLoop();
|
||||||
@@ -238,7 +244,7 @@ void KDEXLib::setupEventLoop()
|
|||||||
{
|
{
|
||||||
old_gpoll = g_main_context_get_poll_func( NULL );
|
old_gpoll = g_main_context_get_poll_func( NULL );
|
||||||
g_main_context_set_poll_func( NULL, gpoll_wrapper );
|
g_main_context_set_poll_func( NULL, gpoll_wrapper );
|
||||||
if( m_haveQt4SocketExcludeFix )
|
if( m_allowKdeDialogs )
|
||||||
m_pApplication->clipboard()->setProperty( "useEventLoopWhenWaiting", true );
|
m_pApplication->clipboard()->setProperty( "useEventLoopWhenWaiting", true );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -53,7 +53,7 @@ class KDEXLib : public QObject, public SalXLib
|
|||||||
QTimer userEventTimer;
|
QTimer userEventTimer;
|
||||||
int m_frameWidth;
|
int m_frameWidth;
|
||||||
bool m_isGlibEventLoopType;
|
bool m_isGlibEventLoopType;
|
||||||
bool m_haveQt4SocketExcludeFix;
|
bool m_allowKdeDialogs;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupEventLoop();
|
void setupEventLoop();
|
||||||
@@ -88,7 +88,7 @@ class KDEXLib : public QObject, public SalXLib
|
|||||||
virtual void PostUserEvent() SAL_OVERRIDE;
|
virtual void PostUserEvent() SAL_OVERRIDE;
|
||||||
|
|
||||||
void doStartup();
|
void doStartup();
|
||||||
bool haveQt4SocketExcludeFix() { return m_haveQt4SocketExcludeFix; }
|
bool allowKdeDialogs() { return m_allowKdeDialogs; }
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
com::sun::star::uno::Reference< com::sun::star::ui::dialogs::XFilePicker2 >
|
com::sun::star::uno::Reference< com::sun::star::ui::dialogs::XFilePicker2 >
|
||||||
|
70
vcl/unx/kde4/tst_exclude_posted_events.hxx
Normal file
70
vcl/unx/kde4/tst_exclude_posted_events.hxx
Normal file
@@ -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;
|
||||||
|
}
|
Reference in New Issue
Block a user