mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 18:08:10 +00:00
Fix #6597: LyX Appears frozen if the process holding the clipboard is frozen
Implements CacheMimeData type so that we only need to query the clipboard once on startup and once each time the contents of the clipboard change. This is important as Qt takes 5 seconds to time-out when the clipboard is non-responsive. Patch by John McCabe-Dansted. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@35790 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
ad51a8e88e
commit
f3ed8071d8
@ -27,6 +27,7 @@
|
||||
#include "support/filetools.h"
|
||||
#include "support/gettext.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/lyxtime.h"
|
||||
|
||||
#ifdef Q_WS_MACX
|
||||
#include "support/linkback/LinkBackProxy.h"
|
||||
@ -55,6 +56,43 @@ namespace lyx {
|
||||
|
||||
namespace frontend {
|
||||
|
||||
static QMimeData const * read_clipboard()
|
||||
{
|
||||
LYXERR(Debug::ACTION, "Getting Clipboard");
|
||||
QMimeData const * source =
|
||||
qApp->clipboard()->mimeData(QClipboard::Clipboard);
|
||||
if (!source) {
|
||||
LYXERR0("0 bytes (no QMimeData)");
|
||||
return new QMimeData();
|
||||
}
|
||||
// It appears that doing IO between getting a mimeData object
|
||||
// and using it can cause a crash (maybe Qt used IO
|
||||
// as an excuse to free() it? Anyway let's not introduce
|
||||
// any new IO here, so e.g. leave the following line commented.
|
||||
// lyxerr << "Got Clipboard (" << (long) source << ")\n" ;
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
void CacheMimeData::update()
|
||||
{
|
||||
time_t const start_time = current_time();
|
||||
LYXERR(Debug::ACTION, "Creating CacheMimeData object");
|
||||
cached_formats_ = read_clipboard()->formats();
|
||||
|
||||
// Qt times out after 5 seconds if it does not recieve a response.
|
||||
if (current_time() - start_time > 3) {
|
||||
lyxerr << "No timely response from clipboard, perhaps process "
|
||||
<< "holding clipboard is frozen?" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QByteArray CacheMimeData::data(QString const & mimeType) const
|
||||
{
|
||||
return read_clipboard()->data(mimeType);
|
||||
}
|
||||
|
||||
|
||||
QString const lyxMimeType(){ return "application/x-lyx"; }
|
||||
QString const pdfMimeType(){ return "application/pdf"; }
|
||||
@ -76,16 +114,9 @@ string const GuiClipboard::getAsLyX() const
|
||||
LYXERR(Debug::ACTION, "GuiClipboard::getAsLyX(): `");
|
||||
// We don't convert encodings here since the encoding of the
|
||||
// clipboard contents is specified in the data itself
|
||||
QMimeData const * source =
|
||||
qApp->clipboard()->mimeData(QClipboard::Clipboard);
|
||||
if (!source) {
|
||||
LYXERR(Debug::ACTION, "' (no QMimeData)");
|
||||
return string();
|
||||
}
|
||||
|
||||
if (source->hasFormat(lyxMimeType())) {
|
||||
if (cache_.hasFormat(lyxMimeType())) {
|
||||
// data from ourself or some other LyX instance
|
||||
QByteArray const ar = source->data(lyxMimeType());
|
||||
QByteArray const ar = cache_.data(lyxMimeType());
|
||||
string const s(ar.data(), ar.count());
|
||||
LYXERR(Debug::ACTION, s << "'");
|
||||
return s;
|
||||
@ -247,14 +278,6 @@ FileName GuiClipboard::getAsGraphics(Cursor const & cur, GraphicsType type) cons
|
||||
return filename;
|
||||
}
|
||||
|
||||
// get mime data
|
||||
QMimeData const * source =
|
||||
qApp->clipboard()->mimeData(QClipboard::Clipboard);
|
||||
if (!source) {
|
||||
LYXERR(Debug::ACTION, "0 bytes (no QMimeData)");
|
||||
return FileName();
|
||||
}
|
||||
|
||||
// get mime for type
|
||||
QString mime;
|
||||
switch (type) {
|
||||
@ -266,10 +289,10 @@ FileName GuiClipboard::getAsGraphics(Cursor const & cur, GraphicsType type) cons
|
||||
}
|
||||
|
||||
// get data
|
||||
if (!source->hasFormat(mime))
|
||||
if (!cache_.hasFormat(mime))
|
||||
return FileName();
|
||||
// data from ourself or some other LyX instance
|
||||
QByteArray const ar = source->data(mime);
|
||||
QByteArray const ar = cache_.data(mime);
|
||||
LYXERR(Debug::ACTION, "Getting from clipboard: mime = " << mime.data()
|
||||
<< "length = " << ar.count());
|
||||
|
||||
@ -336,17 +359,13 @@ void GuiClipboard::put(string const & lyx, docstring const & text)
|
||||
|
||||
bool GuiClipboard::hasLyXContents() const
|
||||
{
|
||||
QMimeData const * const source =
|
||||
qApp->clipboard()->mimeData(QClipboard::Clipboard);
|
||||
return source && source->hasFormat(lyxMimeType());
|
||||
return cache_.hasFormat(lyxMimeType());
|
||||
}
|
||||
|
||||
|
||||
bool GuiClipboard::hasTextContents() const
|
||||
{
|
||||
QMimeData const * const source =
|
||||
qApp->clipboard()->mimeData(QClipboard::Clipboard);
|
||||
return source && source->hasText();
|
||||
return cache_.hasText();
|
||||
}
|
||||
|
||||
|
||||
@ -361,12 +380,9 @@ bool GuiClipboard::hasGraphicsContents(Clipboard::GraphicsType type) const
|
||||
|| hasGraphicsContents(LinkBackGraphicsType);
|
||||
}
|
||||
|
||||
QMimeData const * const source =
|
||||
qApp->clipboard()->mimeData(QClipboard::Clipboard);
|
||||
|
||||
// handle image cases first
|
||||
if (type == PngGraphicsType || type == JpegGraphicsType)
|
||||
return source->hasImage();
|
||||
return cache_.hasImage();
|
||||
|
||||
// handle LinkBack for Mac
|
||||
if (type == LinkBackGraphicsType)
|
||||
@ -377,7 +393,7 @@ bool GuiClipboard::hasGraphicsContents(Clipboard::GraphicsType type) const
|
||||
#endif // Q_WS_MACX
|
||||
|
||||
// get mime data
|
||||
QStringList const & formats = source->formats();
|
||||
QStringList const & formats = cache_.formats();
|
||||
LYXERR(Debug::ACTION, "We found " << formats.size() << " formats");
|
||||
for (int i = 0; i < formats.size(); ++i)
|
||||
LYXERR(Debug::ACTION, "Found format " << formats[i]);
|
||||
@ -391,7 +407,7 @@ bool GuiClipboard::hasGraphicsContents(Clipboard::GraphicsType type) const
|
||||
default: LASSERT(false, /**/);
|
||||
}
|
||||
|
||||
return source && source->hasFormat(mime);
|
||||
return cache_.hasFormat(mime);
|
||||
}
|
||||
|
||||
|
||||
@ -420,9 +436,14 @@ bool GuiClipboard::hasInternal() const
|
||||
|
||||
void GuiClipboard::on_dataChanged()
|
||||
{
|
||||
QMimeData const * const source =
|
||||
qApp->clipboard()->mimeData(QClipboard::Clipboard);
|
||||
QStringList l = source->formats();
|
||||
//Note: we do not really need to run cache_.update() unless the
|
||||
//data has been changed *and* the GuiClipboard has been queried.
|
||||
//However if run cache_.update() the moment a process grabs the
|
||||
//clipboard, the process holding the clipboard presumably won't
|
||||
//yet be frozen, and so we won't need to wait 5 seconds for Qt
|
||||
//to time-out waiting for the clipboard.
|
||||
cache_.update();
|
||||
QStringList l = cache_.formats();
|
||||
LYXERR(Debug::ACTION, "Qt Clipboard changed. We found the following mime types:");
|
||||
for (int i = 0; i < l.count(); i++)
|
||||
LYXERR(Debug::ACTION, l.value(i));
|
||||
|
@ -16,13 +16,43 @@
|
||||
|
||||
#include "frontends/Clipboard.h"
|
||||
|
||||
#include <QMimeData>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
|
||||
namespace lyx {
|
||||
namespace frontend {
|
||||
|
||||
class QMacPasteboardMimeGraphics;
|
||||
|
||||
/**
|
||||
* \class CacheMimeData
|
||||
*
|
||||
* This class is used in order to query the clipboard only once on
|
||||
* startup and once each time the contents of the clipboard changes.
|
||||
*/
|
||||
class CacheMimeData : public QMimeData
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// LyX calls "on_dataChanged" on startup, so it is not necessary to
|
||||
// query the clipboard here.
|
||||
CacheMimeData()
|
||||
{}
|
||||
|
||||
/// reads the clipboard and updates the cached_formats_
|
||||
void update();
|
||||
/// returns the cached list of formats supported by the object
|
||||
virtual QStringList formats() const { return cached_formats_; }
|
||||
/// reads the clipboard and returns the data
|
||||
QByteArray data(QString const & mimeType) const;
|
||||
|
||||
private:
|
||||
/// the cached list of formats supported by the object
|
||||
QStringList cached_formats_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The Qt4 version of the Clipboard.
|
||||
*/
|
||||
@ -57,6 +87,9 @@ private:
|
||||
bool text_clipboard_empty_;
|
||||
bool has_lyx_contents_;
|
||||
bool has_graphics_contents_;
|
||||
/// the cached mime data used to describe the information
|
||||
/// that can be stored in the clipboard
|
||||
CacheMimeData cache_;
|
||||
};
|
||||
|
||||
QString const lyxMimeType();
|
||||
|
Loading…
Reference in New Issue
Block a user