Skip to content

Commit

Permalink
Avoid emitting clipboard change on start
Browse files Browse the repository at this point in the history
  • Loading branch information
hluk committed Nov 26, 2023
1 parent ba200df commit 6ebfa1b
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 19 deletions.
1 change: 0 additions & 1 deletion src/app/clipboardmonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ ClipboardMonitor::ClipboardMonitor(const QStringList &formats)
m_clipboard->setMonitoringEnabled(ClipboardMode::Selection, false);
}
#endif

}

void ClipboardMonitor::startMonitoring()
Expand Down
3 changes: 3 additions & 0 deletions src/app/clipboardserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ ClipboardServer::ClipboardServer(QApplication *app, const QString &sessionName)
loadSettings(&appConfig);
});

setClipboardMonitorRunning(false);
startMonitoring();

callback(QStringLiteral("onStart"));
Expand Down Expand Up @@ -530,6 +531,8 @@ void ClipboardServer::onClientConnectionFailed(ClientSocketId clientId)
void ClipboardServer::onMonitorFinished()
{
COPYQ_LOG("Monitor finished");
if (!m_monitor)
setClipboardMonitorRunning(false);
stopMonitoring();
startMonitoring();
}
Expand Down
2 changes: 0 additions & 2 deletions src/platform/dummy/dummyclipboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ void DummyClipboard::startMonitoring(const QStringList &)
{
connect(QGuiApplication::clipboard(), &QClipboard::changed,
this, &DummyClipboard::onClipboardChanged);

onClipboardChanged(QClipboard::Clipboard);
}

QVariantMap DummyClipboard::data(ClipboardMode mode, const QStringList &formats) const
Expand Down
3 changes: 3 additions & 0 deletions src/platform/mac/macclipboard.mm
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@

void MacClipboard::startMonitoring(const QStringList &formats)
{
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
m_prevChangeCount = [pasteboard changeCount];

auto timer = new MacTimer(this);
timer->setInterval(250);
timer->setTolerance(500);
Expand Down
2 changes: 2 additions & 0 deletions src/platform/win/winplatformclipboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

void WinPlatformClipboard::startMonitoring(const QStringList &formats)
{
m_lastClipboardSequenceNumber = GetClipboardSequenceNumber();

/* Clipboard needs to be checked in intervals since
* the QClipboard::changed() signal is not emitted in some cases on Windows.
*/
Expand Down
21 changes: 17 additions & 4 deletions src/platform/x11/x11platformclipboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,22 @@ void X11PlatformClipboard::startMonitoring(const QStringList &formats)
this, [this](QClipboard::Mode mode){ onClipboardChanged(mode); });
}

// Ignore the initial clipboard content since
// it won't have the correct owner's window title.
m_clipboardData.ignoreNext = true;
m_selectionData.ignoreNext = true;
QTimer::singleShot(5000, this, [this](){
m_clipboardData.ignoreNext = false;
m_selectionData.ignoreNext = false;
});

for (auto clipboardData : {&m_clipboardData, &m_selectionData}) {
clipboardData->owner.clear();
clipboardData->newOwner.clear();
if ( X11Info::isPlatformX11() ) {
updateClipboardData(clipboardData);
useNewClipboardData(clipboardData);
}
}

initSingleShotTimer( &m_timerCheckAgain, 0, this, &X11PlatformClipboard::check );
Expand All @@ -106,9 +119,6 @@ void X11PlatformClipboard::startMonitoring(const QStringList &formats)
m_monitoring = true;

DummyClipboard::startMonitoring(formats);

updateClipboardData(&m_clipboardData);
updateClipboardData(&m_selectionData);
}

void X11PlatformClipboard::setMonitoringEnabled(ClipboardMode mode, bool enable)
Expand Down Expand Up @@ -312,7 +322,10 @@ void X11PlatformClipboard::useNewClipboardData(X11PlatformClipboard::ClipboardDa
clipboardData->data = clipboardData->newData;
clipboardData->owner = clipboardData->newOwner;
clipboardData->timerEmitChange.stop();
emit changed(clipboardData->mode);
if (clipboardData->ignoreNext)
clipboardData->ignoreNext = false;
else
emit changed(clipboardData->mode);
}

