Skip to content

Commit

Permalink
refactor: The Clipboard operations in the Wayland
Browse files Browse the repository at this point in the history
1. 整理所有信号的连接与创建,避免重复连接和内存泄漏的情况。
2. 通过创建一个统一的线程管理机制[服务流机制],管理所有获取
的拷贝和粘贴操作指令。
    其中,用两种不同的服务流来分别管理拷贝和粘贴,拷贝流在
每一次用户操作 Ctrl + c 时都会重新创建,流程执行完毕后自动
退出回收;粘贴流由于执行指令类似,因此将其放在同一个流中进行
后台监听,当用户使用 Ctrl + v 时,不断的向流中放置消息,使
流开始正常工作。
    服务流使用责任链模式实现,每一个服务存在不同的指令,每个
指令在子线程中执行不同的任务,并将结果发送给下一个服务中的指
令,直到服务结束。多个服务串行,形成最终的服务流。
3. 由于窗管对信号中指针的接受,没有进行线程安全的操作,因此
最终实现时增加了较多的线程同步机制,以防止出现野指针

Log:
Influence: Wayland clipboard
  • Loading branch information
Chen Bin committed Sep 23, 2022
1 parent 1002671 commit db682ed
Show file tree
Hide file tree
Showing 15 changed files with 1,244 additions and 150 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ install(TARGETS ${BIN_NAME} DESTINATION bin)
set(BIN_NAME dde-clipboard-daemon)

file(GLOB_RECURSE dde-clipboard-daemon_SCRS
"dde-clipboard-daemon/serviceflow/*.h"
"dde-clipboard-daemon/serviceflow/*.cpp"
"dde-clipboard-daemon/*.h"
"dde-clipboard-daemon/*.cpp"
)
Expand Down
1 change: 0 additions & 1 deletion dde-clipboard-daemon/clipboardloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ ClipboardLoader::ClipboardLoader(QObject *parent)
if (qEnvironmentVariable("XDG_SESSION_TYPE").contains("wayland")) {
#ifdef USE_DEEPIN_KF5_WAYLAND
m_waylandCopyClient = new WaylandCopyClient(this);
m_waylandCopyClient->init();

connect(m_waylandCopyClient, &WaylandCopyClient::dataChanged, this, [this] {
this->doWork(WAYLAND_PROTOCOL);
Expand Down
73 changes: 73 additions & 0 deletions dde-clipboard-daemon/serviceflow/command.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "command.h"
#include "servicetool.h"
#include <QThread>

Command::Command(CommandService *service)
: m_service(service)
{
setAutoDelete(true);
}

void Command::exit()
{
m_isExit = true;
}

Command::State Command::state() const
{
return m_state;
}

CommandService *Command::service() const
{
return m_service;
}

void Command::installMessageExtractor(Extractor *extractor)
{
Q_ASSERT(extractor);
switch (extractor->direction()) {
case Extractor::CommandToTransporter: {
if (m_outEx) {
qWarning("This command already has the out direction Extractor.");
return;
}
m_outEx = extractor;
}
break;
case Extractor::TransporterToCommand: {
if (m_inEx) {
qWarning("This command already has the in direction Extractor.");
return;
}
m_inEx = extractor;
}
break;
}
}

void Command::run()
{
Q_ASSERT(m_inEx);
while (true) {
m_state = Preparing;
CommandMessage *msg = m_inEx->takeFromTransporter();
if (m_isExit) {
delete msg;
break;
}

m_state = Running;
QList<CommandMessage *> destMsgs = doExecute(msg);

// 允许复用同一个 msg 的情况
if (!destMsgs.contains(msg))
delete msg;

if (m_outEx) {
for (auto destMsg : destMsgs)
m_outEx->pushToTransporter(destMsg);
}
}
m_state = Preparing;
}
37 changes: 37 additions & 0 deletions dde-clipboard-daemon/serviceflow/command.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef COMMAND
#define COMMAND

#include <QRunnable>

class CommandService;
class CommandMessage;
class Extractor;
class Command : public QRunnable
{
public:
enum State {
Preparing,
Running
};
Command(CommandService *service = nullptr);

virtual QList<CommandMessage *> doExecute(CommandMessage *) = 0;
virtual QString name() const = 0;

void exit();
State state() const;

CommandService *service() const;
void installMessageExtractor(Extractor *extractor);

private:
void run() override;

Extractor * m_inEx = nullptr;
Extractor * m_outEx = nullptr;
bool m_isExit = false;
State m_state = Preparing;
CommandService *m_service = nullptr;
};

#endif // COMMANDMESSAGE
27 changes: 27 additions & 0 deletions dde-clipboard-daemon/serviceflow/commandmessage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef COMMANDMESSAGE
#define COMMANDMESSAGE

class CommandMessage
{
public:
enum Error {
NoError,
ExecuteError
};

CommandMessage() = default;
virtual ~CommandMessage() {}

inline Error error() const {
return m_error;
}

inline void setError(Error err) {
m_error = err;
}

protected:
Error m_error = NoError;
};

#endif // COMMANDMESSAGE
21 changes: 21 additions & 0 deletions dde-clipboard-daemon/serviceflow/commandservice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "commandservice.h"

CommandService::CommandService()
{

}

CommandService::~CommandService()
{

}

CommandService *CommandService::nextService() const
{
return this->m_nextService;
}

void CommandService::setNextService(CommandService *service)
{
this->m_nextService = service;
}
21 changes: 21 additions & 0 deletions dde-clipboard-daemon/serviceflow/commandservice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef COMMANDSERVICE
#define COMMANDSERVICE

#include "command.h"

class CommandService
{
public:
CommandService();
virtual ~CommandService();

virtual QList<Command *> commands() = 0;

CommandService *nextService() const;
void setNextService(CommandService* service);

private:
CommandService* m_nextService;
};

#endif // COMMANDSERVICE
Loading

0 comments on commit db682ed

Please sign in to comment.