mirror of
https://github.com/Bismuth-Forge/bismuth.git
synced 2024-09-17 11:37:10 +03:00
feat!: register shortcuts in the separate category in the System Settings
This makes the shortcuts appear in the separate category in the System Settings. Note, that we do not delete Action.ts just yet. We need to extract the layouts logic into C++ to do that, since some shortcuts actions depend on the current layout.
This commit is contained in:
parent
b3d4296e92
commit
1a49257180
@ -68,6 +68,7 @@ find_package(
|
||||
I18n
|
||||
KCMUtils
|
||||
Declarative
|
||||
GlobalAccel
|
||||
Config
|
||||
)
|
||||
|
||||
|
@ -12,6 +12,8 @@ target_sources(
|
||||
bismuth_core
|
||||
PRIVATE
|
||||
qml-plugin.cpp
|
||||
ts-proxy.cpp
|
||||
controller.cpp
|
||||
qmldir
|
||||
)
|
||||
|
||||
@ -24,6 +26,7 @@ target_link_libraries(
|
||||
KF5::ConfigCore
|
||||
KF5::ConfigGui
|
||||
KF5::GlobalAccel
|
||||
KF5::I18n
|
||||
)
|
||||
|
||||
target_compile_definitions(
|
||||
|
50
src/core/controller.cpp
Normal file
50
src/core/controller.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
// SPDX-FileCopyrightText: 2022 Mikhail Zolotukhin <mail@genda.life>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "controller.hpp"
|
||||
|
||||
#include <KGlobalAccel>
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Bismuth
|
||||
{
|
||||
|
||||
void Controller::registerAction(const Action &data)
|
||||
{
|
||||
auto action = new QAction(this);
|
||||
action->setProperty("componentName", QStringLiteral("bismuth"));
|
||||
action->setProperty("componentDisplayName", i18n("Window Tiling"));
|
||||
action->setObjectName(data.id);
|
||||
action->setText(data.description);
|
||||
|
||||
// Register the keybinding as the default. This is needed for KCM to
|
||||
// recognize it as such, so that it can properly show whether it is changed
|
||||
// from the default.
|
||||
KGlobalAccel::self()->setDefaultShortcut(action, data.defaultKeybinding);
|
||||
|
||||
// How this function works:
|
||||
// Set the shortcut from the global shortcuts configuration, or set it to
|
||||
// the provided value if it is not found in the config
|
||||
KGlobalAccel::self()->setShortcut(action, data.defaultKeybinding);
|
||||
|
||||
QObject::connect(action, &QAction::triggered, data.callback);
|
||||
|
||||
m_registeredShortcuts.push_back(action);
|
||||
};
|
||||
|
||||
Action::Action(const QString &id, const QString &description, const QString &defaultKeybinding, std::function<void()> callback)
|
||||
{
|
||||
this->id = id;
|
||||
this->description = description;
|
||||
this->defaultKeybinding = {QKeySequence(defaultKeybinding)};
|
||||
this->callback = callback;
|
||||
};
|
||||
|
||||
}
|
36
src/core/controller.hpp
Normal file
36
src/core/controller.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: 2022 Mikhail Zolotukhin <mail@genda.life>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAction>
|
||||
#include <QKeySequence>
|
||||
#include <QList>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace Bismuth
|
||||
{
|
||||
|
||||
struct Action {
|
||||
Action(const QString &id, const QString &description, const QString &defaultKeybinding, std::function<void()> callback);
|
||||
|
||||
QString id;
|
||||
QString description;
|
||||
QList<QKeySequence> defaultKeybinding;
|
||||
std::function<void()> callback;
|
||||
};
|
||||
|
||||
class Controller : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void registerAction(const Action &);
|
||||
|
||||
private:
|
||||
std::vector<QAction *> m_registeredShortcuts{};
|
||||
};
|
||||
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "controller.hpp"
|
||||
#include "plasma-api/plasma-api.hpp"
|
||||
#include "ts-proxy.hpp"
|
||||
|
||||
@ -24,9 +25,10 @@ void CorePlugin::registerTypes(const char *uri)
|
||||
Core::Core(QQuickItem *parent)
|
||||
: QQuickItem(parent)
|
||||
, m_engine() // We cannot get engine from the pointer in the constructor
|
||||
, m_plasmaApi()
|
||||
, m_controller()
|
||||
, m_tsProxy()
|
||||
, m_config(std::make_unique<Bismuth::Config>())
|
||||
, m_plasmaApi()
|
||||
{
|
||||
}
|
||||
|
||||
@ -37,7 +39,8 @@ void Core::init()
|
||||
qDebug() << "[Bismuth] Core QmlEngine ptr: " << m_engine;
|
||||
}
|
||||
m_plasmaApi = std::make_unique<PlasmaApi::PlasmaApi>(m_engine);
|
||||
m_tsProxy = std::make_unique<TSProxy>(m_engine, *m_config);
|
||||
m_controller = std::make_unique<Bismuth::Controller>();
|
||||
m_tsProxy = std::make_unique<TSProxy>(m_engine, *m_controller, *m_config);
|
||||
}
|
||||
|
||||
TSProxy *Core::tsProxy() const
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "controller.hpp"
|
||||
#include "plasma-api/plasma-api.hpp"
|
||||
#include "ts-proxy.hpp"
|
||||
|
||||
@ -45,6 +46,7 @@ public:
|
||||
private:
|
||||
QQmlEngine *m_engine; ///< Pointer to the engine, that is currently using the Core element
|
||||
|
||||
std::unique_ptr<Bismuth::Controller> m_controller; ///< Legacy TS Backend proxy
|
||||
std::unique_ptr<TSProxy> m_tsProxy; ///< Legacy TS Backend proxy
|
||||
std::unique_ptr<Bismuth::Config> m_config;
|
||||
std::unique_ptr<PlasmaApi::PlasmaApi> m_plasmaApi;
|
||||
|
@ -2,11 +2,18 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "ts-proxy.hpp"
|
||||
#include "controller.hpp"
|
||||
|
||||
TSProxy::TSProxy(QQmlEngine *engine, Bismuth::Config &config)
|
||||
#include <KGlobalAccel>
|
||||
#include <KLocalizedString>
|
||||
#include <QAction>
|
||||
#include <QKeySequence>
|
||||
|
||||
TSProxy::TSProxy(QQmlEngine *engine, Bismuth::Controller &controller, Bismuth::Config &config)
|
||||
: QObject()
|
||||
, m_engine(engine)
|
||||
, m_config(config)
|
||||
, m_controller(controller)
|
||||
{
|
||||
}
|
||||
|
||||
@ -98,3 +105,19 @@ QJSValue TSProxy::jsConfig()
|
||||
|
||||
return configJSObject;
|
||||
}
|
||||
|
||||
void TSProxy::registerShortcut(const QJSValue &tsAction)
|
||||
{
|
||||
auto id = tsAction.property("key").toString();
|
||||
auto desk = tsAction.property("description").toString();
|
||||
auto keybinding = tsAction.property("defaultKeybinding").toString();
|
||||
|
||||
qDebug() << "[Bismuth] SK: { id:" << id << ", description:" << desk << ", keybind:" << keybinding << "};";
|
||||
|
||||
// NOTE: Lambda MUST capture by copy, otherwise it is an undefined behavior
|
||||
m_controller.registerAction({id, desk, keybinding, [=]() {
|
||||
auto callback = tsAction.property("execute");
|
||||
qDebug() << "Shortcut triggered! Id:" << id;
|
||||
callback.callWithInstance(tsAction);
|
||||
}});
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "controller.hpp"
|
||||
|
||||
/**
|
||||
* Proxy object for the legacy TS backend.
|
||||
@ -16,14 +17,21 @@ class TSProxy : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TSProxy(QQmlEngine *, Bismuth::Config &);
|
||||
explicit TSProxy(QQmlEngine *, Bismuth::Controller &, Bismuth::Config &);
|
||||
|
||||
/**
|
||||
* Returns the config usable in the legacy TypeScript logic
|
||||
*/
|
||||
Q_INVOKABLE QJSValue jsConfig();
|
||||
|
||||
/**
|
||||
* Register the actions from the legacy backend
|
||||
* @param tsaction
|
||||
*/
|
||||
Q_INVOKABLE void registerShortcut(const QJSValue &);
|
||||
|
||||
private:
|
||||
QQmlEngine *m_engine;
|
||||
Bismuth::Config &m_config;
|
||||
Bismuth::Controller &m_controller;
|
||||
};
|
||||
|
@ -53,10 +53,7 @@ abstract class ActionImpl implements Action {
|
||||
public description: string,
|
||||
public defaultKeybinding: string,
|
||||
protected log: Log
|
||||
) {
|
||||
this.key = `bismuth_${this.key}`;
|
||||
this.description = `Bismuth: ${this.description}`;
|
||||
}
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Action execution pattern. Executes the action override optionally
|
||||
|
@ -14,6 +14,7 @@ import { Config } from "../config";
|
||||
import { Log } from "../util/log";
|
||||
|
||||
import * as Action from "./action";
|
||||
import { TSProxy } from "../extern/proxy";
|
||||
|
||||
/**
|
||||
* Entry point of the script (apart from QML). Handles the user input (shortcuts)
|
||||
@ -161,7 +162,8 @@ export class ControllerImpl implements Controller {
|
||||
private qmlObjects: Bismuth.Qml.Main,
|
||||
kwinApi: KWin.Api,
|
||||
private config: Config,
|
||||
private log: Log
|
||||
private log: Log,
|
||||
private proxy: TSProxy
|
||||
) {
|
||||
this.engine = new EngineImpl(this, config, log);
|
||||
this.driver = new DriverImpl(qmlObjects, kwinApi, this, config, log);
|
||||
@ -441,7 +443,7 @@ export class ControllerImpl implements Controller {
|
||||
];
|
||||
|
||||
for (const action of allPossibleActions) {
|
||||
this.driver.bindShortcut(action);
|
||||
this.proxy.registerShortcut(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import { DriverSurfaceImpl } from "./surface";
|
||||
import { DriverWindowImpl } from "./window";
|
||||
|
||||
import { Controller } from "../controller";
|
||||
import { Action } from "../controller/action";
|
||||
|
||||
import { EngineWindow, EngineWindowImpl } from "../engine/window";
|
||||
|
||||
@ -50,12 +49,6 @@ export interface Driver {
|
||||
*/
|
||||
bindEvents(): void;
|
||||
|
||||
/**
|
||||
* Bind the shortcut for the action
|
||||
* @param action
|
||||
*/
|
||||
bindShortcut(action: Action): void;
|
||||
|
||||
/**
|
||||
* Manage the windows, that were active before script loading
|
||||
*/
|
||||
@ -321,17 +314,6 @@ export class DriverImpl implements Driver {
|
||||
this.qml.popupDialog.show(text, icon, hint);
|
||||
}
|
||||
|
||||
public bindShortcut(action: Action): void {
|
||||
this.kwinApi.KWin.registerShortcut(
|
||||
action.key,
|
||||
action.description,
|
||||
action.defaultKeybinding,
|
||||
(): void => {
|
||||
this.enter(() => action.execute());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public drop(): void {
|
||||
this.log.log(`Dropping all registered callbacks... Goodbye.`);
|
||||
for (const pair of this.registeredConnections) {
|
||||
|
@ -328,7 +328,7 @@ export class EngineWindowImpl implements EngineWindow {
|
||||
|
||||
public commit(): void {
|
||||
const state = this.state;
|
||||
this.log.log(["Window#commit", { state: WindowState[state] }]);
|
||||
// this.log.log(["Window#commit", { state: WindowState[state] }]);
|
||||
switch (state) {
|
||||
case WindowState.NativeMaximized:
|
||||
this.window.commit(
|
||||
|
10
src/kwinscript/extern/proxy.d.ts
vendored
Normal file
10
src/kwinscript/extern/proxy.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// SPDX-FileCopyrightText: 2022 Mikhail Zolotukhin <mail@genda.life>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Config } from "../config";
|
||||
import { Action } from "../controller/action";
|
||||
|
||||
export interface TSProxy {
|
||||
jsConfig(): Config;
|
||||
registerShortcut(data: Action): void;
|
||||
}
|
@ -2,14 +2,10 @@
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Config } from "./config";
|
||||
import { Controller, ControllerImpl } from "./controller";
|
||||
import { TSProxy } from "./extern/proxy";
|
||||
import { LogImpl } from "./util/log";
|
||||
|
||||
interface TSProxy {
|
||||
jsConfig(): Config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Script entry-point from QML side.
|
||||
* @param qmlObjects objects from QML gui. Required for the interaction with QML, as we cannot access globals.
|
||||
@ -30,7 +26,8 @@ export function init(
|
||||
qmlObjects,
|
||||
kwinScriptingApi,
|
||||
config,
|
||||
logger
|
||||
logger,
|
||||
proxy
|
||||
);
|
||||
|
||||
controller.start();
|
||||
|
Loading…
Reference in New Issue
Block a user