Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 18 additions & 24 deletions src/plugin-keyboard/operation/keyboardcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ KeyboardController::KeyboardController(QObject *parent)
connect(m_model, &KeyboardModel::userLayoutChanged, this, &KeyboardController::layoutCountChanged);
connect(m_model, &KeyboardModel::curLayoutChanged, this, &KeyboardController::currentLayoutChanged);
connect(m_model, &KeyboardModel::keyboardEnabledChanged, this, &KeyboardController::keyboardEnabledChanged);
connect(m_worker, &KeyboardWorker::shortcutCommandReady,
this, &KeyboardController::shortcutCommandReady);

connect(m_shortcutModel, &ShortcutModel::keyEvent, this, [this](bool press, const QString &shortcut){
ShortcutInfo *current = m_shortcutModel->currentInfo();
Expand Down Expand Up @@ -282,12 +284,7 @@ QString KeyboardController::checkDesktopCmd(const QString &cmd)
void KeyboardController::addCustomShortcut(const QString &name, const QString &cmd, const QString &accels)
{
if (m_worker->isWayland()) {
// dde-services' Keybinding1 has no AddCustomShortcut yet (the service's
// own CONTROL_CENTER_INTEGRATION.md marks custom-shortcut CRUD as 服务侧需补齐).
// Bail out before any side effect (the conflict Disable below, the
// optimistic model insert in the worker) so the row doesn't flicker.
// TODO: wire up once AddCustomShortcut/ModifyCustomShortcut/DeleteCustomShortcut land.
qWarning() << "[Wayland] addCustomShortcut not yet supported by dde-services; ignoring";
m_worker->addCustomShortcut(name, checkDesktopCmd(cmd), accels);
return;
}

Expand All @@ -303,21 +300,21 @@ void KeyboardController::addCustomShortcut(const QString &name, const QString &c

void KeyboardController::modifyCustomShortcut(const QString &id, const QString &name, const QString &cmd, const QString &accels)
{
if (m_worker->isWayland()) {
// No ModifyCustomShortcut on the Wayland service yet — return before
// mutating the local model or triggering the conflict Disable below,
// so the UI is unchanged rather than showing an edit that won't persist.
// TODO: wire up once dde-services implements custom-shortcut CRUD.
qWarning() << "[Wayland] modifyCustomShortcut not yet supported by dde-services; ignoring";
return;
}

ShortcutInfo *shortcut = m_shortcutModel->findInfoIf([id](ShortcutInfo *info){ return id == info->id; });
if (!shortcut) {
qWarning() << "shortcut not found..." << id << name;
return;
}

if (m_worker->isWayland()) {
ShortcutInfo updated = *shortcut;
updated.name = name;
updated.command = checkDesktopCmd(cmd);
updated.accels = accels;
m_worker->modifyCustomShortcut(&updated);
return;
}

// Clear conflicting shortcuts when modifying
if (auto conflict = m_shortcutModel->getInfo(accels)) {
m_worker->onDisableShortcut(conflict);
Expand All @@ -330,17 +327,14 @@ void KeyboardController::modifyCustomShortcut(const QString &id, const QString &
m_worker->modifyCustomShortcut(shortcut);
}

void KeyboardController::deleteCustomShortcut(const QString &id)
void KeyboardController::requestShortcutCommand(const QString &id)
{
if (m_worker->isWayland()) {
// No DeleteCustomShortcut on the Wayland service yet. Return before
// delShortcut's optimistic delInfo() (which removes + deletes the row);
// otherwise the row would vanish then reappear on the next refresh.
// TODO: wire up once dde-services implements custom-shortcut CRUD.
qWarning() << "[Wayland] deleteCustomShortcut not yet supported by dde-services; ignoring";
return;
}
if (m_worker)
m_worker->requestShortcutCommand(id);
}

void KeyboardController::deleteCustomShortcut(const QString &id)
{
ShortcutInfo *shortcut = m_shortcutModel->findInfoIf([id](ShortcutInfo *info){ return id == info->id; });
if (!shortcut) {
qWarning() << "shortcut not found..." << id;
Expand Down
2 changes: 2 additions & 0 deletions src/plugin-keyboard/operation/keyboardcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public Q_SLOTS:

void addCustomShortcut(const QString &name, const QString &cmd, const QString &accels);
void modifyCustomShortcut(const QString &id, const QString &name, const QString &cmd, const QString &accels);
Q_INVOKABLE void requestShortcutCommand(const QString &id);
void modifyShortcut(const QString &id, const QString &accels, const int &type);
void deleteCustomShortcut(const QString &id);
void clearShortcut(const QString &id, const int &type);
Expand Down Expand Up @@ -130,6 +131,7 @@ public Q_SLOTS:

void waylandKeyCaptureFinished(const QString &id, int type, const QString &accels);
void waylandKeyCaptureFailed(const QString &id, int type, int reason);
void shortcutCommandReady(const QString &id, const QString &command, bool available);

void conflictTextChanged();
void keyboardEnabledChanged();
Expand Down
22 changes: 16 additions & 6 deletions src/plugin-keyboard/operation/keyboarddbusproxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ void KeyboardDBusProxy::onListAllShortcutsNewFinished(QDBusPendingCallWatcher *w
{
QDBusPendingReply<QList<ShortcutInfoNew>> reply = *w;
if (!reply.isError()) {
QString json = convertShortcutListToJson(reply.value());
const QList<ShortcutInfoNew> shortcuts = reply.value();
QString json = convertShortcutListToJson(shortcuts);
Q_EMIT AllShortcutsReady(json);
} else {
qWarning() << "Wayland ListAllShortcuts failed:" << reply.error();
Expand Down Expand Up @@ -354,7 +355,8 @@ void KeyboardDBusProxy::onGetShortcutNewFinished(QDBusPendingCallWatcher *w)
{
QDBusPendingReply<ShortcutInfoNew> reply = *w;
if (!reply.isError()) {
QString json = convertShortcutToJson(reply.value());
const ShortcutInfoNew info = reply.value();
QString json = convertShortcutToJson(info);
Q_EMIT shortcutQueried(json);
}
w->deleteLater();
Expand Down Expand Up @@ -462,27 +464,34 @@ QDBusPendingReply<> KeyboardDBusProxy::AddShortcutKeystroke(const QString &in0,
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("AddShortcutKeystroke"), argumentList);
}

QDBusPendingReply<> KeyboardDBusProxy::AddCustomShortcut(const QString &in0, const QString &in1, const QString &in2)
QDBusPendingReply<QString> KeyboardDBusProxy::AddCustomShortcut(const QString &in0, const QString &in1, const QString &in2)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2);
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("AddCustomShortcut"), argumentList);
}

QDBusPendingReply<> KeyboardDBusProxy::ModifyCustomShortcut(const QString &in0, const QString &in1, const QString &in2, const QString &in3)
QDBusPendingReply<bool> KeyboardDBusProxy::ModifyCustomShortcut(const QString &in0, const QString &in1, const QString &in2, const QString &in3)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2) << QVariant::fromValue(in3);
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("ModifyCustomShortcut"), argumentList);
}

QDBusPendingReply<> KeyboardDBusProxy::DeleteCustomShortcut(const QString &in0)
QDBusPendingReply<bool> KeyboardDBusProxy::DeleteCustomShortcut(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("DeleteCustomShortcut"), argumentList);
}

QDBusPendingReply<QString> KeyboardDBusProxy::GetShortcutCommand(const QString &in0)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(in0);
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("GetShortcutCommand"), argumentList);
}

QDBusPendingReply<> KeyboardDBusProxy::GrabScreen()
{
QList<QVariant> argumentList;
Expand All @@ -505,7 +514,8 @@ void KeyboardDBusProxy::onSearchShortcutsNewFinished(QDBusPendingCallWatcher *w)
{
QDBusPendingReply<QList<ShortcutInfoNew>> reply = *w;
if (!reply.isError()) {
QString json = convertShortcutListToJson(reply.value());
const QList<ShortcutInfoNew> shortcuts = reply.value();
QString json = convertShortcutListToJson(shortcuts);
Q_EMIT searchShortcutsReady(json);
}
w->deleteLater();
Expand Down
7 changes: 4 additions & 3 deletions src/plugin-keyboard/operation/keyboarddbusproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,10 @@ public slots:
QDBusPendingReply<bool> callModifyHotkeys(const QString &id, const QStringList &hotkeys);
// Wayland: replace hotkey — remove newHotkey from conflictId, add to targetId.
QDBusPendingReply<bool> callReplaceHotkey(const QString &targetId, const QString &newHotkey, const QString &conflictId);
QDBusPendingReply<> AddCustomShortcut(const QString &in0, const QString &in1, const QString &in2);
QDBusPendingReply<> ModifyCustomShortcut(const QString &in0, const QString &in1, const QString &in2, const QString &in3);
QDBusPendingReply<> DeleteCustomShortcut(const QString &in0);
QDBusPendingReply<QString> AddCustomShortcut(const QString &in0, const QString &in1, const QString &in2);
QDBusPendingReply<bool> ModifyCustomShortcut(const QString &in0, const QString &in1, const QString &in2, const QString &in3);
QDBusPendingReply<bool> DeleteCustomShortcut(const QString &in0);
QDBusPendingReply<QString> GetShortcutCommand(const QString &in0);
QDBusPendingReply<> GrabScreen();
void SetNumLockState(int in0);
QDBusPendingReply<QString> GetShortcut(const QString &in0, int in1);
Expand Down
132 changes: 125 additions & 7 deletions src/plugin-keyboard/operation/keyboardwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,21 +350,63 @@ void KeyboardWorker::modifyShortcutEdit(ShortcutInfo *info) {

void KeyboardWorker::addCustomShortcut(const QString &name, const QString &command, const QString &accels)
{
m_keyboardDBusProxy->AddCustomShortcut(name, command, accels);
if (!m_keyboardDBusProxy->isWayland()) {
m_keyboardDBusProxy->AddCustomShortcut(name, command, accels);
return;
}

QDBusPendingReply<QString> reply = m_keyboardDBusProxy->AddCustomShortcut(name, command, accels);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
connect(watcher, &QDBusPendingCallWatcher::finished,
this, &KeyboardWorker::onAddCustomShortcutFinished);
}

void KeyboardWorker::callModifyCustomShortcut(const QString &id, const QString &name,
const QString &command, const QString &accels,
int type)
{
QDBusPendingReply<bool> reply = m_keyboardDBusProxy->ModifyCustomShortcut(id, name, command, accels);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
watcher->setProperty("id", id);
watcher->setProperty("type", type);
connect(watcher, &QDBusPendingCallWatcher::finished,
this, &KeyboardWorker::onModifyCustomShortcutFinished);
}

void KeyboardWorker::requestShortcutCommand(const QString &id)
{
ShortcutInfo *shortcut = m_shortcutModel ? m_shortcutModel->findInfoIf([&id](ShortcutInfo *info) {
return info->id == id;
}) : nullptr;
const QString fallbackCommand = shortcut ? shortcut->command : QString();

if (id.isEmpty() || !m_keyboardDBusProxy->isWayland()) {
Q_EMIT shortcutCommandReady(id, fallbackCommand, !id.isEmpty());
return;
}

QDBusPendingReply<QString> reply = m_keyboardDBusProxy->GetShortcutCommand(id);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
watcher->setProperty("id", id);
watcher->setProperty("fallbackCommand", fallbackCommand);
connect(watcher, &QDBusPendingCallWatcher::finished,
this, &KeyboardWorker::onGetShortcutCommandFinished);
}

void KeyboardWorker::modifyCustomShortcut(ShortcutInfo *info)
{
if (m_keyboardDBusProxy->isWayland()) {
callModifyCustomShortcut(info->id, info->name, info->command, info->accels, info->type);
return;
}

if (info->replace) {
onDisableShortcut(info->replace);
}

// reset replace shortcut
info->replace = nullptr;

// Wayland custom-shortcut CRUD is stubbed at the controller layer
// (KeyboardController::modifyCustomShortcut early-returns) until
// dde-services implements ModifyCustomShortcut, so this body is X11-only.
const QString &result = m_keyboardDBusProxy->LookupConflictingShortcut(info->accels);

if (!result.isEmpty()) {
Expand Down Expand Up @@ -408,9 +450,19 @@ QString KeyboardWorker::lookupConflictingShortcut(const QString &key)

void KeyboardWorker::delShortcut(ShortcutInfo* info)
{
m_keyboardDBusProxy->DeleteCustomShortcut(info->id);
if (m_shortcutModel)
m_shortcutModel->delInfo(info);
if (!m_keyboardDBusProxy->isWayland()) {
m_keyboardDBusProxy->DeleteCustomShortcut(info->id);
if (m_shortcutModel)
m_shortcutModel->delInfo(info);
return;
}

QDBusPendingReply<bool> reply = m_keyboardDBusProxy->DeleteCustomShortcut(info->id);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
watcher->setProperty("id", info->id);
watcher->setProperty("type", info->type);
connect(watcher, &QDBusPendingCallWatcher::finished,
this, &KeyboardWorker::onDeleteCustomShortcutFinished);
}

void KeyboardWorker::setRepeatDelay(uint value)
Expand Down Expand Up @@ -931,6 +983,11 @@ void KeyboardWorker::cleanShortcutSlef(const QString &id, const int type, const

void KeyboardWorker::setNewCustomShortcut(const QString &id, const QString &name, const QString &command, const QString &accles)
{
if (m_keyboardDBusProxy->isWayland()) {
callModifyCustomShortcut(id, name, command, accles, ShortcutModel::Custom);
return;
}

m_keyboardDBusProxy->ModifyCustomShortcut(id, name, command, accles);
}

Expand Down Expand Up @@ -1092,6 +1149,67 @@ void KeyboardWorker::onCustomConflictCleanFinished(QDBusPendingCallWatcher *w)
w->deleteLater();
}

void KeyboardWorker::onAddCustomShortcutFinished(QDBusPendingCallWatcher *watch)
{
QDBusPendingReply<QString> reply = *watch;
if (reply.isError() || reply.value().isEmpty()) {
qWarning() << "AddCustomShortcut failed:"
<< (reply.isError() ? reply.error().message() : QStringLiteral("server returned empty id"));
refreshShortcut();
} else {
onAdded(reply.value(), ShortcutModel::Custom);
}

watch->deleteLater();
}

void KeyboardWorker::onModifyCustomShortcutFinished(QDBusPendingCallWatcher *watch)
{
QDBusPendingReply<bool> reply = *watch;
const QString id = watch->property("id").toString();
const int type = watch->property("type").toInt();
const bool success = (!reply.isError() && reply.value());
if (!success) {
qWarning() << "ModifyCustomShortcut failed for" << id
<< (reply.isError() ? reply.error().message() : QStringLiteral("server returned false"));
refreshShortcut();
} else if (!id.isEmpty()) {
onShortcutChanged(id, type);
}

watch->deleteLater();
}

void KeyboardWorker::onDeleteCustomShortcutFinished(QDBusPendingCallWatcher *watch)
{
QDBusPendingReply<bool> reply = *watch;
const QString id = watch->property("id").toString();
const bool success = (!reply.isError() && reply.value());
if (!success) {
qWarning() << "DeleteCustomShortcut failed for" << id
<< (reply.isError() ? reply.error().message() : QStringLiteral("server returned false"));
}
refreshShortcut();

watch->deleteLater();
}

void KeyboardWorker::onGetShortcutCommandFinished(QDBusPendingCallWatcher *watch)
{
QDBusPendingReply<QString> reply = *watch;
const QString id = watch->property("id").toString();
QString command = watch->property("fallbackCommand").toString();

if (reply.isError()) {
qWarning() << "GetShortcutCommand failed for" << id << reply.error().message();
} else {
command = reply.value();
}

Q_EMIT shortcutCommandReady(id, command, !reply.isError() || !command.isEmpty());
watch->deleteLater();
}

QString KeyboardWorker::makeShortcutKey(const QString &id, int type)
{
return id + "_" + QString::number(type);
Expand Down
13 changes: 13 additions & 0 deletions src/plugin-keyboard/operation/keyboardwork.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ class KeyboardWorker : public QObject
void modifyShortcutEdit(ShortcutInfo* info);
void addCustomShortcut(const QString& name, const QString& command, const QString& accels);
void modifyCustomShortcut(ShortcutInfo *info);
void requestShortcutCommand(const QString &id);
// Fire ModifyCustomShortcut on the Wayland service and wire the reply to
// onModifyCustomShortcutFinished. Shared by modifyCustomShortcut (Wayland
// branch) and setNewCustomShortcut so the watcher/id/type setup stays in
// one place.
void callModifyCustomShortcut(const QString &id, const QString &name,
const QString &command, const QString &accels,
int type);

void grabScreen();
bool checkAvaliable(const QString& key);
Expand Down Expand Up @@ -85,6 +93,7 @@ class KeyboardWorker : public QObject
void onLettersChanged(QList<QString> letters);
// 快捷键恢复默认完成
void onResetFinished();
void shortcutCommandReady(const QString &id, const QString &command, bool available);

public Q_SLOTS:
void setLang(const QString &value);
Expand Down Expand Up @@ -122,6 +131,10 @@ public Q_SLOTS:
void onLookupConflictForShortcutFinished(QDBusPendingCallWatcher *watch);
void onShortcutCleanFinished(QDBusPendingCallWatcher *watch);
void onCustomConflictCleanFinished(QDBusPendingCallWatcher *w);
void onAddCustomShortcutFinished(QDBusPendingCallWatcher *watch);
void onModifyCustomShortcutFinished(QDBusPendingCallWatcher *watch);
void onDeleteCustomShortcutFinished(QDBusPendingCallWatcher *watch);
void onGetShortcutCommandFinished(QDBusPendingCallWatcher *watch);

private:
static QString makeShortcutKey(const QString &id, int type);
Expand Down
Loading
Loading