fixed X11 clipboard issues, added support for size limit, added image support for webp/tiff/png/jpg
This commit is contained in:
parent
653e4badeb
commit
c22571658d
|
@ -52,6 +52,7 @@ ServerConfig::ServerConfig(QSettings* settings, int numColumns, int numRows ,
|
|||
m_IgnoreAutoConfigClient(false),
|
||||
m_EnableDragAndDrop(false),
|
||||
m_ClipboardSharing(true),
|
||||
m_ClipboardSharingSize(defaultClipboardSharingSize()),
|
||||
m_pMainWindow(mainWindow)
|
||||
{
|
||||
Q_ASSERT(m_pSettings);
|
||||
|
@ -119,6 +120,7 @@ void ServerConfig::saveSettings()
|
|||
settings().setValue("ignoreAutoConfigClient", ignoreAutoConfigClient());
|
||||
settings().setValue("enableDragAndDrop", enableDragAndDrop());
|
||||
settings().setValue("clipboardSharing", clipboardSharing());
|
||||
settings().setValue("clipboardSharingSize", (int)clipboardSharingSize());
|
||||
|
||||
writeSettings<bool>(settings(), switchCorners(), "switchCorner");
|
||||
|
||||
|
@ -164,6 +166,8 @@ void ServerConfig::loadSettings()
|
|||
setIgnoreAutoConfigClient(settings().value("ignoreAutoConfigClient").toBool());
|
||||
setEnableDragAndDrop(settings().value("enableDragAndDrop", true).toBool());
|
||||
setClipboardSharing(settings().value("clipboardSharing", true).toBool());
|
||||
setClipboardSharingSize(settings().value("clipboardSharingSize",
|
||||
(int) ServerConfig::defaultClipboardSharingSize()).toULongLong());
|
||||
|
||||
readSettings<bool>(settings(), switchCorners(), "switchCorner", false,
|
||||
static_cast<int>(SwitchCorner::Count));
|
||||
|
@ -412,3 +416,18 @@ void::ServerConfig::addToFirstEmptyGrid(const QString &clientName)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t ServerConfig::defaultClipboardSharingSize() {
|
||||
return 100 * 1000 * 1000; // 100 MB
|
||||
}
|
||||
|
||||
size_t ServerConfig::setClipboardSharingSize(size_t size) {
|
||||
if (size) {
|
||||
setClipboardSharing(true);
|
||||
} else {
|
||||
setClipboardSharing(false);
|
||||
}
|
||||
using std::swap;
|
||||
swap (size, m_ClipboardSharingSize);
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ class ServerConfig : public BaseConfig
|
|||
bool ignoreAutoConfigClient() const { return m_IgnoreAutoConfigClient; }
|
||||
bool enableDragAndDrop() const { return m_EnableDragAndDrop; }
|
||||
bool clipboardSharing() const { return m_ClipboardSharing; }
|
||||
size_t clipboardSharingSize() const { return m_ClipboardSharingSize; }
|
||||
static size_t defaultClipboardSharingSize();
|
||||
|
||||
void saveSettings();
|
||||
void loadSettings();
|
||||
|
@ -92,6 +94,7 @@ class ServerConfig : public BaseConfig
|
|||
void setIgnoreAutoConfigClient(bool on) { m_IgnoreAutoConfigClient = on; }
|
||||
void setEnableDragAndDrop(bool on) { m_EnableDragAndDrop = on; }
|
||||
void setClipboardSharing(bool on) { m_ClipboardSharing = on; }
|
||||
size_t setClipboardSharingSize(size_t size);
|
||||
QList<bool>& switchCorners() { return m_SwitchCorners; }
|
||||
std::vector<Hotkey>& hotkeys() { return m_Hotkeys; }
|
||||
|
||||
|
@ -125,6 +128,7 @@ class ServerConfig : public BaseConfig
|
|||
bool m_IgnoreAutoConfigClient;
|
||||
bool m_EnableDragAndDrop;
|
||||
bool m_ClipboardSharing;
|
||||
size_t m_ClipboardSharingSize;
|
||||
MainWindow* m_pMainWindow;
|
||||
};
|
||||
|
||||
|
|
|
@ -59,6 +59,8 @@ ServerConfigDialog::ServerConfigDialog(QWidget* parent, ServerConfig& config, co
|
|||
m_pCheckBoxEnableDragAndDrop->setChecked(serverConfig().enableDragAndDrop());
|
||||
|
||||
m_pCheckBoxEnableClipboard->setChecked(serverConfig().clipboardSharing());
|
||||
m_pSpinBoxClipboardSizeLimit->setValue(serverConfig().clipboardSharingSize());
|
||||
m_pSpinBoxClipboardSizeLimit->setEnabled(serverConfig().clipboardSharing());
|
||||
|
||||
for (const Hotkey& hotkey : serverConfig().hotkeys()) {
|
||||
m_pListHotkeys->addItem(hotkey.text());
|
||||
|
@ -108,6 +110,7 @@ void ServerConfigDialog::accept()
|
|||
serverConfig().setIgnoreAutoConfigClient(m_pCheckBoxIgnoreAutoConfigClient->isChecked());
|
||||
serverConfig().setEnableDragAndDrop(m_pCheckBoxEnableDragAndDrop->isChecked());
|
||||
serverConfig().setClipboardSharing(m_pCheckBoxEnableClipboard->isChecked());
|
||||
serverConfig().setClipboardSharingSize(m_pSpinBoxClipboardSizeLimit->value());
|
||||
|
||||
// now that the dialog has been accepted, copy the new server config to the original one,
|
||||
// which is a reference to the one in MainWindow.
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>795</width>
|
||||
<height>534</height>
|
||||
<width>816</width>
|
||||
<height>580</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -17,7 +17,7 @@
|
|||
<item>
|
||||
<widget class="QTabWidget" name="m_pTabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="m_pTabScreens">
|
||||
<attribute name="title">
|
||||
|
@ -44,7 +44,7 @@
|
|||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="Barrier.qrc">:/res/icons/64x64/user-trash.png</pixmap>
|
||||
<pixmap>:/res/icons/64x64/user-trash.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -82,7 +82,7 @@
|
|||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="Barrier.qrc">:/res/icons/64x64/video-display.png</pixmap>
|
||||
<pixmap>:/res/icons/64x64/video-display.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -422,13 +422,27 @@ Double click on a screen to edit its settings.</string>
|
|||
<string>&Options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxWin32KeepForeground">
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxEnableDragAndDrop">
|
||||
<property name="text">
|
||||
<string>Enable drag and drop file transfers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxIgnoreAutoConfigClient">
|
||||
<property name="text">
|
||||
<string>Ignore auto config clients</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxScreenSaverSync">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Don't take &foreground window on Windows servers</string>
|
||||
<string>S&ynchronize screen savers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -442,13 +456,36 @@ Double click on a screen to edit its settings.</string>
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxScreenSaverSync">
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxWin32KeepForeground">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>S&ynchronize screen savers</string>
|
||||
<string>Don't take &foreground window on Windows servers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxEnableClipboard">
|
||||
<property name="text">
|
||||
<string>Enable clipboard sharing</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -505,41 +542,23 @@ Double click on a screen to edit its settings.</string>
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxEnableDragAndDrop">
|
||||
<property name="text">
|
||||
<string>Enable drag and drop file transfers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxIgnoreAutoConfigClient">
|
||||
<property name="text">
|
||||
<string>Ignore auto config clients</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxEnableClipboard">
|
||||
<property name="text">
|
||||
<string>Enable clipboard sharing</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<item row="8" column="0">
|
||||
<widget class="QSpinBox" name="m_pSpinBoxClipboardSizeLimit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1000000</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000000000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100000000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -59,6 +59,10 @@ public:
|
|||
kText, //!< Text format, UTF-8, newline is LF
|
||||
kHTML, //!< HTML format, HTML fragment, UTF-8, newline is LF
|
||||
kBitmap, //!< Bitmap format, BMP 24/32bpp, BI_RGB
|
||||
kPNG, //!< PNG format
|
||||
kJpeg, //!< JPEG format
|
||||
kTiff, //!< TIFF format
|
||||
kWebp, //!< WEBP format
|
||||
kNumFormats //!< The number of clipboard formats
|
||||
};
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ static const OptionID kOptionScreenPreserveFocus = OPTION_CODE("SFOC")
|
|||
static const OptionID kOptionRelativeMouseMoves = OPTION_CODE("MDLT");
|
||||
static const OptionID kOptionWin32KeepForeground = OPTION_CODE("_KFW");
|
||||
static const OptionID kOptionClipboardSharing = OPTION_CODE("CLPS");
|
||||
static const OptionID kOptionClipboardSharingSize = OPTION_CODE("CLSZ");
|
||||
//@}
|
||||
|
||||
//! @name Screen switch corner enumeration
|
||||
|
|
|
@ -70,7 +70,8 @@ Client::Client(IEventQueue* events, const std::string& name, const NetworkAddres
|
|||
m_socket(NULL),
|
||||
m_useSecureNetwork(args.m_enableCrypto),
|
||||
m_args(args),
|
||||
m_enableClipboard(true)
|
||||
m_enableClipboard(true),
|
||||
m_maximumClipboardSize(INT_MAX)
|
||||
{
|
||||
assert(m_socketFactory != NULL);
|
||||
assert(m_screen != NULL);
|
||||
|
@ -369,8 +370,19 @@ Client::setOptions(const OptionsList& options)
|
|||
m_enableClipboard = *index;
|
||||
|
||||
break;
|
||||
} else if (id == kOptionClipboardSharingSize) {
|
||||
index++;
|
||||
if (index != options.end()) {
|
||||
m_maximumClipboardSize = *index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_enableClipboard && !m_maximumClipboardSize) {
|
||||
m_enableClipboard = false;
|
||||
LOG((CLOG_NOTE "clipboard sharing is disabled because the server "
|
||||
"set the maximum clipboard size to 0"));
|
||||
}
|
||||
|
||||
m_screen->setOptions(options);
|
||||
}
|
||||
|
@ -406,6 +418,12 @@ Client::sendClipboard(ClipboardID id)
|
|||
|
||||
// marshall the data
|
||||
std::string data = clipboard.marshall();
|
||||
if (data.size() >= m_maximumClipboardSize) {
|
||||
LOG((CLOG_NOTE "Skipping clipboard transfer because the clipboard"
|
||||
" contents exceeds the %i MB size limit set by the server",
|
||||
m_maximumClipboardSize));
|
||||
return;
|
||||
}
|
||||
|
||||
// save and send data if different or not yet sent
|
||||
if (!m_sentClipboard[id] || data != m_dataClipboard[id]) {
|
||||
|
@ -660,7 +678,7 @@ Client::handleShapeChanged(const Event&, void*)
|
|||
void
|
||||
Client::handleClipboardGrabbed(const Event& event, void*)
|
||||
{
|
||||
if (!m_enableClipboard) {
|
||||
if (!m_enableClipboard || (m_maximumClipboardSize == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -224,4 +224,5 @@ private:
|
|||
bool m_useSecureNetwork;
|
||||
ClientArgs m_args;
|
||||
bool m_enableClipboard;
|
||||
size_t m_maximumClipboardSize;
|
||||
};
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#include "platform/XWindowsClipboardUTF8Converter.h"
|
||||
#include "platform/XWindowsClipboardHTMLConverter.h"
|
||||
#include "platform/XWindowsClipboardBMPConverter.h"
|
||||
#include "platform/XWindowsClipboardJPGConverter.h"
|
||||
#include "platform/XWindowsClipboardPNGConverter.h"
|
||||
#include "platform/XWindowsClipboardTIFConverter.h"
|
||||
#include "platform/XWindowsClipboardWEBPConverter.h"
|
||||
#include "platform/XWindowsUtil.h"
|
||||
#include "mt/Thread.h"
|
||||
#include "arch/Arch.h"
|
||||
|
@ -82,11 +86,15 @@ XWindowsClipboard::XWindowsClipboard(IXWindowsImpl* impl, Display* display,
|
|||
}
|
||||
|
||||
// add converters, most desired first
|
||||
m_converters.push_back(new XWindowsClipboardPNGConverter(m_display));
|
||||
m_converters.push_back(new XWindowsClipboardWEBPConverter(m_display));
|
||||
m_converters.push_back(new XWindowsClipboardJPGConverter(m_display));
|
||||
m_converters.push_back(new XWindowsClipboardTIFConverter(m_display));
|
||||
m_converters.push_back(new XWindowsClipboardBMPConverter(m_display));
|
||||
m_converters.push_back(new XWindowsClipboardHTMLConverter(m_display,
|
||||
"text/html"));
|
||||
m_converters.push_back(new XWindowsClipboardHTMLConverter(m_display,
|
||||
"application/x-moz-nativehtml"));
|
||||
m_converters.push_back(new XWindowsClipboardBMPConverter(m_display));
|
||||
m_converters.push_back(new XWindowsClipboardUTF8Converter(m_display,
|
||||
"text/plain;charset=UTF-8"));
|
||||
m_converters.push_back(new XWindowsClipboardUTF8Converter(m_display,
|
||||
|
@ -545,31 +553,54 @@ XWindowsClipboard::icccmFillCache()
|
|||
// available rather than checking TARGETS. i've seen clipboard
|
||||
// owners that don't report all the targets they support.
|
||||
target = converter->getAtom();
|
||||
/*
|
||||
#if 0
|
||||
for (UInt32 i = 0; i < numTargets; ++i) {
|
||||
if (converter->getAtom() == targets[i]) {
|
||||
target = targets[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
if (target == None) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the data
|
||||
Atom actualTarget;
|
||||
IClipboard::EFormat format = converter->getFormat();
|
||||
std::string targetData;
|
||||
|
||||
if (!icccmGetSelection(target, &actualTarget, &targetData)) {
|
||||
LOG((CLOG_DEBUG1 " no data for target %s", XWindowsUtil::atomToString(m_display, target).c_str()));
|
||||
m_added[format] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (actualTarget != target) {
|
||||
LOG((CLOG_DEBUG1 " target %s not same as actual target %s",
|
||||
XWindowsUtil::atomToString(m_display, target).c_str(),
|
||||
XWindowsUtil::atomToString(m_display, actualTarget).c_str()));
|
||||
m_added[format] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (targetData.empty()) {
|
||||
m_added[format] = false;
|
||||
LOG((CLOG_DEBUG1 " no targetdata for target %s (actual target %s)",
|
||||
XWindowsUtil::atomToString(m_display, target).c_str(),
|
||||
XWindowsUtil::atomToString(m_display, actualTarget).c_str()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!converter->toIClipboard(targetData).empty()) {
|
||||
// add to clipboard and note we've done it
|
||||
IClipboard::EFormat format = converter->getFormat();
|
||||
m_data[format] = converter->toIClipboard(targetData);
|
||||
m_added[format] = true;
|
||||
LOG((CLOG_DEBUG " added format %d for target %s (%u %s)", format, XWindowsUtil::atomToString(m_display, target).c_str(), targetData.size(), targetData.size() == 1 ? "byte" : "bytes"));
|
||||
} else {
|
||||
LOG((CLOG_DEBUG1 " no clipboard data for target %s", XWindowsUtil::atomToString(m_display, target).c_str()));
|
||||
m_added[format] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -799,17 +830,23 @@ XWindowsClipboard::motifFillCache()
|
|||
|
||||
// get the data (finally)
|
||||
Atom actualTarget;
|
||||
IClipboard::EFormat format = converter->getFormat();
|
||||
std::string targetData;
|
||||
if (!motifGetSelection(&motifFormat, &actualTarget, &targetData)) {
|
||||
LOG((CLOG_DEBUG1 " no data for target %s", XWindowsUtil::atomToString(m_display, target).c_str()));
|
||||
m_added[format] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!converter->toIClipboard(targetData).empty()) {
|
||||
// add to clipboard and note we've done it
|
||||
IClipboard::EFormat format = converter->getFormat();
|
||||
m_data[format] = converter->toIClipboard(targetData);
|
||||
m_added[format] = true;
|
||||
LOG((CLOG_DEBUG "added format %d for target %s", format, XWindowsUtil::atomToString(m_display, target).c_str()));
|
||||
LOG((CLOG_DEBUG " added format %d for target %s (%u %s)", format, XWindowsUtil::atomToString(m_display, target).c_str(), targetData.size(), targetData.size() == 1 ? "byte" : "bytes"));
|
||||
} else {
|
||||
LOG((CLOG_DEBUG1 " no clipboard data for target %s", XWindowsUtil::atomToString(m_display, target).c_str()));
|
||||
m_added[format] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,10 @@ std::string XWindowsClipboardAnyBitmapConverter::fromIClipboard(const std::strin
|
|||
|
||||
std::string XWindowsClipboardAnyBitmapConverter::toIClipboard(const std::string& image) const
|
||||
{
|
||||
if (image.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// convert to raw BMP data
|
||||
UInt32 w, h, depth;
|
||||
std::string rawBMP = doToIClipboard(image, w, h, depth);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "base/Log.h"
|
||||
#include "platform/XWindowsClipboardBMPConverter.h"
|
||||
|
||||
// BMP file header structure
|
||||
|
@ -103,6 +104,11 @@ XWindowsClipboardBMPConverter::getDataSize() const
|
|||
|
||||
std::string XWindowsClipboardBMPConverter::fromIClipboard(const std::string& bmp) const
|
||||
{
|
||||
if (bmp.size() <= 14 + 40) {
|
||||
LOG((CLOG_DEBUG2 "fromIClipboard BMP, sized failed"));
|
||||
return {};
|
||||
}
|
||||
|
||||
// create BMP image
|
||||
UInt8 header[14];
|
||||
UInt8* dst = header;
|
||||
|
@ -128,6 +134,8 @@ std::string XWindowsClipboardBMPConverter::toIClipboard(const std::string& bmp)
|
|||
return {};
|
||||
}
|
||||
|
||||
LOG((CLOG_DEBUG2 "Prepare BMP"));
|
||||
|
||||
// get offset to image data
|
||||
UInt32 offset = fromLEU32(rawBMPHeader + 10);
|
||||
|
||||
|
|
|
@ -61,6 +61,10 @@ std::string XWindowsClipboardHTMLConverter::fromIClipboard(const std::string& da
|
|||
|
||||
std::string XWindowsClipboardHTMLConverter::toIClipboard(const std::string& data) const
|
||||
{
|
||||
if (data.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Older Firefox [1] and possibly other applications use UTF-16 for text/html - handle both
|
||||
// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1497580
|
||||
if (Unicode::isUTF8(data)) {
|
||||
|
|
|
@ -61,6 +61,10 @@ std::string XWindowsClipboardTextConverter::fromIClipboard(const std::string& da
|
|||
|
||||
std::string XWindowsClipboardTextConverter::toIClipboard(const std::string& data) const
|
||||
{
|
||||
if (data.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// convert to UTF-8
|
||||
bool errors;
|
||||
std::string utf8 = Unicode::textToUTF8(data, &errors);
|
||||
|
|
|
@ -61,5 +61,9 @@ std::string XWindowsClipboardUCS2Converter::fromIClipboard(const std::string& da
|
|||
|
||||
std::string XWindowsClipboardUCS2Converter::toIClipboard(const std::string& data) const
|
||||
{
|
||||
if (data.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return Unicode::UCS2ToUTF8(data);
|
||||
}
|
||||
|
|
|
@ -59,5 +59,9 @@ std::string XWindowsClipboardUTF8Converter::fromIClipboard(const std::string& da
|
|||
|
||||
std::string XWindowsClipboardUTF8Converter::toIClipboard(const std::string& data) const
|
||||
{
|
||||
if (data.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -1812,9 +1812,11 @@ XWindowsUtil::ErrorLock::internalHandler(Display* display, XErrorEvent* event)
|
|||
}
|
||||
|
||||
void
|
||||
XWindowsUtil::ErrorLock::ignoreHandler(Display*, XErrorEvent* e, void*)
|
||||
XWindowsUtil::ErrorLock::ignoreHandler(Display* display, XErrorEvent* e, void*)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "ignoring X error: %d", e->error_code));
|
||||
char errtxt[1024];
|
||||
XGetErrorText(display, e->error_code, errtxt, 1023);
|
||||
LOG((CLOG_DEBUG1 "ignoring X error: %d - %.1023s", e->error_code, errtxt));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -744,6 +744,9 @@ Config::readSectionOptions(ConfigReadContext& s)
|
|||
else if (name == "clipboardSharing") {
|
||||
addOption("", kOptionClipboardSharing, s.parseBoolean(value));
|
||||
}
|
||||
else if (name == "clipboardSharingSize") {
|
||||
addOption("", kOptionClipboardSharingSize, s.parseInt(value));
|
||||
}
|
||||
|
||||
else {
|
||||
handled = false;
|
||||
|
@ -1360,6 +1363,9 @@ Config::getOptionName(OptionID id)
|
|||
if (id == kOptionClipboardSharing) {
|
||||
return "clipboardSharing";
|
||||
}
|
||||
if (id == kOptionClipboardSharingSize) {
|
||||
return "clipboardSharingSize";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1376,7 +1382,8 @@ std::string Config::getOptionValue(OptionID id, OptionValue value)
|
|||
id == kOptionRelativeMouseMoves ||
|
||||
id == kOptionWin32KeepForeground ||
|
||||
id == kOptionScreenPreserveFocus ||
|
||||
id == kOptionClipboardSharing) {
|
||||
id == kOptionClipboardSharing ||
|
||||
id == kOptionClipboardSharingSize) {
|
||||
return (value != 0) ? "true" : "false";
|
||||
}
|
||||
if (id == kOptionModifierMapForShift ||
|
||||
|
|
|
@ -90,6 +90,7 @@ Server::Server(
|
|||
m_writeToDropDirThread(NULL),
|
||||
m_ignoreFileTransfer(false),
|
||||
m_enableClipboard(true),
|
||||
m_maximumClipboardSize(INT_MAX),
|
||||
m_sendDragInfoThread(NULL),
|
||||
m_waitDragInfoThread(true),
|
||||
m_args(args)
|
||||
|
@ -511,6 +512,10 @@ Server::switchScreen(BaseClientProxy* dst,
|
|||
if (m_enableClipboard) {
|
||||
// send the clipboard data to new active screen
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
// Hackity hackity hack
|
||||
if (m_clipboards[id].m_clipboard.marshall().size() > m_maximumClipboardSize) {
|
||||
continue;
|
||||
}
|
||||
m_active->setClipboard(id, &m_clipboards[id].m_clipboard);
|
||||
}
|
||||
}
|
||||
|
@ -1177,6 +1182,15 @@ Server::processOptions()
|
|||
LOG((CLOG_NOTE "clipboard sharing is disabled"));
|
||||
}
|
||||
}
|
||||
else if (id == kOptionClipboardSharingSize) {
|
||||
if (value <= 0) {
|
||||
m_maximumClipboardSize = 0;
|
||||
LOG((CLOG_NOTE "clipboard sharing is disabled because the "
|
||||
"maximum shared clipboard size is set to 0"));
|
||||
} else {
|
||||
m_maximumClipboardSize = static_cast<size_t>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_relativeMoves && !newRelativeMoves) {
|
||||
stopRelativeMoves();
|
||||
|
@ -1220,7 +1234,7 @@ Server::handleShapeChanged(const Event&, void* vclient)
|
|||
void
|
||||
Server::handleClipboardGrabbed(const Event& event, void* vclient)
|
||||
{
|
||||
if (!m_enableClipboard) {
|
||||
if (!m_enableClipboard || (m_maximumClipboardSize == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1553,6 +1567,11 @@ Server::onClipboardChanged(BaseClientProxy* sender,
|
|||
|
||||
// ignore if data hasn't changed
|
||||
std::string data = clipboard.m_clipboard.marshall();
|
||||
if (data.size() > m_maximumClipboardSize) {
|
||||
LOG((CLOG_NOTE "not updating clipboard because it's over the size limit (%i KB) configured by the server",
|
||||
m_maximumClipboardSize));
|
||||
return;
|
||||
}
|
||||
if (data == clipboard.m_clipboardData) {
|
||||
LOG((CLOG_DEBUG "ignored screen \"%s\" update of clipboard %d (unchanged)", clipboard.m_clipboardOwner.c_str(), id));
|
||||
return;
|
||||
|
|
|
@ -475,6 +475,7 @@ private:
|
|||
std::string m_dragFileExt;
|
||||
bool m_ignoreFileTransfer;
|
||||
bool m_enableClipboard;
|
||||
size_t m_maximumClipboardSize;
|
||||
|
||||
Thread* m_sendDragInfoThread;
|
||||
bool m_waitDragInfoThread;
|
||||
|
|
Loading…
Reference in New Issue