refactor: wrap clientArea workspace method

This commit is contained in:
Mikhail Zolotukhin 2022-03-21 15:36:10 +03:00 committed by Genda
parent 75dd01e024
commit 23eb425181
11 changed files with 105 additions and 28 deletions

View File

@ -16,3 +16,22 @@
{ \ { \
m_kwinImpl->setProperty(#NAME, QVariant::fromValue(value)); \ m_kwinImpl->setProperty(#NAME, QVariant::fromValue(value)); \
} }
/**
* Wrap QML API method
*
* @param RET_TYPE return type of a method
* @param SIGNATURE method signature, that consists of method name (without
* object association) and arguments types. Constness is not needed!
*/
#define BI_METHOD_IMPL_WRAP(RET_TYPE, SIGNATURE, ...) \
{ \
auto implMeta = m_kwinImpl->metaObject(); \
/* Signature must not contain return value and cost status*/ \
auto normSignature = QMetaObject::normalizedSignature(SIGNATURE); \
auto methodIndex = implMeta->indexOfMethod(normSignature); \
auto method = implMeta->method(methodIndex); \
auto result = RET_TYPE(); \
method.invoke(m_kwinImpl, Qt::DirectConnection, Q_RETURN_ARG(RET_TYPE, result), __VA_ARGS__); \
return result; \
}

View File

@ -44,6 +44,11 @@ void Workspace::wrapSignals()
wrapComplexSignal(SIGNAL(currentDesktopChanged(int, KWin::AbstractClient *)), SLOT(currentDesktopChangedTransformer(int, KWin::AbstractClient *))); wrapComplexSignal(SIGNAL(currentDesktopChanged(int, KWin::AbstractClient *)), SLOT(currentDesktopChangedTransformer(int, KWin::AbstractClient *)));
}; };
QRect Workspace::clientArea(ClientAreaOption option, int screen, int desktop)
{
BI_METHOD_IMPL_WRAP(QRect, "clientArea(ClientAreaOption, int, int)", Q_ARG(ClientAreaOption, option), Q_ARG(int, screen), Q_ARG(int, desktop));
};
void Workspace::currentDesktopChangedTransformer(int desktop, KWin::AbstractClient *kwinClient) void Workspace::currentDesktopChangedTransformer(int desktop, KWin::AbstractClient *kwinClient)
{ {
// Since we don't know the KWin internal implementation we have to use reinterpret_cast // Since we don't know the KWin internal implementation we have to use reinterpret_cast

View File

@ -22,12 +22,36 @@ class Workspace : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
enum ClientAreaOption {
PlacementArea, // Geometry where a window will be initially placed after being mapped
MovementArea, // Window movement snapping area? Ignore struts
MaximizeArea, // Geometry to which a window will be maximized
MaximizeFullArea, // Like MaximizeArea, but ignore struts
FullScreenArea, // Area for fullscreen windows
WorkArea, // Whole workarea (all screens together)
FullArea, // Whole area (all screens together), ignore struts
ScreenArea, // One whole screen, ignore struts
};
Q_ENUM(ClientAreaOption)
Workspace(QQmlEngine *engine); Workspace(QQmlEngine *engine);
Workspace(const Workspace &); Workspace(const Workspace &);
BI_PROPERTY(int, currentDesktop, setCurrentDesktop); BI_PROPERTY(int, currentDesktop, setCurrentDesktop);
public Q_SLOTS: /**
* Returns the geometry a Client can use with the specified option.
* This method should be preferred over other methods providing screen sizes as the
* various options take constraints such as struts set on panels into account.
* This method is also multi screen aware, but there are also options to get full areas.
* @param option The type of area which should be considered
* @param screen The screen for which the area should be considered
* @param desktop The desktop for which the area should be considered, in general there should not be a difference
* @returns The specified screen geometry
*/
Q_INVOKABLE QRect clientArea(ClientAreaOption, int screen, int desktop);
private Q_SLOTS:
void currentDesktopChangedTransformer(int desktop, KWin::AbstractClient *kwinClient); void currentDesktopChangedTransformer(int desktop, KWin::AbstractClient *kwinClient);
Q_SIGNALS: Q_SIGNALS:

View File

@ -42,10 +42,9 @@ void Core::init()
{ {
m_config = std::make_unique<Bismuth::Config>(); m_config = std::make_unique<Bismuth::Config>();
m_engine = qmlEngine(this); m_engine = qmlEngine(this);
qDebug(Bi) << "Core QmlEngine ptr: " << m_engine;
m_controller = std::make_unique<Bismuth::Controller>(); m_controller = std::make_unique<Bismuth::Controller>();
m_plasmaApi = std::make_unique<PlasmaApi::PlasmaApi>(m_engine); m_plasmaApi = std::make_unique<PlasmaApi::PlasmaApi>(m_engine);
m_tsProxy = std::make_unique<TSProxy>(m_engine, *m_controller, *m_config); m_tsProxy = std::make_unique<TSProxy>(m_engine, *m_controller, *m_plasmaApi, *m_config);
} }
TSProxy *Core::tsProxy() const TSProxy *Core::tsProxy() const

View File

@ -10,12 +10,14 @@
#include "controller.hpp" #include "controller.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "plasma-api/plasma-api.hpp"
TSProxy::TSProxy(QQmlEngine *engine, Bismuth::Controller &controller, Bismuth::Config &config) TSProxy::TSProxy(QQmlEngine *engine, Bismuth::Controller &controller, PlasmaApi::PlasmaApi &plasmaApi, Bismuth::Config &config)
: QObject() : QObject()
, m_engine(engine) , m_engine(engine)
, m_config(config) , m_config(config)
, m_controller(controller) , m_controller(controller)
, m_plasmaApi(plasmaApi)
{ {
} }
@ -107,6 +109,14 @@ QJSValue TSProxy::jsConfig()
return configJSObject; return configJSObject;
} }
QJSValue TSProxy::workspace()
{
auto &workspace = m_plasmaApi.workspace();
auto jsValue = m_engine->newQObject(&workspace);
QQmlEngine::setObjectOwnership(&workspace, QQmlEngine::CppOwnership);
return jsValue;
}
void TSProxy::registerShortcut(const QJSValue &tsAction) void TSProxy::registerShortcut(const QJSValue &tsAction)
{ {
auto id = tsAction.property("key").toString(); auto id = tsAction.property("key").toString();

View File

@ -9,6 +9,7 @@
#include "config.hpp" #include "config.hpp"
#include "controller.hpp" #include "controller.hpp"
#include "plasma-api/plasma-api.hpp"
/** /**
* Proxy object for the legacy TS backend. * Proxy object for the legacy TS backend.
@ -17,13 +18,18 @@ class TSProxy : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TSProxy(QQmlEngine *, Bismuth::Controller &, Bismuth::Config &); TSProxy(QQmlEngine *, Bismuth::Controller &, PlasmaApi::PlasmaApi &, Bismuth::Config &);
/** /**
* Returns the config usable in the legacy TypeScript logic * Returns the config usable in the legacy TypeScript logic
*/ */
Q_INVOKABLE QJSValue jsConfig(); Q_INVOKABLE QJSValue jsConfig();
/**
* Returns the workspace instance
*/
Q_INVOKABLE QJSValue workspace();
/** /**
* Register the actions from the legacy backend * Register the actions from the legacy backend
* @param tsaction * @param tsaction
@ -39,4 +45,5 @@ private:
QQmlEngine *m_engine; QQmlEngine *m_engine;
Bismuth::Config &m_config; Bismuth::Config &m_config;
Bismuth::Controller &m_controller; Bismuth::Controller &m_controller;
PlasmaApi::PlasmaApi &m_plasmaApi;
}; };

View File

@ -159,14 +159,14 @@ export class ControllerImpl implements Controller {
private engine: Engine; private engine: Engine;
private driver: Driver; private driver: Driver;
public constructor( public constructor(
private qmlObjects: Bismuth.Qml.Main, qmlObjects: Bismuth.Qml.Main,
kwinApi: KWin.Api, kwinApi: KWin.Api,
private config: Config, private config: Config,
private log: Log, private log: Log,
private proxy: TSProxy private proxy: TSProxy
) { ) {
this.engine = new EngineImpl(this, config, log); this.engine = new EngineImpl(this, config, log);
this.driver = new DriverImpl(qmlObjects, kwinApi, this, config, log); this.driver = new DriverImpl(qmlObjects, kwinApi, this, config, log, proxy);
} }
/** /**

View File

@ -15,6 +15,7 @@ import { WindowState } from "../engine/window";
import { Config } from "../config"; import { Config } from "../config";
import { Log } from "../util/log"; import { Log } from "../util/log";
import { TSProxy } from "../extern/proxy";
/** /**
* Provides convenient interface to KWin functions. * Provides convenient interface to KWin functions.
@ -70,7 +71,8 @@ export class DriverImpl implements Driver {
this.kwinApi.workspace.currentDesktop, this.kwinApi.workspace.currentDesktop,
this.qml.activityInfo, this.qml.activityInfo,
this.kwinApi, this.kwinApi,
this.config this.config,
this.proxy
); );
} }
@ -109,7 +111,8 @@ export class DriverImpl implements Driver {
this.kwinApi.workspace.currentDesktop, this.kwinApi.workspace.currentDesktop,
this.qml.activityInfo, this.qml.activityInfo,
this.kwinApi, this.kwinApi,
this.config this.config,
this.proxy
) )
); );
} }
@ -135,7 +138,8 @@ export class DriverImpl implements Driver {
kwinApi: KWin.Api, kwinApi: KWin.Api,
controller: Controller, controller: Controller,
private config: Config, private config: Config,
private log: Log private log: Log,
private proxy: TSProxy
) { ) {
this.registeredConnections = []; this.registeredConnections = [];
@ -155,7 +159,8 @@ export class DriverImpl implements Driver {
this.qml, this.qml,
this.kwinApi, this.kwinApi,
this.config, this.config,
this.log this.log,
this.proxy
), ),
this.config, this.config,
this.log this.log
@ -178,7 +183,8 @@ export class DriverImpl implements Driver {
this.kwinApi.workspace.currentDesktop, this.kwinApi.workspace.currentDesktop,
this.qml.activityInfo, this.qml.activityInfo,
this.kwinApi, this.kwinApi,
this.config this.config,
this.proxy
); );
this.controller.onSurfaceUpdate("resized " + srf.toString()); this.controller.onSurfaceUpdate("resized " + srf.toString());
}; };
@ -365,8 +371,8 @@ export class DriverImpl implements Driver {
try { try {
callback(); callback();
} catch (e: any) { } catch (e: any) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
this.log.log(e); this.log.log(`Oops! ${e.name}: ${e.message}. `);
} finally { } finally {
this.entered = false; this.entered = false;
} }

View File

@ -4,6 +4,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { Config } from "../config"; import { Config } from "../config";
import { TSProxy } from "../extern/proxy";
import { Rect } from "../util/rect"; import { Rect } from "../util/rect";
/** /**
@ -44,7 +45,8 @@ export class DriverSurfaceImpl implements DriverSurface {
public readonly desktop: number, public readonly desktop: number,
private activityInfo: Plasma.TaskManager.ActivityInfo, private activityInfo: Plasma.TaskManager.ActivityInfo,
private kwinApi: KWin.Api, private kwinApi: KWin.Api,
private config: Config private config: Config,
private proxy: TSProxy
) { ) {
this.id = this.generateId(); this.id = this.generateId();
@ -54,11 +56,9 @@ export class DriverSurfaceImpl implements DriverSurface {
this.config.ignoreScreen.indexOf(screen) >= 0; this.config.ignoreScreen.indexOf(screen) >= 0;
this.workingArea = Rect.fromQRect( this.workingArea = Rect.fromQRect(
this.kwinApi.workspace.clientArea( this.proxy
this.kwinApi.KWin.PlacementArea, .workspace()
screen, .clientArea(this.kwinApi.KWin.PlacementArea, screen, desktop)
desktop
)
); );
} }
@ -74,7 +74,8 @@ export class DriverSurfaceImpl implements DriverSurface {
this.desktop + 1, this.desktop + 1,
this.activityInfo, this.activityInfo,
this.kwinApi, this.kwinApi,
this.config this.config,
this.proxy
); );
} }

View File

@ -9,6 +9,7 @@ import { Rect } from "../util/rect";
import { clip, matchWords } from "../util/func"; import { clip, matchWords } from "../util/func";
import { Config } from "../config"; import { Config } from "../config";
import { Log } from "../util/log"; import { Log } from "../util/log";
import { TSProxy } from "../extern/proxy";
/** /**
* KWin window representation. * KWin window representation.
@ -181,7 +182,8 @@ export class DriverWindowImpl implements DriverWindow {
desktop, desktop,
this.qml.activityInfo, this.qml.activityInfo,
this.kwinApi, this.kwinApi,
this.config this.config,
this.proxy
); );
} }
@ -212,7 +214,8 @@ export class DriverWindowImpl implements DriverWindow {
private qml: Bismuth.Qml.Main, private qml: Bismuth.Qml.Main,
private kwinApi: KWin.Api, private kwinApi: KWin.Api,
private config: Config, private config: Config,
private log: Log private log: Log,
private proxy: TSProxy
) { ) {
this.id = DriverWindowImpl.generateID(client); this.id = DriverWindowImpl.generateID(client);
this.maximized = false; this.maximized = false;
@ -273,11 +276,13 @@ export class DriverWindowImpl implements DriverWindow {
geometry = this.adjustGeometry(geometry); geometry = this.adjustGeometry(geometry);
if (this.config.preventProtrusion) { if (this.config.preventProtrusion) {
const area = Rect.fromQRect( const area = Rect.fromQRect(
this.kwinApi.workspace.clientArea( this.proxy
this.kwinApi.KWin.PlacementArea, .workspace()
this.client.screen, .clientArea(
this.kwinApi.workspace.currentDesktop this.kwinApi.KWin.PlacementArea,
) this.client.screen,
this.kwinApi.workspace.currentDesktop
)
); );
if (!area.includes(geometry)) { if (!area.includes(geometry)) {
/* assume windows will extrude only through right and bottom edges */ /* assume windows will extrude only through right and bottom edges */

View File

@ -5,6 +5,7 @@ import { Config } from "../config";
import { Action } from "../controller/action"; import { Action } from "../controller/action";
export interface TSProxy { export interface TSProxy {
workspace(): KWin.WorkspaceWrapper;
jsConfig(): Config; jsConfig(): Config;
registerShortcut(data: Action): void; registerShortcut(data: Action): void;
log(value: any): void; log(value: any): void;