From 2f4301ad06aa9c1fa85bf3cdeb053ccf41167d06 Mon Sep 17 00:00:00 2001 From: Tezkerek Date: Thu, 9 Apr 2020 15:02:13 +0300 Subject: [PATCH] [CLI] On Unix, copy to clipboard using wl-clipboard if xclip is not available. --- src/cli/Utils.cpp | 61 +++++++++++++++++++++++++++++------------------ tests/TestCli.cpp | 4 ++++ 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/cli/Utils.cpp b/src/cli/Utils.cpp index c20f30ee18..ab7c23186b 100644 --- a/src/cli/Utils.cpp +++ b/src/cli/Utils.cpp @@ -273,48 +273,63 @@ namespace Utils { TextStream err(Utils::STDERR); - QString programName = ""; - QStringList arguments; + // List of programs and their arguments + QList> clipPrograms; #ifdef Q_OS_UNIX - programName = "xclip"; - arguments << "-i" - << "-selection" - << "clipboard"; + if (QProcessEnvironment::systemEnvironment().contains("WAYLAND_DISPLAY")) { + clipPrograms << qMakePair(QStringLiteral("wl-copy"), QStringLiteral("")); + } else { + clipPrograms << qMakePair(QStringLiteral("xclip"), QStringLiteral("-selection clipboard -i")); + } #endif #ifdef Q_OS_MACOS - programName = "pbcopy"; + clipPrograms << qMakePair(QStringLiteral("pbcopy"), QStringLiteral("")); #endif #ifdef Q_OS_WIN - programName = "clip"; + clipPrograms << qMakePair(QStringLiteral("clip"), QStringLiteral("")); #endif - if (programName.isEmpty()) { + if (clipPrograms.isEmpty()) { err << QObject::tr("No program defined for clipboard manipulation"); err.flush(); return EXIT_FAILURE; } - QScopedPointer clipProcess(new QProcess(nullptr)); - clipProcess->start(programName, arguments); - clipProcess->waitForStarted(); + QStringList failedProgramNames; - if (clipProcess->state() != QProcess::Running) { - err << QObject::tr("Unable to start program %1").arg(programName); - err.flush(); - return EXIT_FAILURE; - } + for (auto prog : clipPrograms) { + QScopedPointer clipProcess(new QProcess(nullptr)); + + // Skip empty parts, otherwise the program may clip the empty string + QStringList progArgs = prog.second.split(" ", QString::SkipEmptyParts); - if (clipProcess->write(text.toLatin1()) == -1) { - qDebug("Unable to write to process : %s", qPrintable(clipProcess->errorString())); + clipProcess->start(prog.first, progArgs); + clipProcess->waitForStarted(); + + if (clipProcess->state() != QProcess::Running) { + failedProgramNames.append(prog.first); + continue; + } + + if (clipProcess->write(text.toLatin1()) == -1) { + qDebug("Unable to write to process : %s", qPrintable(clipProcess->errorString())); + } + clipProcess->waitForBytesWritten(); + clipProcess->closeWriteChannel(); + clipProcess->waitForFinished(); + + if (clipProcess->exitCode() == EXIT_SUCCESS) { + return EXIT_SUCCESS; + } } - clipProcess->waitForBytesWritten(); - clipProcess->closeWriteChannel(); - clipProcess->waitForFinished(); - return clipProcess->exitCode(); + // No clipping program worked + err << QObject::tr("All clipping programs failed. Tried %1\n").arg(failedProgramNames.join(", ")); + err.flush(); + return EXIT_FAILURE; } /** diff --git a/tests/TestCli.cpp b/tests/TestCli.cpp index 31e090beec..4ebc2f4e6a 100644 --- a/tests/TestCli.cpp +++ b/tests/TestCli.cpp @@ -473,6 +473,10 @@ void TestCli::testClip() m_stdoutFile->reset(); QString errorOutput(m_stderrFile->readAll()); + if (QProcessEnvironment::systemEnvironment().contains("WAYLAND_DISPLAY")) { + QSKIP("Clip test skipped due to QClipboard and Wayland issues"); + } + if (errorOutput.contains("Unable to start program") || errorOutput.contains("No program defined for clipboard manipulation")) { QSKIP("Clip test skipped due to missing clipboard tool");