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