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)); \
}
/**
* 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 *)));
};
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)
{
// 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
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(const Workspace &);
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);
Q_SIGNALS:

View File

@ -42,10 +42,9 @@ void Core::init()
{
m_config = std::make_unique<Bismuth::Config>();
m_engine = qmlEngine(this);
qDebug(Bi) << "Core QmlEngine ptr: " << m_engine;
m_controller = std::make_unique<Bismuth::Controller>();
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

View File

@ -10,12 +10,14 @@
#include "controller.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()
, m_engine(engine)
, m_config(config)
, m_controller(controller)
, m_plasmaApi(plasmaApi)
{
}
@ -107,6 +109,14 @@ QJSValue TSProxy::jsConfig()
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)
{
auto id = tsAction.property("key").toString();

View File

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

View File

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

View File

@ -4,6 +4,7 @@
// SPDX-License-Identifier: MIT
import { Config } from "../config";
import { TSProxy } from "../extern/proxy";
import { Rect } from "../util/rect";
/**
@ -44,7 +45,8 @@ export class DriverSurfaceImpl implements DriverSurface {
public readonly desktop: number,
private activityInfo: Plasma.TaskManager.ActivityInfo,
private kwinApi: KWin.Api,
private config: Config
private config: Config,
private proxy: TSProxy
) {
this.id = this.generateId();
@ -54,11 +56,9 @@ export class DriverSurfaceImpl implements DriverSurface {
this.config.ignoreScreen.indexOf(screen) >= 0;
this.workingArea = Rect.fromQRect(
this.kwinApi.workspace.clientArea(
this.kwinApi.KWin.PlacementArea,
screen,
desktop
)
this.proxy
.workspace()
.clientArea(this.kwinApi.KWin.PlacementArea, screen, desktop)
);
}
@ -74,7 +74,8 @@ export class DriverSurfaceImpl implements DriverSurface {
this.desktop + 1,
this.activityInfo,
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 { Config } from "../config";
import { Log } from "../util/log";
import { TSProxy } from "../extern/proxy";
/**
* KWin window representation.
@ -181,7 +182,8 @@ export class DriverWindowImpl implements DriverWindow {
desktop,
this.qml.activityInfo,
this.kwinApi,
this.config
this.config,
this.proxy
);
}
@ -212,7 +214,8 @@ export class DriverWindowImpl implements DriverWindow {
private qml: Bismuth.Qml.Main,
private kwinApi: KWin.Api,
private config: Config,
private log: Log
private log: Log,
private proxy: TSProxy
) {
this.id = DriverWindowImpl.generateID(client);
this.maximized = false;
@ -273,11 +276,13 @@ export class DriverWindowImpl implements DriverWindow {
geometry = this.adjustGeometry(geometry);
if (this.config.preventProtrusion) {
const area = Rect.fromQRect(
this.kwinApi.workspace.clientArea(
this.kwinApi.KWin.PlacementArea,
this.client.screen,
this.kwinApi.workspace.currentDesktop
)
this.proxy
.workspace()
.clientArea(
this.kwinApi.KWin.PlacementArea,
this.client.screen,
this.kwinApi.workspace.currentDesktop
)
);
if (!area.includes(geometry)) {
/* 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";
export interface TSProxy {
workspace(): KWin.WorkspaceWrapper;
jsConfig(): Config;
registerShortcut(data: Action): void;
log(value: any): void;