Skip to content

Commit

Permalink
Safer clipboard pasting
Browse files Browse the repository at this point in the history
  • Loading branch information
hluk committed Jun 6, 2018
1 parent bd610ac commit 96052ba
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 54 deletions.
34 changes: 20 additions & 14 deletions src/app/clipboardmanager.cpp
Expand Up @@ -44,9 +44,9 @@ class ClipboardAction {
actionHandler->internalAction(m_act.data());
}

bool wasClipboardSet() const
QPointer<Action> action() const
{
return m_act == nullptr || m_act->data().isEmpty();
return m_act;
}

private:
Expand All @@ -73,11 +73,11 @@ class ClipboardManagerPrivate {
m_selectionAction.provideClipboard(data, m_actionHandler);
}

bool wasClipboardSet(ClipboardMode mode) const
QPointer<Action> action(ClipboardMode mode) const
{
if (mode == ClipboardMode::Clipboard)
return m_clipboardAction.wasClipboardSet();
return m_selectionAction.wasClipboardSet();
return mode == ClipboardMode::Clipboard
? m_clipboardAction.action()
: m_selectionAction.action();
}

private:
Expand Down Expand Up @@ -109,21 +109,25 @@ void ClipboardManager::setClipboard(const QVariantMap &data, ClipboardMode mode)
d->setClipboard(data, mode);
}

void ClipboardManager::waitForClipboardSet()
bool ClipboardManager::waitForClipboardSet()
{
waitForClipboardSet(ClipboardMode::Clipboard);
waitForClipboardSet(ClipboardMode::Selection);
return waitForClipboardSet(ClipboardMode::Clipboard)
&& waitForClipboardSet(ClipboardMode::Selection);
}

void ClipboardManager::waitForClipboardSet(ClipboardMode mode)
bool ClipboardManager::waitForClipboardSet(ClipboardMode mode)
{
#ifndef HAS_MOUSE_SELECTIONS
if (mode == ClipboardMode::Selection)
return;
return true;
#endif

if ( d->wasClipboardSet(mode) )
return;
const auto act = d->action(mode);
const auto completed = [&act] { return act == nullptr || act->data().isEmpty(); };
const auto success = [&act] { return act != nullptr && act->data().isEmpty(); };

if ( completed() )
return success();

QEventLoop loop;

Expand All @@ -135,10 +139,12 @@ void ClipboardManager::waitForClipboardSet(ClipboardMode mode)
QTimer timerCheck;
timerCheck.setInterval(0);
QObject::connect( &timerCheck, &QTimer::timeout, [&]() {
if ( d->wasClipboardSet(mode) )
if ( completed() )
loop.quit();
});
timerCheck.start();

loop.exec();

return success();
}
4 changes: 2 additions & 2 deletions src/app/clipboardmanager.h
Expand Up @@ -37,8 +37,8 @@ class ClipboardManager {

void setClipboard(const QVariantMap &data);
void setClipboard(const QVariantMap &data, ClipboardMode mode);
void waitForClipboardSet();
void waitForClipboardSet(ClipboardMode mode);
bool waitForClipboardSet();
bool waitForClipboardSet(ClipboardMode mode);

private:
std::unique_ptr<ClipboardManagerPrivate> d;
Expand Down
21 changes: 10 additions & 11 deletions src/gui/mainwindow.cpp
Expand Up @@ -1631,12 +1631,13 @@ void MainWindow::activateMenuItem(ClipboardBrowser *c, const QVariantMap &data,
const auto itemHash = ::hash(data);
if ( !c || !c->moveToClipboard(itemHash) )
m_clipboardManager.setClipboard(data);
m_clipboardManager.waitForClipboardSet();

PlatformWindowPtr lastWindow = m_lastWindow;
if ( m_clipboardManager.waitForClipboardSet() ) {
PlatformWindowPtr lastWindow = m_lastWindow;

if ( m_options.trayItemPaste && lastWindow && !omitPaste && canPaste() )
lastWindow->pasteClipboard();
if ( m_options.trayItemPaste && lastWindow && !omitPaste && canPaste() )
lastWindow->pasteClipboard();
}
}

QWidget *MainWindow::toggleMenu(TrayMenu *menu, QPoint pos)
Expand Down Expand Up @@ -2761,13 +2762,13 @@ void MainWindow::setClipboardAndSelection(const QVariantMap &data)
m_clipboardManager.setClipboard(data);
}

void MainWindow::setClipboardAndWait(const QVariantMap &data, ClipboardMode mode)
bool MainWindow::setClipboardAndWait(const QVariantMap &data, ClipboardMode mode)
{
m_clipboardManager.setClipboard(data, mode);
m_clipboardManager.waitForClipboardSet(mode);
return m_clipboardManager.waitForClipboardSet(mode);
}

void MainWindow::moveToClipboard(ClipboardBrowser *c, int row)
bool MainWindow::moveToClipboard(ClipboardBrowser *c, int row)
{
if (c) {
const auto index = c->index(row);
Expand All @@ -2779,7 +2780,7 @@ void MainWindow::moveToClipboard(ClipboardBrowser *c, int row)
m_clipboardManager.setClipboard(QVariantMap());
}

m_clipboardManager.waitForClipboardSet();
return m_clipboardManager.waitForClipboardSet();
}

void MainWindow::activateCurrentItem()
Expand Down Expand Up @@ -2824,9 +2825,7 @@ void MainWindow::activateCurrentItemHelper()

