Kaydet (Commit) 65a36221 authored tarafından Luboš Luňák's avatar Luboš Luňák

disable KFileDialog usage if QClipboard can recurse

Change-Id: If23a365b96c1634c2f8940f6ece973089dc3151f
üst e809aa1e
......@@ -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++])
......
......@@ -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 \
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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 >
......
/* -*- 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment