wayland custom shortcut key

This commit is contained in:
sundagao 2022-08-02 14:29:00 +08:00
parent b6735e2e3a
commit 4f7219cb77
7 changed files with 382 additions and 30 deletions

View File

@ -34,7 +34,7 @@
KeybindingsManager *KeybindingsManager::mKeybinding = nullptr; KeybindingsManager *KeybindingsManager::mKeybinding = nullptr;
KeybindingsManager::KeybindingsManager() KeybindingsManager::KeybindingsManager(QObject *parent) : Manager(parent)
{ {
} }
@ -480,7 +480,7 @@ void KeybindingsManager::get_screens_list (void)
screens->append(screen); screens->append(screen);
} }
bool KeybindingsManager::KeybindingsManagerStart() bool KeybindingsManager::start()
{ {
USD_LOG(LOG_DEBUG,"-- Keybindings Manager Start --"); USD_LOG(LOG_DEBUG,"-- Keybindings Manager Start --");
QList<GdkScreen*>::iterator l, begin, end; QList<GdkScreen*>::iterator l, begin, end;
@ -577,7 +577,7 @@ bool KeybindingsManager::KeybindingsManagerStart()
return true; return true;
} }
void KeybindingsManager::KeybindingsManagerStop() void KeybindingsManager::stop()
{ {
USD_LOG(LOG_DEBUG,"Stopping keybindings manager"); USD_LOG(LOG_DEBUG,"Stopping keybindings manager");

View File

@ -33,6 +33,7 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "manager.h"
@ -59,18 +60,18 @@ typedef struct {
Key previous_key; Key previous_key;
} Binding; } Binding;
class KeybindingsManager : public QObject class KeybindingsManager : public Manager
{ {
Q_OBJECT Q_OBJECT
private: private:
KeybindingsManager(); KeybindingsManager(QObject *parent = nullptr);
KeybindingsManager(KeybindingsManager&)=delete; KeybindingsManager(KeybindingsManager&)=delete;
public: public:
~KeybindingsManager(); ~KeybindingsManager();
static KeybindingsManager *KeybindingsManagerNew(); static KeybindingsManager *KeybindingsManagerNew();
bool KeybindingsManagerStart(); bool start();
void KeybindingsManagerStop(); void stop();
void get_screens_list(); void get_screens_list();
public: public:

View File

@ -20,18 +20,19 @@
#include "clib-syslog.h" #include "clib-syslog.h"
#include "usd_base_class.h" #include "usd_base_class.h"
PluginInterface *KeybindingsPlugin::mInstance=nullptr; PluginInterface *KeybindingsPlugin::mInstance=nullptr;
KeybindingsManager *KeybindingsPlugin::mKeyManager=nullptr; Manager *KeybindingsPlugin::mKeyManager=nullptr;
KeybindingsPlugin::KeybindingsPlugin() KeybindingsPlugin::KeybindingsPlugin()
{ {
if (UsdBaseClass::isWayland()) {
USD_LOG(LOG_DEBUG,"is wayland exit...");
return;
}
USD_LOG(LOG_DEBUG,"KeybindingsPlugin initializing"); USD_LOG(LOG_DEBUG,"KeybindingsPlugin initializing");
if(nullptr == mKeyManager) if(nullptr == mKeyManager) {
if(UsdBaseClass::isWayland()){
//wayland
mKeyManager = KeybindingsWaylandManager::KeybindingsWaylandManagerNew();
} else {
mKeyManager = KeybindingsManager::KeybindingsManagerNew(); mKeyManager = KeybindingsManager::KeybindingsManagerNew();
}
}
} }
KeybindingsPlugin::~KeybindingsPlugin() KeybindingsPlugin::~KeybindingsPlugin()
@ -46,14 +47,10 @@ KeybindingsPlugin::~KeybindingsPlugin()
void KeybindingsPlugin::activate() void KeybindingsPlugin::activate()
{ {
bool res; bool res;
if (UsdBaseClass::isWayland()) {
USD_LOG(LOG_DEBUG,"is wayland exit...");
return;
}
USD_LOG (LOG_DEBUG, "Activating %s plugin compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__); USD_LOG (LOG_DEBUG, "Activating %s plugin compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__);
res = mKeyManager->KeybindingsManagerStart(); res = mKeyManager->start();
if(!res) if(!res)
USD_LOG(LOG_ERR,"Unable to start Keybindings manager"); USD_LOG(LOG_ERR,"Unable to start Keybindings manager");
} }
@ -67,12 +64,8 @@ PluginInterface *KeybindingsPlugin::getInstance()
void KeybindingsPlugin::deactivate() void KeybindingsPlugin::deactivate()
{ {
if (UsdBaseClass::isWayland()) {
USD_LOG(LOG_DEBUG,"is wayland exit...");
return;
}
USD_LOG(LOG_DEBUG,"Dectivating Keybindings Plugin"); USD_LOG(LOG_DEBUG,"Dectivating Keybindings Plugin");
mKeyManager->KeybindingsManagerStop(); mKeyManager->stop();
} }
PluginInterface *createSettingsPlugin() PluginInterface *createSettingsPlugin()

View File

@ -20,6 +20,7 @@
#define KEYBINDINGSPLUGIN_H #define KEYBINDINGSPLUGIN_H
#include "keybindings-manager.h" #include "keybindings-manager.h"
#include "keybindings-wayland-manager.h"
#include "plugin-interface.h" #include "plugin-interface.h"
class KeybindingsPlugin : public PluginInterface class KeybindingsPlugin : public PluginInterface
@ -35,7 +36,7 @@ private:
KeybindingsPlugin(KeybindingsPlugin&)=delete; KeybindingsPlugin(KeybindingsPlugin&)=delete;
private: private:
static KeybindingsManager *mKeyManager; static Manager *mKeyManager;
static PluginInterface *mInstance; static PluginInterface *mInstance;
}; };

View File

@ -0,0 +1,254 @@
/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*-
* -*- coding: utf-8 -*-
*
* Copyright (C) 2020 KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QDebug>
#include <QDir>
#include <QProcess>
#include "keybindings-wayland-manager.h"
#include "clib-syslog.h"
#define GSETTINGS_KEYBINDINGS_DIR "/org/ukui/desktop/keybindings/"
#define CUSTOM_KEYBINDING_SCHEMA "org.ukui.control-center.keybinding"
#define ACTION "action"
#define BINDING "binding"
#define NAME "name"
#define CUSTOM_COMPONET_NAME "usd_keybindings"
KeybindingsWaylandManager *KeybindingsWaylandManager::m_keybinding = nullptr;
KeybindingsWaylandManager::KeybindingsWaylandManager(QObject *parent): Manager (parent)
{
}
KeybindingsWaylandManager::~KeybindingsWaylandManager()
{
if (m_dconfClient) {
dconf_client_unwatch_fast(m_dconfClient, GSETTINGS_KEYBINDINGS_DIR);
dconf_client_unwatch_sync(m_dconfClient, GSETTINGS_KEYBINDINGS_DIR);
g_object_unref (m_dconfClient);
m_dconfClient = nullptr;
}
clearShortcutList();
}
KeybindingsWaylandManager *KeybindingsWaylandManager::KeybindingsWaylandManagerNew()
{
if(nullptr == m_keybinding)
m_keybinding = new KeybindingsWaylandManager();
return m_keybinding;
}
void KeybindingsWaylandManager::bindings_callback (DConfClient *client,
gchar *prefix,
const gchar **changes,
gchar *tag,
KeybindingsWaylandManager *manager)
{
Q_UNUSED(client)
Q_UNUSED(changes)
Q_UNUSED(tag)
if (strncmp(GSETTINGS_KEYBINDINGS_DIR,prefix,strlen(GSETTINGS_KEYBINDINGS_DIR))) {
return;
}
//卸载所有自定义快捷键
manager->unRegisterShortcutAll();
//重新注册已定义的热键
manager->registerShortcutAll();
qDebug()<<prefix;
}
bool KeybindingsWaylandManager::start()
{
USD_LOG(LOG_DEBUG,"-- Keybindings Wayland Manager Start --");
//清除kglobalaceel 的配置
clearKglobalShortcutAll();
registerShortcutAll();
if(!m_dconfClient){
m_dconfClient = dconf_client_new ();
dconf_client_watch_fast (m_dconfClient, GSETTINGS_KEYBINDINGS_DIR);
dconf_client_watch_sync (m_dconfClient, GSETTINGS_KEYBINDINGS_DIR);
g_signal_connect (m_dconfClient, "changed", G_CALLBACK (bindings_callback), this);
}
return true;
}
QStringList KeybindingsWaylandManager::getCustomShortcutPath()
{
int len;
gchar ** childs;
QStringList path;
DConfClient * client = dconf_client_new();
childs = dconf_client_list (client, GSETTINGS_KEYBINDINGS_DIR, &len);
g_object_unref (client);
for (int i = 0; childs[i] != NULL; i++){
if (dconf_is_rel_dir (childs[i], NULL)){
gchar * val = g_strdup (childs[i]);
path<<val;
}
}
g_strfreev (childs);
return path;
}
void KeybindingsWaylandManager::registerShortcutAll()
{
QStringList customPaths = getCustomShortcutPath();
for (QString path : customPaths) {
QString customPath = QString(GSETTINGS_KEYBINDINGS_DIR) + path;
GSettings* settings;
settings = g_settings_new_with_path (CUSTOM_KEYBINDING_SCHEMA, customPath.toLatin1().data());
if(settings){
QString path = customPath;
QString action = QString(g_settings_get_string (settings, ACTION));
QString binding = QString(g_settings_get_string (settings, BINDING));
QString name = QString(g_settings_get_string (settings, NAME));
USD_LOG(LOG_DEBUG,"keybindings name : %s key : %s action : %s",
name.toLocal8Bit().data(),binding.toLatin1().data(),action.toLatin1().data());
ShortCutKeyBind* bind = new ShortCutKeyBind(path,name,binding,action,CUSTOM_COMPONET_NAME);
m_shortcutList.append(bind);
g_object_unref (settings);
}
}
}
void KeybindingsWaylandManager::clearKglobalShortcutAll()
{
QString path = QDir::homePath() + QStringLiteral("/.config/kglobalshortcutsrc");
qDebug()<<path;
QSettings settings(path,QSettings::IniFormat);
settings.beginGroup(CUSTOM_COMPONET_NAME);
QStringList strList = settings.allKeys();
for(QString str : strList){
QStringList list = settings.value(str).toStringList();
if(list.contains("ukui-settings-daemon")){
continue;
}
QAction action;
action.setObjectName(str.toLatin1().data());
action.setProperty("componentName",CUSTOM_COMPONET_NAME);
QList<QKeySequence> seq = QKeySequence::listFromString(list.at(0));
KGlobalAccel::self()->setDefaultShortcut(&action, seq);
KGlobalAccel::self()->setShortcut(&action, seq);
KGlobalAccel::self()->removeAllShortcuts(&action);
}
settings.endGroup();
}
void KeybindingsWaylandManager::unRegisterShortcutAll()
{
if(m_shortcutList.isEmpty()){
return;
}
for(ShortCutKeyBind* bind : m_shortcutList){
KGlobalAccel::self()->removeAllShortcuts(bind->action());
}
qDeleteAll(m_shortcutList);
m_shortcutList.clear();
}
void KeybindingsWaylandManager::clearShortcutList()
{
if(m_shortcutList.isEmpty()){
return;
}
qDeleteAll(m_shortcutList);
m_shortcutList.clear();
}
void KeybindingsWaylandManager::stop()
{
USD_LOG(LOG_DEBUG,"Stopping keybindings manager");
if (m_dconfClient) {
dconf_client_unwatch_fast(m_dconfClient, GSETTINGS_KEYBINDINGS_DIR);
dconf_client_unwatch_sync(m_dconfClient, GSETTINGS_KEYBINDINGS_DIR);
g_object_unref (m_dconfClient);
m_dconfClient = nullptr;
}
clearShortcutList();
}
/*********************ShortCutKeyBind***********************/
ShortCutKeyBind::ShortCutKeyBind(QString settingsPath, QString actionName, QString bindKey, QString execName,QString componetName,QObject* parent)
:m_settingsPath(settingsPath),
m_actionName(actionName),
m_bindKey(bindKey),
m_execName(execName),
m_componentName(componetName),
QObject(parent)
{
m_action = new QAction(this);
m_action->setObjectName(m_actionName);
m_action->setProperty("componentName", m_componentName);
setUp();
}
ShortCutKeyBind::~ShortCutKeyBind()
{
}
void ShortCutKeyBind::setUp()
{
setShortcut();
}
void ShortCutKeyBind::setShortcut()
{
QList<QKeySequence> seq = listFromString();
KGlobalAccel::self()->setDefaultShortcut(m_action, seq);
KGlobalAccel::self()->setShortcut(m_action, seq);
connect(m_action, &QAction::triggered,this,[this]() {
USD_LOG(LOG_DEBUG,"shortcut action name %s",m_execName.toLatin1().data());
parsingDesktop(m_execName);
});
}
QList<QKeySequence> ShortCutKeyBind::listFromString()
{
m_bindKey.replace("<","");
m_bindKey.replace(">","+");
if(m_bindKey.contains("Win")){
m_bindKey.replace("Win","Meta");
}
return QKeySequence::listFromString(m_bindKey);
}
void ShortCutKeyBind::parsingDesktop(QString exec)
{
if(exec.contains("desktop")){
QSettings setting(exec,QSettings::IniFormat);
setting.beginGroup("Desktop Entry");
QString name = setting.value("Name").toString();
QString type = setting.value("Type").toString();
QString exec = setting.value("Exec").toString();
setting.endGroup();
Q_UNUSED(name)
Q_UNUSED(type)
QProcess process;
process.startDetached(exec);
}
}

View File

@ -0,0 +1,101 @@
/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*-
* -*- coding: utf-8 -*-
*
* Copyright (C) 2022 KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEYBINDINGSWAYLANDMANAGER_H
#define KEYBINDINGSWAYLANDsMANAGER_H
#include <QApplication>
#include <QObject>
#include <QTimer>
#include <QGSettings>
#include <QSettings>
#include <manager.h>
#include <QAction>
#include <QKeySequence>
#include <KF5/KGlobalAccel/KGlobalAccel>
extern "C" {
#include <glib.h>
#include <gio/gio.h>
#include <dconf/dconf.h>
#include <dconf/common/dconf-paths.h>
}
class ShortCutKeyBind;
class KeybindingsWaylandManager : public Manager
{
Q_OBJECT
private:
KeybindingsWaylandManager(QObject *parent = nullptr);
KeybindingsWaylandManager(KeybindingsWaylandManager&)=delete;
public:
~KeybindingsWaylandManager();
static KeybindingsWaylandManager *KeybindingsWaylandManagerNew();
bool start();
void stop();
public:
static void bindings_callback (DConfClient *client,
gchar *prefix,
const gchar **changes,
gchar *tag,
KeybindingsWaylandManager *manager);
private:
QStringList getCustomShortcutPath();
void registerShortcutAll();
void unRegisterShortcutAll();
void clearShortcutList();
void clearKglobalShortcutAll();
private:
static KeybindingsWaylandManager *m_keybinding;
DConfClient *m_dconfClient = nullptr;
QList<ShortCutKeyBind*> m_shortcutList;
};
/*************ShortCutKeyBind**************/
class ShortCutKeyBind : public QObject
{
Q_OBJECT
public:
ShortCutKeyBind(QString settingsPath, QString actionName, QString bindKey, QString execName,QString componetName ,QObject *parent = nullptr);
~ShortCutKeyBind();
QString settingPath(){return m_settingsPath;}
QAction* action(){return m_action;}
private:
void setUp();
void setShortcut();
static void parsingDesktop(QString);
QList<QKeySequence> listFromString();
private:
QString m_settingsPath;
QString m_actionName;//名称唯一
QString m_bindKey;//绑定组合键
QString m_execName;//组合键动作
QString m_componentName;//组名称
QAction *m_action;
};
#endif // KEYBINDINGSWAYLANDMANAGER_H

View File

@ -4,12 +4,12 @@
# #
#------------------------------------------------- #-------------------------------------------------
QT -= gui QT -= gui
QT += core widgets x11extras QT += core widgets x11extras KGlobalAccel
TARGET = keybindings TARGET = keybindings
TEMPLATE = lib TEMPLATE = lib
DEFINES += KEYBINDINGS_LIBRARY DEFINES += KEYBINDINGS_LIBRARY
CONFIG += c++11 no_keywords link_pkgconfig plugin CONFIG += c++11 no_keywords link_pkgconfig plugin -lgsettings-qt
DEFINES += QT_DEPRECATED_WARNINGS MODULE_NAME=\\\"keybindings\\\" DEFINES += QT_DEPRECATED_WARNINGS MODULE_NAME=\\\"keybindings\\\"
@ -27,12 +27,14 @@ PKGCONFIG += \
SOURCES += \ SOURCES += \
dconf-util.c \ dconf-util.c \
keybindings-manager.cpp \ keybindings-manager.cpp \
keybindings-plugin.cpp keybindings-plugin.cpp \
keybindings-wayland-manager.cpp
HEADERS += \ HEADERS += \
dconf-util.h \ dconf-util.h \
keybindings-manager.h \ keybindings-manager.h \
keybindings-plugin.h keybindings-plugin.h \
keybindings-wayland-manager.h
keybindings_lib.path = $${PLUGIN_INSTALL_DIRS} keybindings_lib.path = $${PLUGIN_INSTALL_DIRS}