resetStatus();

m_clipboardManager.waitForClipboardSet();

if (paste)
if ( m_clipboardManager.waitForClipboardSet() && paste)
lastWindow->pasteClipboard();
}

Expand Down
4 changes: 2 additions & 2 deletions src/gui/mainwindow.h
Expand Up @@ -360,8 +360,8 @@ public slots:

void setClipboard(const QVariantMap &data, ClipboardMode mode);
void setClipboardAndSelection(const QVariantMap &data);
void setClipboardAndWait(const QVariantMap &data, ClipboardMode mode);
void moveToClipboard(ClipboardBrowser *c, int row);
bool setClipboardAndWait(const QVariantMap &data, ClipboardMode mode);
bool moveToClipboard(ClipboardBrowser *c, int row);

/** Show/hide main window. Return true only if window is shown. */
bool toggleVisible();
Expand Down
30 changes: 13 additions & 17 deletions src/scriptable/scriptable.cpp
Expand Up @@ -96,11 +96,9 @@ QString argumentError()
return Scriptable::tr("Invalid number of arguments!");
}

bool clipboardContains(
ClipboardMode mode, ScriptableProxy *proxy,
const QString &format, const QByteArray &content)
QString clipboardError()
{
return content == proxy->getClipboardData(format, mode);
return Scriptable::tr("Failed to set clipboard!");
}

QByteArray *getByteArray(const QScriptValue &value, const Scriptable *scriptable)
Expand Down Expand Up @@ -552,8 +550,10 @@ class SynchronizeSelectionTimer : public QObject
return;

syncLog("Synchronizing");
m_scriptableProxy->setClipboard(m_data, m_targetClipboardMode);
syncLog("Synchronized");
if ( !m_scriptableProxy->setClipboard(m_data, m_targetClipboardMode) )
syncLog("Synchronized");
else
syncLog("Failed to synchronize");
}

void syncLog(const char *message) const
Expand Down Expand Up @@ -1106,8 +1106,10 @@ void Scriptable::select()
m_skipArguments = 1;
QScriptValue value = argument(0);
int row;
if ( toInt(value, &row) )
m_proxy->browserMoveToClipboard(row);
if ( !toInt(value, &row) )
throwError(argumentError());
else if ( !m_proxy->browserMoveToClipboard(row) )
throwError(clipboardError());
}

void Scriptable::next()
Expand Down Expand Up @@ -2645,17 +2647,11 @@ bool Scriptable::setClipboard(QVariantMap *data, ClipboardMode mode)
data->insert(mime, id);

for (int i = 0; i < setClipboardMaxRetries; ++i) {
m_proxy->setClipboard(*data, mode);

// Wait for clipboard to be set.
for (int j = 0; j < 10; ++j) {
if ( clipboardContains(mode, m_proxy, mime, id) )
return true;
waitFor(5 + i * 20 + j * 10);
}
if ( m_proxy->setClipboard(*data, mode) )
return true;
}

throwError( tr("Failed to set clipboard!") );
throwError(clipboardError());
return false;
}

Expand Down
12 changes: 6 additions & 6 deletions src/scriptable/scriptableproxy.cpp
Expand Up @@ -844,10 +844,10 @@ void ScriptableProxy::disableMonitoring(bool arg1)
m_wnd->disableClipboardStoring(arg1);
}

void ScriptableProxy::setClipboard(const QVariantMap &data, ClipboardMode mode)
bool ScriptableProxy::setClipboard(const QVariantMap &data, ClipboardMode mode)
{
INVOKE2(setClipboard, (data, mode));
m_wnd->setClipboardAndWait(data, mode);
INVOKE(setClipboard, (data, mode));
return m_wnd->setClipboardAndWait(data, mode);
}

QString ScriptableProxy::renameTab(const QString &arg1, const QString &arg2)
Expand Down Expand Up @@ -958,11 +958,11 @@ QVariantMap ScriptableProxy::nextItem(int where)
return c->copyIndex(index);
}

void ScriptableProxy::browserMoveToClipboard(int row)
bool ScriptableProxy::browserMoveToClipboard(int row)
{
INVOKE2(browserMoveToClipboard, (row));
INVOKE(browserMoveToClipboard, (row));
ClipboardBrowser *c = fetchBrowser();
m_wnd->moveToClipboard(c, row);
return m_wnd->moveToClipboard(c, row);
}

void ScriptableProxy::browserSetCurrent(int arg1)
Expand Down
4 changes: 2 additions & 2 deletions src/scriptable/scriptableproxy.h
Expand Up @@ -103,7 +103,7 @@ public slots:
bool isMainWindowVisible();
bool isMainWindowFocused();
void disableMonitoring(bool arg1);
void setClipboard(const QVariantMap &data, ClipboardMode mode);
bool setClipboard(const QVariantMap &data, ClipboardMode mode);

QString renameTab(const QString &arg1, const QString &arg2);

Expand All @@ -127,7 +127,7 @@ public slots:
const NotificationButtons &buttons = NotificationButtons());

QVariantMap nextItem(int where);
void browserMoveToClipboard(int row);
bool browserMoveToClipboard(int row);
void browserSetCurrent(int arg1);
QString browserRemoveRows(QVector<int> rows);

Expand Down

0 comments on commit 96052ba

Please sign in to comment.