void X11PlatformClipboard::checkAgainLater(bool clipboardChanged, int interval)
Expand Down
1 change: 1 addition & 0 deletions src/platform/x11/x11platformclipboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class X11PlatformClipboard final : public DummyClipboard
bool enabled = true;
bool cloningData = false;
bool abortCloning = false;
bool ignoreNext = false;
int retry = 0;
};

Expand Down
7 changes: 7 additions & 0 deletions src/scriptable/scriptable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2810,7 +2810,9 @@ void Scriptable::monitorClipboard()
this, &Scriptable::onSynchronizeSelection );

monitor.startMonitoring();
setClipboardMonitorRunning(true);
loop.exec();
setClipboardMonitorRunning(false);
}

void Scriptable::provideClipboard()
Expand All @@ -2823,6 +2825,11 @@ void Scriptable::provideSelection()
provideClipboard(ClipboardMode::Selection);
}

QJSValue Scriptable::isClipboardMonitorRunning()
{
return ::isClipboardMonitorRunning();
}

QJSValue Scriptable::clipboardFormatsToSave()
{
ItemFactory factory;
Expand Down
1 change: 1 addition & 0 deletions src/scriptable/scriptable.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ public slots:
void monitorClipboard();
void provideClipboard();
void provideSelection();
QJSValue isClipboardMonitorRunning();

QJSValue clipboardFormatsToSave();

Expand Down
19 changes: 19 additions & 0 deletions src/scriptable/scriptableproxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2704,3 +2704,22 @@ QString translationsPath()
{
return platformNativeInterface()->translationPrefix();
}

void setClipboardMonitorRunning(bool running)
{
QSettings settings(
QSettings::IniFormat,
QSettings::UserScope,
QCoreApplication::organizationName(),
QCoreApplication::applicationName() + "-monitor");
settings.setValue(QStringLiteral("running"), running);
}
bool isClipboardMonitorRunning()
{
const QSettings settings(
QSettings::IniFormat,
QSettings::UserScope,
QCoreApplication::organizationName(),
QCoreApplication::applicationName() + "-monitor");
return settings.value(QStringLiteral("running")).toBool();
}
3 changes: 3 additions & 0 deletions src/scriptable/scriptableproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,4 +330,7 @@ QString pluginsPath();
QString themesPath();
QString translationsPath();

void setClipboardMonitorRunning(bool running);
bool isClipboardMonitorRunning();

#endif // SCRIPTABLEPROXY_H
2 changes: 1 addition & 1 deletion src/tests/testinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class TestInterface {
virtual QByteArray waitOnOutput(const QStringList &arguments, const QByteArray &stdoutExpected) = 0;

/// Set clipboard through monitor process.
virtual void setClipboard(const QVariantMap &data, ClipboardMode mode = ClipboardMode::Clipboard) = 0;
virtual QByteArray setClipboard(const QVariantMap &data, ClipboardMode mode = ClipboardMode::Clipboard) = 0;

/// Set clipboard through monitor process.
virtual QByteArray setClipboard(
Expand Down
36 changes: 25 additions & 11 deletions src/tests/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,18 +476,32 @@ class TestInterfaceImpl final : public TestInterface {
return clipboard()->data(mode, QStringList(mime)).value(mime).toByteArray();
}

void setClipboard(const QVariantMap &data, ClipboardMode mode) override
QByteArray setClipboard(const QVariantMap &data, ClipboardMode mode) override
{
waitFor(waitMsSetClipboard);
if ( !data.isEmpty() ) {
// Wait for clipboard monitor
QByteArray error;
SleepTimer t(8000);
do {
error = runClient(
Args("monitoring() == isClipboardMonitorRunning()"),
QByteArrayLiteral("true\n"));
} while (!error.isEmpty() && t.sleep());

if (!error.isEmpty())
return "Clipboard monitor is not running:" + error;
}

clipboard()->setData(mode, data);
return {};
}

QByteArray setClipboard(const QByteArray &bytes, const QString &mime, ClipboardMode mode) override
{
if ( getClipboard(mime, mode) == bytes )
return QByteArray();
const QByteArray error = setClipboard( createDataMap(mime, bytes), mode );
if (!error.isEmpty())
return error;

setClipboard( createDataMap(mime, bytes), mode );
return verifyClipboard(bytes, mime);
}

Expand Down Expand Up @@ -630,9 +644,9 @@ class TestInterfaceImpl final : public TestInterface {
verifyConfiguration();

// Clear clipboard.
RETURN_ON_ERROR( setClipboard(QByteArray(), mimeText, ClipboardMode::Clipboard), "Failed to reset clipboard" );
RETURN_ON_ERROR( setClipboard({}, ClipboardMode::Clipboard), "Failed to reset clipboard" );
#ifdef HAS_MOUSE_SELECTIONS
RETURN_ON_ERROR( setClipboard(QByteArray(), mimeText, ClipboardMode::Selection), "Failed to reset selection" );
RETURN_ON_ERROR( setClipboard({}, ClipboardMode::Selection), "Failed to reset selection" );
#endif

RETURN_ON_ERROR( startServer(), "Failed to initialize server" );
Expand Down Expand Up @@ -2736,6 +2750,7 @@ void Tests::toggleClipboardMonitoring()

RUN("disable", "");
RUN("monitoring", "false\n");
WAIT_ON_OUTPUT("isClipboardMonitorRunning", "false\n");

const QByteArray data2 = generateData();
TEST( m_test->setClipboard(data2) );
Expand All @@ -2744,6 +2759,7 @@ void Tests::toggleClipboardMonitoring()

RUN("enable", "");
RUN("monitoring", "true\n");
WAIT_ON_OUTPUT("isClipboardMonitorRunning", "true\n");

const QByteArray data3 = generateData();
TEST( m_test->setClipboard(data3) );
Expand Down Expand Up @@ -3814,7 +3830,6 @@ void Tests::automaticCommandStoreSpecialFormat()

void Tests::automaticCommandIgnoreSpecialFormat()
{
TEST( m_test->setClipboard("SHOULD BE IGNORED", "test-format") );
const auto script = R"(
setCommands([
{ automatic: true, name: 'CMD1', cmd: 'copyq add CMD1', input: 'test-format', remove: true },
Expand All @@ -3825,6 +3840,7 @@ void Tests::automaticCommandIgnoreSpecialFormat()
RUN(script, "");
WAIT_ON_OUTPUT("commands().length", "3\n");

TEST( m_test->setClipboard("SHOULD BE IGNORED", "test-format") );
WAIT_ON_OUTPUT("separator" << "," << "read" << "0" << "1", "CMD1,");

TEST( m_test->setClipboard("SHOULD NOT BE IGNORED") );
Expand Down Expand Up @@ -4407,8 +4423,6 @@ void Tests::startServerAndRunCommand()

void Tests::avoidStoringPasswords()
{
waitFor(waitMsSetClipboard);

#ifdef Q_OS_WIN
const QString format("application/x-qt-windows-mime;value=\"Clipboard Viewer Ignore\"");
const QByteArray value("");
Expand All @@ -4424,7 +4438,7 @@ void Tests::avoidStoringPasswords()
{format, value},
{mimeText, QByteArrayLiteral("secret")},
};
m_test->setClipboard(data);
TEST( m_test->setClipboard(data) );
waitFor(2 * waitMsPasteClipboard);
RUN("clipboard" << "?", "");
RUN("read" << "0" << "1" << "2", "\n\n");
Expand Down

0 comments on commit 6ebfa1b

Please sign in to comment.