Skip to content

Commit 3cb1950

Browse files
committed
Plugin: Modify desktop shortcuts in gnome #91
1 parent 8ae3a18 commit 3cb1950

3 files changed

Lines changed: 117 additions & 153 deletions

File tree

Src/Hook.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414
class CHook : public QObject
1515
{
16+
Q_OBJECT
1617
public:
1718
static CHook* GetHook(CParameterPlugin* pPara, QObject *parent = nullptr);
1819

Src/Unix/DesktopShortcuts.cpp

Lines changed: 112 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Author: Kang Lin <kl222@126.com>
22

3+
#include <QRegularExpression>
34
#include <QLoggingCategory>
45
#include <QStandardPaths>
56
#include <QTemporaryDir>
@@ -113,119 +114,76 @@ bool CDesktopShortcutManager::restoreAllShortcuts()
113114

114115
#if defined(Q_OS_LINUX)
115116
// GNOME 快捷键管理
117+
// 设置 -> 键盘 -> 键盘快捷键
116118
bool CDesktopShortcutManager::disableGNOMEShortcuts()
117119
{
118120
qDebug(log) << "Disable GNOME shortcuts ......";
119121

120122
// 备份当前设置
121123
backupGNOMESettings();
122124

123-
// 使用正确的数据结构来存储设置
124-
struct GNOMESetting {
125-
QString schema;
126-
QString key;
127-
QString value;
128-
};
129-
130-
QVector<GNOMESetting> disabledSettings = {
131-
// Super 键
132-
{"org.gnome.mutter", "overlay-key", "''"},
133-
134-
// 窗口管理
135-
{"org.gnome.desktop.wm.keybindings", "close", "['']"},
136-
{"org.gnome.desktop.wm.keybindings", "minimize", "['']"},
137-
{"org.gnome.desktop.wm.keybindings", "maximize", "['']"},
138-
{"org.gnome.desktop.wm.keybindings", "unmaximize", "['']"},
139-
{"org.gnome.desktop.wm.keybindings", "begin-move", "['']"},
140-
{"org.gnome.desktop.wm.keybindings", "begin-resize", "['']"},
141-
{"org.gnome.desktop.wm.keybindings", "toggle-fullscreen", "['']"},
142-
{"org.gnome.desktop.wm.keybindings", "toggle-maximized", "['']"},
143-
{"org.gnome.desktop.wm.keybindings", "show-desktop", "['']"},
144-
145-
// 工作区
146-
{"org.gnome.desktop.wm.keybindings", "switch-to-workspace-left", "['']"},
147-
{"org.gnome.desktop.wm.keybindings", "switch-to-workspace-right", "['']"},
148-
{"org.gnome.desktop.wm.keybindings", "switch-to-workspace-up", "['']"},
149-
{"org.gnome.desktop.wm.keybindings", "switch-to-workspace-down", "['']"},
150-
{"org.gnome.desktop.wm.keybindings", "switch-to-workspace-last", "['']"},
151-
{"org.gnome.desktop.wm.keybindings", "move-to-workspace-left", "['']"},
152-
{"org.gnome.desktop.wm.keybindings", "move-to-workspace-right", "['']"},
153-
{"org.gnome.desktop.wm.keybindings", "move-to-workspace-up", "['']"},
154-
{"org.gnome.desktop.wm.keybindings", "move-to-workspace-down", "['']"},
155-
156-
{"org.gnome.desktop.wm.keybindings", "switch-input-source", "['']"},
157-
{"org.gnome.desktop.wm.keybindings", "switch-input-source-backward", "['']"},
158-
159-
// 面板和 Shell
160-
{"org.gnome.shell.keybindings", "toggle-application-view", "['']"},
161-
{"org.gnome.shell.keybindings", "toggle-message-tray", "['']"},
162-
{"org.gnome.shell.keybindings", "focus-active-notification", "['']"},
163-
{"org.gnome.shell.keybindings", "toggle-overview", "['']"},
164-
165-
{"org.gnome.shell.keybindings", "screenshot", "['']"},
166-
{"org.gnome.shell.keybindings", "screenshot-window", "['']"},
167-
{"org.gnome.shell.keybindings", "show-screenshot-ui", "['']"},
168-
{"org.gnome.shell.keybindings", "show-screen-recording-ui", "['']"},
169-
170-
// 媒体键
171-
{"org.gnome.settings-daemon.plugins.media-keys", "home", "['']"},
172-
{"org.gnome.settings-daemon.plugins.media-keys", "email", "['']"},
173-
{"org.gnome.settings-daemon.plugins.media-keys", "www", "['']"},
174-
{"org.gnome.settings-daemon.plugins.media-keys", "calculator", "['']"},
175-
{"org.gnome.settings-daemon.plugins.media-keys", "screensaver", "['']"},
176-
{"org.gnome.settings-daemon.plugins.media-keys", "media", "['']"},
177-
{"org.gnome.settings-daemon.plugins.media-keys", "volume-up", "['']"},
178-
{"org.gnome.settings-daemon.plugins.media-keys", "volume-down", "['']"},
179-
{"org.gnome.settings-daemon.plugins.media-keys", "volume-mute", "['']"},
180-
{"org.gnome.settings-daemon.plugins.media-keys", "next", "['']"},
181-
{"org.gnome.settings-daemon.plugins.media-keys", "previous", "['']"},
182-
{"org.gnome.settings-daemon.plugins.media-keys", "play", "['']"},
183-
{"org.gnome.settings-daemon.plugins.media-keys", "pause", "['']"},
184-
{"org.gnome.settings-daemon.plugins.media-keys", "stop", "['']"},
185-
186-
// 自定义快捷键
187-
{"org.gnome.settings-daemon.plugins.media-keys", "custom-keybindings", "['']"},
188-
189-
// 其他系统快捷键
190-
{"org.gnome.desktop.wm.keybindings", "panel-main-menu", "['']"},
191-
{"org.gnome.desktop.wm.keybindings", "panel-run-dialog", "['']"},
192-
{"org.gnome.desktop.wm.keybindings", "switch-applications", "['']"},
193-
{"org.gnome.desktop.wm.keybindings", "switch-applications-backward", "['']"},
194-
{"org.gnome.desktop.wm.keybindings", "switch-windows", "['']"},
195-
{"org.gnome.desktop.wm.keybindings", "switch-windows-backward", "['']"},
196-
{"org.gnome.desktop.wm.keybindings", "switch-group", "['']"},
197-
{"org.gnome.desktop.wm.keybindings", "switch-group-backward", "['']"}
198-
199-
};
200-
201-
// 应用设置
202-
bool allSuccess = true;
203-
int successCount = 0;
204-
int totalCount = disabledSettings.size();
205-
206-
for (const GNOMESetting &setting : disabledSettings) {
207-
if (runCommand("gsettings", {"set", setting.schema, setting.key, setting.value})) {
208-
successCount++;
209-
qDebug(log) << "Disabled:" << setting.schema << setting.key;
210-
} else {
211-
qCritical(log) << "Disable fail:" << setting.schema << setting.key;
212-
allSuccess = false;
125+
// 禁止设置
126+
bool bAllSuccess = true;
127+
int nSuccessCount = 0;
128+
int nTotalCount = 0;
129+
for (auto it = m_gnomeSettings.begin(); it != m_gnomeSettings.end(); ++it) {
130+
QString szSchema = it.key();
131+
auto keys = it.value();
132+
for(auto itKey = keys.begin(); itKey != keys.end(); itKey++) {
133+
nTotalCount++;
134+
QString szKey = itKey.key();
135+
QString szValue = itKey.value();
136+
// 是否包含 "[]"
137+
// 方法一:直接判断包含 []
138+
//if(!(szValue.contains('[') && szValue.contains(']'))) continue;
139+
// 方法二:使用正则表达式: \[.*\]
140+
if(!szValue.contains(QRegularExpression("\\[.*\\]"))) continue;
141+
142+
// 去掉 [] 中的内容:
143+
/*
144+
* 方法一:正则表达式写法:
145+
*
146+
* (?<=\[)[^\]]*(?=\])
147+
*
148+
* 说明:
149+
* - (?<=\[) — 正向肯定后顾,匹配在 [ 之后的位置
150+
* - [^\]]* — 匹配任意不是 ] 的字符(0个或多个)
151+
* - (?=\]) — 正向肯定前瞻,匹配在 ] 之前的位置
152+
*
153+
* 这样匹配到的就是括号内的内容,不包括括号本身。
154+
* 注意:QRegularExpression 对前瞻/后顾的支持
155+
* Qt 的 QRegularExpression(基于 PCRE)支持前瞻 (?=) 和后顾 (?<=),所以上面的写法是有效的。
156+
*/
157+
//szValue = szValue.replace(QRegularExpression("(?<=\\[)[^\\]]*(?=\\])"), "");
158+
/* 方法二:使用捕获组
159+
* 正则表达式:
160+
* \[([^\]]*)\]
161+
* 说明:
162+
* |正则 |C++ 字符串|含义 |
163+
* |-------|---------|-------------------|
164+
* |\[ |"\\[" |匹配左方括号 [ |
165+
* |( |"(" |开始捕获组 |
166+
* |[^\]] |"[^\\]]" |匹配任意不是 ] 的字符 |
167+
* |* |"*" |重复 0 次或多次 |
168+
* |) |")" |结束捕获组 |
169+
* |\] |"\\]" |匹配右方括号 ] |
170+
*
171+
* 注意: [^\\]] 在正则中表示字符类 [^]](匹配非 ] 的字符),但在 C++ 字符串中需要对 \ 和 ] 进行转义。
172+
*/
173+
szValue.replace(QRegularExpression("\\[([^\\]]*)\\]"), "[]");
174+
if (runCommand("gsettings", {"set", szSchema, szKey, szValue})) {
175+
nSuccessCount++;
176+
qDebug(log) << "Disabled:" << szSchema + ": " + szKey + " = " + szValue;
177+
} else {
178+
qCritical(log) << "Disabled failed:" << szSchema + ": " + szKey + " = " + szValue;
179+
bAllSuccess = false;
180+
}
213181
}
214182
}
215183

216-
qDebug(log) << QString("GNOME is disabled: %1/%2 Success").arg(successCount).arg(totalCount);
184+
qDebug(log) << QString("GNOME is disabled: %1/%2 Success").arg(nSuccessCount).arg(nTotalCount);
217185

218-
/*/ 重启 GNOME Shell 使设置生效
219-
if (allSuccess || successCount > 0) {
220-
qDebug(log) << "Reboot GNOME Shell ......";
221-
if (runCommand("killall", {"-3", "gnome-shell"})) {
222-
qDebug(log) << "GNOME Shell reboot signal is sended";
223-
} else {
224-
qWarning(log) << "Reboot GNOME Shell fail, Some settings may require you to log in again to take effect.";
225-
}
226-
} //*/
227-
228-
return allSuccess;
186+
return bAllSuccess;
229187
}
230188

231189
bool CDesktopShortcutManager::restoreGNOMEShortcuts()
@@ -237,31 +195,31 @@ bool CDesktopShortcutManager::restoreGNOMEShortcuts()
237195
return false;
238196
}
239197

240-
bool allSuccess = true;
241-
int successCount = 0;
242-
int totalCount = m_gnomeSettings.size();
198+
bool bAllSuccess = true;
199+
int nSuccessCount = 0;
200+
int nTotalCount = 0;
243201

244202
// 恢复备份的设置
245203
for (auto it = m_gnomeSettings.begin(); it != m_gnomeSettings.end(); ++it) {
246-
QStringList parts = it.key().split("|");
247-
if (parts.size() == 2) {
248-
QString schema = parts[0];
249-
QString key = parts[1];
250-
QString value = it.value().toString();
251-
252-
if (runCommand("gsettings", {"set", schema, key, value})) {
253-
successCount++;
254-
qDebug(log) << "Restored:" << schema << key << value;
204+
QString szSchema = it.key();
205+
auto keys = it.value();
206+
for(auto itKey = keys.begin(); itKey != keys.end(); itKey++) {
207+
nTotalCount++;
208+
QString szKey = itKey.key();
209+
QString szValue = itKey.value();
210+
if (runCommand("gsettings", {"set", szSchema, szKey, szValue})) {
211+
nSuccessCount++;
212+
qDebug(log) << "Restored:" << szSchema + ": " + szKey + " = " + szValue;
255213
} else {
256-
qCritical(log) << "Restore failed:" << schema << key << value;
257-
allSuccess = false;
214+
qCritical(log) << "Restore failed:" << szSchema + ": " + szKey + " = " + szValue;
215+
bAllSuccess = false;
258216
}
259217
}
260218
}
261219

262-
qDebug(log) << QString("GNOME shortcut restoration completed: %1/%2 successful").arg(successCount).arg(totalCount);
220+
qDebug(log) << QString("GNOME shortcut restoration completed: %1/%2 successful").arg(nSuccessCount).arg(nTotalCount);
263221

264-
/*/ 重启 GNOME Shell 使设置生效
222+
/* 重启 GNOME Shell 使设置生效。锁屏和注销需要重启才能生效
265223
if (successCount > 0) {
266224
qDebug(log) << "Restart GNOME Shell...";
267225
if (runCommand("killall", {"-3", "gnome-shell"})) {
@@ -271,7 +229,7 @@ bool CDesktopShortcutManager::restoreGNOMEShortcuts()
271229
}
272230
} //*/
273231

274-
return allSuccess;
232+
return bAllSuccess;
275233
}
276234

277235
bool CDesktopShortcutManager::resetGNOMEShortcuts()
@@ -283,30 +241,30 @@ bool CDesktopShortcutManager::resetGNOMEShortcuts()
283241
return false;
284242
}
285243

286-
bool allSuccess = true;
287-
int successCount = 0;
288-
int totalCount = m_gnomeSettings.size();
244+
bool bAllSuccess = true;
245+
int nSuccessCount = 0;
246+
int nTotalCount = 0;
289247

290-
// 恢复备份的设置
248+
// 重置
291249
for (auto it = m_gnomeSettings.begin(); it != m_gnomeSettings.end(); ++it) {
292-
QStringList parts = it.key().split("|");
293-
if (parts.size() == 2) {
294-
QString schema = parts[0];
295-
QString key = parts[1];
296-
297-
if (runCommand("gsettings", {"reset", schema, key})) {
298-
successCount++;
299-
qDebug(log) << "Reset:" << schema << key;
250+
QString szSchema = it.key();
251+
auto keys = it.value();
252+
for(auto itKey = keys.begin(); itKey != keys.end(); itKey++) {
253+
nTotalCount++;
254+
QString szKey = itKey.key();
255+
if (runCommand("gsettings", {"reset", szSchema, szKey})) {
256+
nSuccessCount++;
257+
qDebug(log) << "Reset:" << szSchema + ": " + szKey;
300258
} else {
301-
qCritical(log) << "Reset failed:" << schema << key;
302-
allSuccess = false;
259+
qCritical(log) << "Reset failed:" << szSchema + ": " + szKey;
260+
bAllSuccess = false;
303261
}
304262
}
305263
}
306264

307-
qDebug(log) << QString("GNOME shortcut reset completed: %1/%2 successful").arg(successCount).arg(totalCount);
265+
qDebug(log) << QString("GNOME shortcut reset completed: %1/%2 successful").arg(nSuccessCount).arg(nTotalCount);
308266

309-
/*/ 重启 GNOME Shell 使设置生效
267+
/* 重启 GNOME Shell 使设置生效。锁屏和注销需要重启才能生效
310268
if (successCount > 0) {
311269
qDebug(log) << "Restart GNOME Shell...";
312270
if (runCommand("killall", {"-3", "gnome-shell"})) {
@@ -316,48 +274,50 @@ bool CDesktopShortcutManager::resetGNOMEShortcuts()
316274
}
317275
} //*/
318276

319-
return allSuccess;
277+
return bAllSuccess;
320278
}
321279

322280
void CDesktopShortcutManager::backupGNOMESettings()
323281
{
324282
qDebug(log) << "Backup GNOME settings ......";
283+
int nTotalCount = 0;
284+
QString szDesktop = "." + m_desktopEnv.toLower() + ".";
325285

326286
m_gnomeSettings.clear();
327287

328-
// 重要的 GNOME 设置 schema
329-
QVector<QString> schemas = {
330-
"org.gnome.desktop.wm.keybindings",
331-
"org.gnome.shell.keybindings",
332-
"org.gnome.settings-daemon.plugins.media-keys",
333-
"org.gnome.mutter"
334-
};
335-
336-
for (const QString &schema : schemas) {
288+
// 可以使用下面命令得到 schema
289+
// `gsettings list-schemas|grep keybindings|grep org.gnome.`
290+
QString szSchemas = getCommandOutput("gsettings", {"list-schemas"});
291+
//qDebug(log) << "Schemas:\n" << szSchemas;
292+
QStringList lstSchemas = szSchemas.split('\n', Qt::SkipEmptyParts);
293+
foreach (const QString &schema, lstSchemas) {
294+
if(!schema.contains("keybindings")) continue;
295+
//if(!schema.contains(szDesktop)) continue;
337296
// 获取 schema 的所有键
338297
QString output = getCommandOutput("gsettings", {"list-keys", schema});
339298
if (output.isEmpty()) {
340299
qWarning(log) << "Unable to retrieve the schema key:" << schema;
341300
continue;
342301
}
343302

303+
QMap<QString, QString> vKey;
344304
QStringList keys = output.split('\n', Qt::SkipEmptyParts);
345305
qDebug(log) << QString("Schema %1 has %2 keys").arg(schema).arg(keys.size());
346-
347306
foreach (const QString &key, keys) {
348307
QString value = getCommandOutput("gsettings", {"get", schema, key}).trimmed();
349308
if (!value.isEmpty()) {
350-
// 使用 schema + key 作为唯一标识
351-
QString settingKey = schema + "|" + key;
352-
m_gnomeSettings[settingKey] = value;
353-
qDebug(log) << "Backup:" << settingKey << "=" << value;
309+
nTotalCount++;
310+
vKey.insert(key, value);
311+
qDebug(log) << "Backup:" << schema + ": " + key << "=" << value;
354312
} else {
355-
qWarning(log) << "Backup fail:" << schema + "|" + key;
313+
qWarning(log) << "Backup fail:" << schema + ": " + key;
356314
}
357315
}
316+
if(!vKey.isEmpty())
317+
m_gnomeSettings.insert(schema, vKey);
358318
}
359319

360-
qDebug(log) << QString("GNOME settings backup completed, a total of %1 settings were backed up").arg(m_gnomeSettings.size());
320+
qDebug(log) << QString("GNOME settings backup completed, a total of %1 settings were backed up").arg(nTotalCount);
361321
}
362322

363323
// KDE 快捷键管理

Src/Unix/DesktopShortcuts.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <QFile>
1111
#include <QDir>
1212

13+
/*!
14+
* \brief Manage desktop shortcut keys
15+
*/
1316
class CDesktopShortcutManager : public QObject
1417
{
1518
Q_OBJECT
@@ -36,7 +39,7 @@ class CDesktopShortcutManager : public QObject
3639
bool m_shortcutsDisabled = false;
3740

3841
// 存储原始设置
39-
QMap<QString, QVariant> m_gnomeSettings;
42+
QMap<QString, QMap<QString, QString> > m_gnomeSettings;
4043
QMap<QString, QString> m_kdeSettings;
4144
QString m_gnomeBackupPath;
4245
QString m_kdeBackupPath;

0 commit comments

Comments
 (0)