Clipboard sync on new connection
Summary: Added a timestamp to track clipboard changes, so when a new device connects it will sync the most recently updated clipboard to both devices. Reviewers: #kde_connect, albertvaka Reviewed By: #kde_connect, albertvaka Subscribers: albertvaka, sredman, kdeconnect Tags: #kde_connect Differential Revision: https://phabricator.kde.org/D22584
This commit is contained in:
parent
88e0ffa01a
commit
7799973371
5 changed files with 82 additions and 14 deletions
|
@ -38,16 +38,28 @@ void ClipboardListener::updateClipboard(QClipboard::Mode mode)
|
||||||
|
|
||||||
QString content = clipboard->text();
|
QString content = clipboard->text();
|
||||||
|
|
||||||
if (content == currentContent) {
|
if (content == m_currentContent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentContent = content;
|
m_updateTimestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
|
||||||
|
m_currentContent = content;
|
||||||
|
|
||||||
Q_EMIT clipboardChanged(content);
|
Q_EMIT clipboardChanged(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ClipboardListener::currentContent()
|
||||||
|
{
|
||||||
|
return m_currentContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 ClipboardListener::updateTimestamp(){
|
||||||
|
|
||||||
|
return m_updateTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
void ClipboardListener::setText(const QString& content)
|
void ClipboardListener::setText(const QString& content)
|
||||||
{
|
{
|
||||||
currentContent = content;
|
m_updateTimestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
|
||||||
|
m_currentContent = content;
|
||||||
clipboard->setText(content);
|
clipboard->setText(content);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#ifndef CLIPBOARDLISTENER_H
|
#ifndef CLIPBOARDLISTENER_H
|
||||||
#define CLIPBOARDLISTENER_H
|
#define CLIPBOARDLISTENER_H
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
|
@ -35,7 +36,8 @@ class ClipboardListener : public QObject
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClipboardListener();
|
ClipboardListener();
|
||||||
QString currentContent;
|
QString m_currentContent;
|
||||||
|
qint64 m_updateTimestamp = 0;
|
||||||
QClipboard* clipboard;
|
QClipboard* clipboard;
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
QTimer m_clipboardMonitorTimer;
|
QTimer m_clipboardMonitorTimer;
|
||||||
|
@ -56,6 +58,9 @@ public:
|
||||||
|
|
||||||
void setText(const QString& content);
|
void setText(const QString& content);
|
||||||
|
|
||||||
|
QString currentContent();
|
||||||
|
qint64 updateTimestamp();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void clipboardChanged(const QString& content);
|
void clipboardChanged(const QString& content);
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,17 +35,44 @@ ClipboardPlugin::ClipboardPlugin(QObject* parent, const QVariantList& args)
|
||||||
this, &ClipboardPlugin::propagateClipboard);
|
this, &ClipboardPlugin::propagateClipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClipboardPlugin::connected()
|
||||||
|
{
|
||||||
|
sendConnectPacket();
|
||||||
|
}
|
||||||
|
|
||||||
void ClipboardPlugin::propagateClipboard(const QString& content)
|
void ClipboardPlugin::propagateClipboard(const QString& content)
|
||||||
{
|
{
|
||||||
NetworkPacket np(PACKET_TYPE_CLIPBOARD, {{QStringLiteral("content"), content}});
|
NetworkPacket np(PACKET_TYPE_CLIPBOARD, {{QStringLiteral("content"), content}});
|
||||||
sendPacket(np);
|
sendPacket(np);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClipboardPlugin::sendConnectPacket()
|
||||||
|
{
|
||||||
|
NetworkPacket np(PACKET_TYPE_CLIPBOARD_CONNECT, {
|
||||||
|
{QStringLiteral("content"), ClipboardListener::instance()->currentContent()},
|
||||||
|
{QStringLiteral("timestamp"), ClipboardListener::instance()->updateTimestamp()}
|
||||||
|
});
|
||||||
|
sendPacket(np);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ClipboardPlugin::receivePacket(const NetworkPacket& np)
|
bool ClipboardPlugin::receivePacket(const NetworkPacket& np)
|
||||||
{
|
{
|
||||||
QString content = np.get<QString>(QStringLiteral("content"));
|
QString content = np.get<QString>(QStringLiteral("content"));
|
||||||
|
if (np.type() == PACKET_TYPE_CLIPBOARD) {
|
||||||
ClipboardListener::instance()->setText(content);
|
ClipboardListener::instance()->setText(content);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (np.type() == PACKET_TYPE_CLIPBOARD_CONNECT) {
|
||||||
|
qint64 packetTime = np.get<qint64>(QStringLiteral("timestamp"));
|
||||||
|
// If the packetTime is 0, it means the timestamp is unknown (so do nothing).
|
||||||
|
if (packetTime == 0 || packetTime < ClipboardListener::instance()->updateTimestamp()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClipboardListener::instance()->setText(content);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "clipboardplugin.moc"
|
#include "clipboardplugin.moc"
|
||||||
|
|
|
@ -27,8 +27,32 @@
|
||||||
#include <core/kdeconnectplugin.h>
|
#include <core/kdeconnectplugin.h>
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_CLIPBOARD)
|
Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_CLIPBOARD)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packet containing just clipboard contents, sent when a device updates its clipboard.
|
||||||
|
* <p>
|
||||||
|
* The body should look like so:
|
||||||
|
* {
|
||||||
|
* "content": "password"
|
||||||
|
* }
|
||||||
|
*/
|
||||||
#define PACKET_TYPE_CLIPBOARD QStringLiteral("kdeconnect.clipboard")
|
#define PACKET_TYPE_CLIPBOARD QStringLiteral("kdeconnect.clipboard")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packet containing clipboard contents and a timestamp that the contents were last updated, sent
|
||||||
|
* on first connection
|
||||||
|
* <p>
|
||||||
|
* The timestamp is milliseconds since epoch. It can be 0, which indicates that the clipboard
|
||||||
|
* update time is currently unknown.
|
||||||
|
* <p>
|
||||||
|
* The body should look like so:
|
||||||
|
* {
|
||||||
|
* "timestamp": 542904563213,
|
||||||
|
* "content": "password"
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
#define PACKET_TYPE_CLIPBOARD_CONNECT QStringLiteral("kdeconnect.clipboard.connect")
|
||||||
|
|
||||||
class ClipboardPlugin
|
class ClipboardPlugin
|
||||||
: public KdeConnectPlugin
|
: public KdeConnectPlugin
|
||||||
{
|
{
|
||||||
|
@ -38,10 +62,10 @@ public:
|
||||||
explicit ClipboardPlugin(QObject* parent, const QVariantList& args);
|
explicit ClipboardPlugin(QObject* parent, const QVariantList& args);
|
||||||
|
|
||||||
bool receivePacket(const NetworkPacket& np) override;
|
bool receivePacket(const NetworkPacket& np) override;
|
||||||
void connected() override { }
|
void connected() override;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void propagateClipboard(const QString& content);
|
void propagateClipboard(const QString& content);
|
||||||
|
void sendConnectPacket();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -129,9 +129,9 @@
|
||||||
"Website": "https://albertvaka.wordpress.com"
|
"Website": "https://albertvaka.wordpress.com"
|
||||||
},
|
},
|
||||||
"X-KdeConnect-OutgoingPacketType": [
|
"X-KdeConnect-OutgoingPacketType": [
|
||||||
"kdeconnect.clipboard"
|
"kdeconnect.clipboard", "kdeconnect.clipboard.connect"
|
||||||
],
|
],
|
||||||
"X-KdeConnect-SupportedPacketType": [
|
"X-KdeConnect-SupportedPacketType": [
|
||||||
"kdeconnect.clipboard"
|
"kdeconnect.clipboard", "kdeconnect.clipboard.connect"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue