From fa5238ae7fe386480440450e90e28e7b9cbf52e3 Mon Sep 17 00:00:00 2001 From: Pier Luigi Fiorini Date: Thu, 3 Aug 2023 20:17:31 +0200 Subject: [PATCH] Say hello to AuroraPlatform AuroraPlatform is a platform abstraction library that glues together compositors with EGL device integration and input device managers. Compositors will use the platform abstraction layer to access input and output devices directly. Closes: #41 --- CMakeLists.txt | 1 + src/platform/CMakeLists.txt | 38 ++ src/platform/deviceintegration.cpp | 129 +++++++ src/platform/deviceintegration.h | 85 +++++ src/platform/deviceintegration_p.h | 37 ++ src/platform/deviceintegrationplugin.cpp | 89 +++++ src/platform/deviceintegrationplugin.h | 37 ++ src/platform/eglconfigchooser.cpp | 85 +++++ src/platform/eglconfigchooser_p.h | 21 ++ src/platform/inputdevice.cpp | 17 + src/platform/inputdevice.h | 37 ++ src/platform/inputmanager.cpp | 38 ++ src/platform/inputmanager.h | 43 +++ src/platform/keyboarddevice.cpp | 37 ++ src/platform/keyboarddevice.h | 35 ++ src/platform/output.cpp | 455 +++++++++++++++++++++++ src/platform/output.h | 193 ++++++++++ src/platform/output_p.h | 67 ++++ src/platform/pointerdevice.cpp | 22 ++ src/platform/pointerdevice.h | 28 ++ src/platform/session.cpp | 127 +++++++ src/platform/session.h | 62 +++ src/platform/session_noop.cpp | 55 +++ src/platform/session_noop_p.h | 49 +++ src/platform/touchdevice.cpp | 22 ++ src/platform/touchdevice.h | 23 ++ src/platform/window.cpp | 46 +++ src/platform/window.h | 40 ++ src/platform/window_p.h | 44 +++ 29 files changed, 1962 insertions(+) create mode 100644 src/platform/CMakeLists.txt create mode 100644 src/platform/deviceintegration.cpp create mode 100644 src/platform/deviceintegration.h create mode 100644 src/platform/deviceintegration_p.h create mode 100644 src/platform/deviceintegrationplugin.cpp create mode 100644 src/platform/deviceintegrationplugin.h create mode 100644 src/platform/eglconfigchooser.cpp create mode 100644 src/platform/eglconfigchooser_p.h create mode 100644 src/platform/inputdevice.cpp create mode 100644 src/platform/inputdevice.h create mode 100644 src/platform/inputmanager.cpp create mode 100644 src/platform/inputmanager.h create mode 100644 src/platform/keyboarddevice.cpp create mode 100644 src/platform/keyboarddevice.h create mode 100644 src/platform/output.cpp create mode 100644 src/platform/output.h create mode 100644 src/platform/output_p.h create mode 100644 src/platform/pointerdevice.cpp create mode 100644 src/platform/pointerdevice.h create mode 100644 src/platform/session.cpp create mode 100644 src/platform/session.h create mode 100644 src/platform/session_noop.cpp create mode 100644 src/platform/session_noop_p.h create mode 100644 src/platform/touchdevice.cpp create mode 100644 src/platform/touchdevice.h create mode 100644 src/platform/window.cpp create mode 100644 src/platform/window.h create mode 100644 src/platform/window_p.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 043ac7b7..c776f193 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ endif() if(FEATURE_aurora_xkbcommon) add_subdirectory(src/platformsupport/xkbcommon) endif() +add_subdirectory(src/platform) add_subdirectory(src/compositor) if(FEATURE_aurora_brcm) add_subdirectory(src/plugins/hardwareintegration/compositor/brcm-egl) diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt new file mode 100644 index 00000000..1ef91aa1 --- /dev/null +++ b/src/platform/CMakeLists.txt @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +# SPDX-License-Identifier: BSD-3-Clause + +include(ECMQtDeclareLoggingCategory) +ecm_qt_declare_logging_category( + AuroraPlatform_SOURCES + HEADER "auroracoreloggingcategories.h" + IDENTIFIER "Aurora::Platform::gLcAuroraPlatform" + CATEGORY_NAME "aurora.platform" + DEFAULT_SEVERITY "Info" + DESCRIPTION "Aurora platform abstraction" +) + +liri_add_module(AuroraPlatform + DESCRIPTION + "Platform abstraction library for Wayland compositors using Aurora" + SOURCES + deviceintegration.cpp deviceintegration.h + deviceintegrationplugin.cpp deviceintegrationplugin.h + eglconfigchooser.cpp eglconfigchooser_p.h + inputdevice.cpp inputdevice.h + inputmanager.cpp inputmanager.h + keyboarddevice.cpp keyboarddevice.h + output.cpp output.h output_p.h + pointerdevice.cpp pointerdevice.h + session.cpp session.h + session_noop.cpp session_noop_p.h + touchdevice.cpp touchdevice.h + window.cpp window.h window_p.h + ${AuroraPlatform_SOURCES} + DEFINES + QT_NO_CAST_FROM_ASCII + PUBLIC_LIBRARIES + Qt::Core + Qt::Gui +) + +liri_finalize_module(AuroraPlatform) diff --git a/src/platform/deviceintegration.cpp b/src/platform/deviceintegration.cpp new file mode 100644 index 00000000..c18ef83e --- /dev/null +++ b/src/platform/deviceintegration.cpp @@ -0,0 +1,129 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "deviceintegration.h" +#include "deviceintegration_p.h" +#include "eglconfigchooser_p.h" +#include "inputmanager.h" + +namespace Aurora { + +namespace Platform { + +/* + * DeviceIntegration + */ + +DeviceIntegration::DeviceIntegration(QObject *parent) + : QObject(parent) + , d_ptr(new DeviceIntegrationPrivate(this)) +{ +} + +DeviceIntegration::~DeviceIntegration() +{ +} + +DeviceIntegration::Status DeviceIntegration::status() const +{ + Q_D(const DeviceIntegration); + return d->status; +} + +void DeviceIntegration::setStatus(Status status) +{ + Q_D(DeviceIntegration); + + if (d->status == status) + return; + + d->status = status; + emit statusChanged(status); +} + +bool DeviceIntegration::supportsPBuffers() +{ + return true; +} + +bool DeviceIntegration::supportsSurfacelessContexts() +{ + return true; +} + +EGLNativeDisplayType DeviceIntegration::platformDisplay() const +{ + return EGL_DEFAULT_DISPLAY; +} + +EGLDisplay DeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay) +{ + return eglGetDisplay(nativeDisplay); +} + +void DeviceIntegration::destroyDisplay(EGLDisplay eglDisplay) +{ + if (eglDisplay != EGL_NO_DISPLAY) + eglTerminate(eglDisplay); +} + +EGLNativeWindowType DeviceIntegration::createNativeWindow(Window *window, const QSize &size, + const QSurfaceFormat &format) +{ + Q_UNUSED(window) + Q_UNUSED(size) + Q_UNUSED(format) + return 0; +} + +void DeviceIntegration::destroyNativeWindow(EGLNativeWindowType nativeWindow) +{ + Q_UNUSED(nativeWindow) +} + +QSurfaceFormat DeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +{ + return inputFormat; +} + +EGLint DeviceIntegration::surfaceType() const +{ + return EGL_WINDOW_BIT; +} + +EGLConfig DeviceIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format) +{ + Q_D(DeviceIntegration); + + QVector configAttribs = eglConfigAttributesFromSurfaceFormat(display, format); + + configAttribs.append(EGL_SURFACE_TYPE); + configAttribs.append(surfaceType()); + + configAttribs.append(EGL_NONE); + + // Get the number of matching configurations for the attributes + EGLConfig config = nullptr; + EGLint numConfigs = 0; + if (!eglChooseConfig(display, configAttribs.constData(), &config, 1, &numConfigs)) + return nullptr; + return config; +} + +InputManager *Aurora::Platform::DeviceIntegration::createInputManager() +{ + return nullptr; +} + +/* + * DeviceIntegrationPrivate + */ + +DeviceIntegrationPrivate::DeviceIntegrationPrivate(DeviceIntegration *self) + : q_ptr(self) +{ +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/deviceintegration.h b/src/platform/deviceintegration.h new file mode 100644 index 00000000..e5b07eb1 --- /dev/null +++ b/src/platform/deviceintegration.h @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +#include + +#include + +#include + +class QPlatformSurface; + +namespace Aurora { + +namespace Platform { + +class DeviceIntegrationPrivate; +class InputManager; +class Window; + +class LIRIAURORAPLATFORM_EXPORT DeviceIntegration : public QObject +{ + Q_OBJECT + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + Q_DECLARE_PRIVATE(DeviceIntegration) +public: + enum class Status { + NotReady, + Ready, + Failed + }; + Q_ENUM(Status) + + ~DeviceIntegration(); + + Status status() const; + + virtual void initialize() = 0; + virtual void destroy() = 0; + + virtual bool supportsPBuffers(); + virtual bool supportsSurfacelessContexts(); + + virtual EGLNativeDisplayType platformDisplay() const; + + virtual EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay); + virtual void destroyDisplay(EGLDisplay eglDisplay); + + virtual EGLNativeWindowType createNativeWindow(Window *window, const QSize &size, + const QSurfaceFormat &format); + virtual void destroyNativeWindow(EGLNativeWindowType nativeWindow); + + virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const; + virtual EGLint surfaceType() const; + + virtual EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format); + + virtual Window *createWindow(Output *output, QWindow *window) = 0; + + virtual void waitForVSync(Window *window) const = 0; + virtual void presentBuffer(Window *window) = 0; + + virtual InputManager *createInputManager(); + + virtual Outputs outputs() const = 0; + +signals: + void statusChanged(Status status); + void outputAdded(Output *output); + void outputRemoved(Output *output); + +protected: + QScopedPointer const d_ptr; + + explicit DeviceIntegration(QObject *parent = nullptr); + + void setStatus(Status status); +}; + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/deviceintegration_p.h b/src/platform/deviceintegration_p.h new file mode 100644 index 00000000..e9c56d50 --- /dev/null +++ b/src/platform/deviceintegration_p.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Aurora API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +namespace Aurora { + +namespace Platform { + +class LIRIAURORAPLATFORM_EXPORT DeviceIntegrationPrivate +{ + Q_DECLARE_PUBLIC(DeviceIntegration) +public: + DeviceIntegrationPrivate(DeviceIntegration *self); + + DeviceIntegration::Status status = DeviceIntegration::Status::NotReady; + +protected: + DeviceIntegration *q_ptr = nullptr; +}; + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/deviceintegrationplugin.cpp b/src/platform/deviceintegrationplugin.cpp new file mode 100644 index 00000000..055a80ad --- /dev/null +++ b/src/platform/deviceintegrationplugin.cpp @@ -0,0 +1,89 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include +#include +#include +#include + +#include "auroracoreloggingcategories.h" +#include "deviceintegrationplugin.h" + +namespace Aurora { + +namespace Platform { + +DeviceIntegrationPlugin::DeviceIntegrationPlugin(QObject *parent) + : QObject(parent) +{ +} + +QStringList DeviceIntegrationFactory::keys(const QString &pluginPath) +{ + QStringList list; + + if (!pluginPath.isEmpty()) + QCoreApplication::addLibraryPath(pluginPath); + + const auto paths = QCoreApplication::libraryPaths(); + for (const auto &path : paths) { + const auto absolutePath = + QDir(path).absoluteFilePath(QStringLiteral("aurora/deviceintegration")); + QDir dir(absolutePath); + + const auto fileNames = dir.entryList(QDir::Files); + for (const auto &fileName : fileNames) { + QPluginLoader loader(dir.absoluteFilePath(fileName)); + + if (loader.load()) { + const auto metaData = + loader.metaData().value(QLatin1String("MetaData")).toVariant().toMap(); + list += metaData.value(QStringLiteral("Keys"), QStringList()).toStringList(); + } + + loader.unload(); + } + } + + qCDebug(gLcAuroraPlatform) << "Device integration plugin keys:" << list; + return list; +} + +DeviceIntegration *DeviceIntegrationFactory::create(const QString &name, const QString &pluginPath) +{ + if (!pluginPath.isEmpty()) + QCoreApplication::addLibraryPath(pluginPath); + + const auto paths = QCoreApplication::libraryPaths(); + for (const auto &path : paths) { + const auto absolutePath = + QDir(path).absoluteFilePath(QStringLiteral("aurora/deviceintegration")); + QDir dir(absolutePath); + + const auto fileNames = dir.entryList(QDir::Files); + for (const auto &fileName : fileNames) { + QPluginLoader loader(dir.absoluteFilePath(fileName)); + + if (loader.load()) { + const auto metaData = + loader.metaData().value(QLatin1String("MetaData")).toVariant().toMap(); + const auto keys = + metaData.value(QStringLiteral("Keys"), QStringList()).toStringList(); + + if (keys.contains(name)) { + auto *plugin = dynamic_cast(loader.instance()); + if (plugin) + return plugin->create(); + } + } + + loader.unload(); + } + } + + return nullptr; +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/deviceintegrationplugin.h b/src/platform/deviceintegrationplugin.h new file mode 100644 index 00000000..c705bd87 --- /dev/null +++ b/src/platform/deviceintegrationplugin.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +#include + +namespace Aurora { + +namespace Platform { + +class DeviceIntegration; + +class LIRIAURORAPLATFORM_EXPORT DeviceIntegrationPlugin : public QObject +{ + Q_OBJECT +public: + explicit DeviceIntegrationPlugin(QObject *parent = nullptr); + + virtual DeviceIntegration *create() = 0; +}; + +class LIRIAURORAPLATFORM_EXPORT DeviceIntegrationFactory +{ +public: + static QStringList keys(const QString &pluginPath = QString()); + static DeviceIntegration *create(const QString &name, const QString &pluginPath = QString()); +}; + +} // namespace Platform + +} // namespace Aurora + +Q_DECLARE_INTERFACE(Aurora::Platform::DeviceIntegrationPlugin, + "io.liri.Aurora.DeviceIntegrationPlugin/1") diff --git a/src/platform/eglconfigchooser.cpp b/src/platform/eglconfigchooser.cpp new file mode 100644 index 00000000..a57318d5 --- /dev/null +++ b/src/platform/eglconfigchooser.cpp @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "eglconfigchooser_p.h" + +#ifndef EGL_OPENGL_ES3_BIT_KHR +# define EGL_OPENGL_ES3_BIT_KHR 0x0040 +#endif + +namespace Aurora { + +namespace Platform { + +bool hasEglExtension(EGLDisplay display, const char *name) +{ + QList extensions = + QByteArray(reinterpret_cast(eglQueryString(display, EGL_EXTENSIONS))) + .split(' '); + return extensions.contains(name); +} + +QVector eglConfigAttributesFromSurfaceFormat(EGLDisplay display, + const QSurfaceFormat &format) +{ + QVector configAttribs; + + configAttribs.append(EGL_RED_SIZE); + configAttribs.append(qMax(0, format.redBufferSize())); + + configAttribs.append(EGL_GREEN_SIZE); + configAttribs.append(qMax(0, format.greenBufferSize())); + + configAttribs.append(EGL_BLUE_SIZE); + configAttribs.append(qMax(0, format.blueBufferSize())); + + configAttribs.append(EGL_ALPHA_SIZE); + configAttribs.append(qMax(0, format.alphaBufferSize())); + + configAttribs.append(EGL_SAMPLES); + configAttribs.append(qMax(0, format.samples())); + + configAttribs.append(EGL_SAMPLE_BUFFERS); + configAttribs.append(format.samples() > 0 ? 1 : 0); + + switch (format.renderableType()) { + case QSurfaceFormat::OpenGL: + configAttribs.append(EGL_RENDERABLE_TYPE); + configAttribs.append(EGL_OPENGL_BIT); + break; + case QSurfaceFormat::OpenGLES: + configAttribs.append(EGL_RENDERABLE_TYPE); + if (format.majorVersion() == 1) + configAttribs.append(EGL_OPENGL_ES_BIT); + else if (format.majorVersion() == 2) + configAttribs.append(EGL_OPENGL_ES2_BIT); + else if (format.majorVersion() == 3 && hasEglExtension(display, "EGL_KHR_create_context")) + configAttribs.append(EGL_OPENGL_ES3_BIT_KHR); + else if (format.majorVersion() == 3) + configAttribs.append(EGL_OPENGL_ES3_BIT); + break; + case QSurfaceFormat::OpenVG: + configAttribs.append(EGL_RENDERABLE_TYPE); + configAttribs.append(EGL_OPENVG_BIT); + break; + default: + break; + } + + if (format.renderableType() != QSurfaceFormat::OpenVG) { + configAttribs.append(EGL_DEPTH_SIZE); + configAttribs.append(qMax(0, format.depthBufferSize())); + + configAttribs.append(EGL_STENCIL_SIZE); + configAttribs.append(qMax(0, format.stencilBufferSize())); + } else { + configAttribs.append(EGL_ALPHA_MASK_SIZE); + configAttribs.append(8); + } + + return configAttribs; +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/eglconfigchooser_p.h b/src/platform/eglconfigchooser_p.h new file mode 100644 index 00000000..71532feb --- /dev/null +++ b/src/platform/eglconfigchooser_p.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include +#include + +#include + +namespace Aurora { + +namespace Platform { + +bool hasEglExtension(EGLDisplay display, const char *name); +QVector eglConfigAttributesFromSurfaceFormat(EGLDisplay display, + const QSurfaceFormat &format); + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/inputdevice.cpp b/src/platform/inputdevice.cpp new file mode 100644 index 00000000..c5c3593c --- /dev/null +++ b/src/platform/inputdevice.cpp @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "inputdevice.h" + +namespace Aurora { + +namespace Platform { + +InputDevice::InputDevice(QObject *parent) + : QObject(parent) +{ +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/inputdevice.h b/src/platform/inputdevice.h new file mode 100644 index 00000000..d2e9066e --- /dev/null +++ b/src/platform/inputdevice.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +#include + +namespace Aurora { + +namespace Platform { + +class LIRIAURORAPLATFORM_EXPORT InputDevice : public QObject +{ + Q_OBJECT + Q_PROPERTY(DeviceType deviceType READ deviceType CONSTANT) +public: + enum class DeviceType { + Unknown, + Pointer, + Keyboard, + Touch, + Tablet + }; + Q_ENUM(DeviceType) + + explicit InputDevice(QObject *parent = nullptr); + + virtual QString seatName() const = 0; + + virtual DeviceType deviceType() = 0; +}; + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/inputmanager.cpp b/src/platform/inputmanager.cpp new file mode 100644 index 00000000..3288c37c --- /dev/null +++ b/src/platform/inputmanager.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "inputmanager.h" + +namespace Aurora { + +namespace Platform { + +InputManager::InputManager(QObject *parent) + : QObject(parent) +{ +} + +QList InputManager::keyboardDevices() const +{ + return QList(); +} + +QList InputManager::pointerDevices() const +{ + return QList(); +} + +QList InputManager::touchDevices() const +{ + return QList(); +} + +int InputManager::deviceCount(InputDevice::DeviceType deviceType) const +{ + Q_UNUSED(deviceType) + return 0; +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/inputmanager.h b/src/platform/inputmanager.h new file mode 100644 index 00000000..e1b6f591 --- /dev/null +++ b/src/platform/inputmanager.h @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +#include + +namespace Aurora { + +namespace Platform { + +class KeyboardDevice; +class PointerDevice; +class TouchDevice; + +class LIRIAURORAPLATFORM_EXPORT InputManager : public QObject +{ + Q_OBJECT +public: + explicit InputManager(QObject *parent = nullptr); + + virtual QList keyboardDevices() const; + virtual QList pointerDevices() const; + virtual QList touchDevices() const; + + virtual int deviceCount(InputDevice::DeviceType deviceType) const; + +signals: + void deviceAdded(InputDevice *inputDevice); + void deviceRemoved(InputDevice *inputDevice); + void keyboardAdded(KeyboardDevice *keyboardDevice); + void keyboardRemoved(KeyboardDevice *keyboardDevice); + void pointerAdded(PointerDevice *pointerDevice); + void pointerRemoved(PointerDevice *pointerDevice); + void touchAdded(TouchDevice *touchDevice); + void touchRemoved(TouchDevice *touchDevice); +}; + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/keyboarddevice.cpp b/src/platform/keyboarddevice.cpp new file mode 100644 index 00000000..34aed6cb --- /dev/null +++ b/src/platform/keyboarddevice.cpp @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "keyboarddevice.h" + +namespace Aurora { + +namespace Platform { + +KeyboardDevice::KeyboardDevice(QObject *parent) + : InputDevice(parent) +{ +} + +InputDevice::DeviceType KeyboardDevice::deviceType() +{ + return DeviceType::Keyboard; +} + +bool KeyboardDevice::isKeyRepeatEnabled() const +{ + return false; +} + +qint32 KeyboardDevice::keyRepeatRate() const +{ + return 0; +} + +qint32 KeyboardDevice::keyRepeatDelay() const +{ + return 0; +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/keyboarddevice.h b/src/platform/keyboarddevice.h new file mode 100644 index 00000000..66a37547 --- /dev/null +++ b/src/platform/keyboarddevice.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +namespace Aurora { + +namespace Platform { + +class LIRIAURORAPLATFORM_EXPORT KeyboardDevice : public InputDevice +{ + Q_OBJECT + Q_PROPERTY(bool keyRepeatEnabled READ isKeyRepeatEnabled NOTIFY keyRepeatChanged) + Q_PROPERTY(qint32 keyRepeatRate READ keyRepeatRate NOTIFY keyRepeatChanged) + Q_PROPERTY(qint32 keyRepeatDelay READ keyRepeatDelay NOTIFY keyRepeatChanged) +public: + explicit KeyboardDevice(QObject *parent = nullptr); + + DeviceType deviceType() override; + + virtual bool isKeyRepeatEnabled() const; + virtual qint32 keyRepeatRate() const; + virtual qint32 keyRepeatDelay() const; + +signals: + void keyPressed(quint32 key); + void keyReleased(quint32 key); + void keyRepeatChanged(); +}; + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/output.cpp b/src/platform/output.cpp new file mode 100644 index 00000000..3efe28de --- /dev/null +++ b/src/platform/output.cpp @@ -0,0 +1,455 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include + +#include "output.h" +#include "output_p.h" + +namespace Aurora { + +namespace Platform { + +/*! + \class Output + \inmodule AuroraCore + \brief Generic output representation. + + The Output class represents an output. + */ + +/*! + * Constructs an Output with the given \a parent. + */ +Output::Output(QObject *parent) + : QObject(parent) + , d_ptr(new OutputPrivate(this)) +{ +} + +Output::~Output() +{ +} + +/*! + * \property Output::name + * \brief A user presentable string representing the output. + * + * This property contains a user presentable string representing the output, + * typycally something like "VGA1", "eDP-1", "HDMI1", etc. + */ +QString Output::name() const +{ + Q_D(const Output); + return d->name; +} + +/*! + * \property Output::description + * \brief Human readable description of the output. + * + * This property contains a human readable description of he output. + */ +QString Output::description() const +{ + Q_D(const Output); + return d->description; +} + +/*! + * \property Output::uuid + * \brief The unique identifier of the output. + * + * This property contains a unique identifier of the output. + */ +QUuid Output::uuid() const +{ + Q_D(const Output); + return d->uuid; +} + +/*! + * \property Output::manufacturer + * \brief The manufacturer of the screen. + * + * This property holds the manufacturer of the screen. + */ +QString Output::manufacturer() const +{ + Q_D(const Output); + return d->manufacturer; +} + +/*! + * \property Output::model + * \brief The model of the screen. + * + * This property holds the model of the screen. + */ +QString Output::model() const +{ + Q_D(const Output); + return d->model; +} + +/*! + * \property Output::serialNumber + * \brief The serial number of the screen. + * + * This property holds the serial number of the screen. + */ +QString Output::serialNumber() const +{ + Q_D(const Output); + return d->serialNumber; +} + +/*! + * \property Output::physicalSize + * \brief The physical size of the screen in millimiters. + * + * This property holds the physical size of the screen in millimiters. + */ +QSize Output::physicalSize() const +{ + Q_D(const Output); + return d->physicalSize; +} + +/*! + * \property Output::enabled + * \brief Weather the output is enable or not. + * + * This property holds weather the output is enabled or not. + */ +bool Output::isEnabled() const +{ + Q_D(const Output); + return d->enabled; +} + +/*! + * \property Output::globalPosition + * \brief Position in the global compositor space. + * + * This property holds the output position within the global compositor space. + */ +QPoint Output::globalPosition() const +{ + Q_D(const Output); + return d->globalPosition; +} + +/*! + * \property Output::pixelSize + * \brief Size. + * + * This property holds the output size in pixels, taking transform into account. + * + * \sa Output::modeSize + * \sa Output::transform + */ +QSize Output::pixelSize() const +{ + Q_D(const Output); + + switch (d->transform) { + case Output::Transform::Rotated90: + case Output::Transform::Rotated270: + case Output::Transform::Flipped90: + case Output::Transform::Flipped270: + return modeSize().transposed(); + default: + break; + } + + return modeSize(); +} + +/*! + * \property Output::modeSize + * \brief Actual resolution. + * + * This property holds the actual resolution of the output, without + * being multiplied by the scale. + * + * \sa Output::pixelSize + * \sa Output::scale + */ +QSize Output::modeSize() const +{ + Q_D(const Output); + + if (d->currentMode == d->modes.end()) + return QSize(); + return d->currentMode->size; +} + +/*! + * \property Output::scale + * \brief Scale. + * + * This property holds the output scale. + */ +qreal Output::scale() const +{ + Q_D(const Output); + return d->scale; +} + +/*! + * \property Output::geometry + * \brief Geometry of the output. + * + * This property holds the position of the output in the compositor space + * and the size in pixels. + * + * The geometry is transformed according to the output transform. + * + * \sa Output::transform + * \sa Output::globalPosition + * \sa Output::pixelSize + * \sa Output::scale + */ +QRect Output::geometry() const +{ + Q_D(const Output); + + if (d->currentMode == d->modes.end()) + return QRect(); + + auto rect = QRect(d->globalPosition, pixelSize() / d->scale); + auto x = rect.x(); + auto y = rect.y(); + auto width = rect.width(); + auto height = rect.height(); + + switch (d->transform) { + case Output::Transform::Normal: + return rect; + case Output::Transform::Rotated90: + return QRect(y, rect.left(), height, width); + case Output::Transform::Rotated180: + return QRect(rect.topLeft(), QSize(width, height)); + case Output::Transform::Rotated270: + return QRect(rect.top(), x, height, width); + case Output::Transform::Flipped: + return QRect(x + width, y, -width, height); + case Output::Transform::Flipped90: + return QRect(y + height, rect.left(), -height, width); + case Output::Transform::Flipped180: + return QRect(rect.bottomRight(), QSize(-width, -height)); + case Output::Transform::Flipped270: + return QRect(rect.top(), x + width, height, -width); + } +} + +/*! + * \property Output::refreshRate + * \brief The refresh rate of the output in mHz. + * + * This property holds the refresh rate of the output in mHz. + */ +int Output::refreshRate() const +{ + Q_D(const Output); + + if (d->currentMode == d->modes.end()) + return 0; + return d->currentMode->refreshRate; +} + +/*! + * \property Output::depth + * \brief Color depth. + * + * This property holds the color depth of the output. + * It must be compatible with the image format: for example if the + * Output::format property is QImage::Format_RGB32, depth must be 32. + * + * \ sa Output::format + */ +int Output::depth() const +{ + Q_D(const Output); + return d->depth; +} + +/*! + * \property Output::format + * \brief Image format. + * + * This property holds the image format of the output. + * It must be compatible with color depth: for example if the + * Output::depth property is 32, format might be QImage::Format_RGB32. + * + * \sa Output::depth + */ +QImage::Format Output::format() const +{ + Q_D(const Output); + return d->format; +} + +/*! + * \property Output::powerState + * \brief The power state. + * + * This property holds the power state of the screen. + */ +Output::PowerState Output::powerState() const +{ + Q_D(const Output); + return d->powerState; +} + +void Output::setPowerState(Output::PowerState powerState) +{ + Q_D(Output); + + if (powerState == d->powerState) + return; + + d->powerState = powerState; + emit powerStateChanged(powerState); +} + +Output::Subpixel Output::subpixel() const +{ + Q_D(const Output); + return d->subpixel; +} + +Output::Transform Output::transform() const +{ + Q_D(const Output); + return d->transform; +} + +Output::ContentType Output::contentType() const +{ + Q_D(const Output); + return d->contentType; +} + +void Output::setContentType(Output::ContentType contentType) +{ + Q_D(Output); + + if (d->contentType == contentType) + return; + + d->contentType = contentType; + emit contentTypeChanged(contentType); +} + +QDebug operator<<(QDebug debug, const Output *output) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + + if (output) { + debug << output->metaObject()->className() << '(' << static_cast(output); + debug << ", name=" << output->name(); + debug << ", geometry=" << output->geometry(); + // scale + if (debug.verbosity() > 2) { + debug << ", manufacturer=" << output->manufacturer(); + debug << ", model=" << output->model(); + debug << ", serialNumber=" << output->serialNumber(); + } + debug << ')'; + } else { + debug << "Output(0x0)"; + } + + return debug; +} + +bool Output::Mode::operator==(const Output::Mode &m) const +{ + return flags == m.flags && size == m.size && refreshRate == m.refreshRate; +} + +/* + * OutputPrivate + */ + +OutputPrivate::OutputPrivate(Output *self) + : q_ptr(self) +{ +} + +void OutputPrivate::setManufacturer(const QString &manufacturer) +{ + Q_Q(Output); + + if (this->manufacturer != manufacturer) { + this->manufacturer = manufacturer; + emit q->manufacturerChanged(manufacturer); + } +} + +void OutputPrivate::setModel(const QString &model) +{ + Q_Q(Output); + + if (this->model != model) { + this->model = model; + emit q->modelChanged(model); + } +} + +void OutputPrivate::setSubpixel(Output::Subpixel subpixel) +{ + Q_Q(Output); + + if (this->subpixel != subpixel) { + this->subpixel = subpixel; + emit q->subpixelChanged(subpixel); + } +} + +void OutputPrivate::setTransform(Output::Transform transform) +{ + Q_Q(Output); + + if (this->transform != transform) { + this->transform = transform; + emit q->transformChanged(transform); + } +} + +void OutputPrivate::setPhysicalSize(const QSize &physicalSize) +{ + Q_Q(Output); + + if (this->physicalSize != physicalSize) { + this->physicalSize = physicalSize; + emit q->physicalSizeChanged(physicalSize); + } +} + +void OutputPrivate::setGlobalPosition(const QPoint &globalPosition) +{ + Q_Q(Output); + + if (this->globalPosition != globalPosition) { + this->globalPosition = globalPosition; + emit q->globalPositionChanged(globalPosition); + } +} + +void OutputPrivate::setScale(qreal scale) +{ + Q_Q(Output); + + if (this->scale != scale) { + this->scale = scale; + emit q->scaleChanged(scale); + } +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/output.h b/src/platform/output.h new file mode 100644 index 00000000..2af12388 --- /dev/null +++ b/src/platform/output.h @@ -0,0 +1,193 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace Aurora { + +namespace Platform { + +class OutputPrivate; + +class LIRIAURORAPLATFORM_EXPORT Output : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUuid uuid READ uuid CONSTANT) + Q_PROPERTY(QString name READ name CONSTANT) + Q_PROPERTY(QString description READ description CONSTANT) + Q_PROPERTY(QString manufacturer READ manufacturer NOTIFY manufacturerChanged) + Q_PROPERTY(QString model READ model NOTIFY modelChanged) + Q_PROPERTY(QString serialNumber READ serialNumber CONSTANT) + Q_PROPERTY(QSize physicalSize READ physicalSize NOTIFY physicalSizeChanged) + Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged) + Q_PROPERTY(QPoint globalPosition READ globalPosition NOTIFY globalPositionChanged) + Q_PROPERTY(QSize modeSize READ modeSize NOTIFY modeSizeChanged) + Q_PROPERTY(QSize pixelSize READ pixelSize NOTIFY pixelSizeChanged) + Q_PROPERTY(qreal scale READ scale NOTIFY scaleChanged) + Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged) + Q_PROPERTY(int refreshRate READ refreshRate NOTIFY refreshRateChanged) + Q_PROPERTY(int depth READ depth CONSTANT) + Q_PROPERTY(int format READ format CONSTANT) + Q_PROPERTY(PowerState powerState READ powerState WRITE setPowerState NOTIFY powerStateChanged) + Q_PROPERTY(Subpixel subpixel READ subpixel NOTIFY subpixelChanged) + Q_PROPERTY(Transform transform READ transform NOTIFY transformChanged) + Q_PROPERTY( + ContentType contenType READ contentType WRITE setContentType NOTIFY contentTypeChanged) + Q_DECLARE_PRIVATE(Output) +public: + Q_DISABLE_COPY_MOVE(Output) + + enum class Capability : uint { + PowerState = 1, + Overscan = 1 << 1, + Vrr = 1 << 2, + RgbRange = 1 << 3, + HighDynamicRange = 1 << 4, + WideColorGamut = 1 << 5, + }; + Q_DECLARE_FLAGS(Capabilities, Capability) + + enum class PowerState { + On, + Standby, + Suspend, + Off, + }; + Q_ENUM(PowerState) + + enum class Subpixel { + Unknown, + None, + HorizontalRGB, + HorizontalBGR, + VerticalRGB, + VerticalBGR, + }; + Q_ENUM(Subpixel) + + enum class Transform { + Normal, + Rotated90, + Rotated180, + Rotated270, + Flipped, + Flipped90, + Flipped180, + Flipped270, + }; + Q_ENUM(Transform); + + enum class ContentType { + Unknown, + Photo, + Video, + Game, + }; + Q_ENUM(ContentType) + + struct Mode + { + enum class Flag { + None = 0, + Current = 1 << 0, + Preferred = 1 << 1, + }; + Q_DECLARE_FLAGS(Flags, Flag) + + /*! Weather this mode is current or preferred */ + Flags flags = Flag::None; + + /*! Size in pixel space */ + QSize size; + + /*! Refresh rate in mHz */ + int refreshRate = 0; + + bool operator==(const Mode &m) const; + }; + + explicit Output(QObject *parent = nullptr); + ~Output(); + + QUuid uuid() const; + + QString name() const; + QString description() const; + + QString manufacturer() const; + QString model() const; + QString serialNumber() const; + + QSize physicalSize() const; + + bool isEnabled() const; + + QPoint globalPosition() const; + QSize pixelSize() const; + QSize modeSize() const; + + qreal scale() const; + + QRect geometry() const; + + int refreshRate() const; + + int depth() const; + QImage::Format format() const; + + PowerState powerState() const; + void setPowerState(PowerState powerState); + + Subpixel subpixel() const; + + Transform transform() const; + + ContentType contentType() const; + void setContentType(ContentType contentType); + +signals: + void manufacturerChanged(const QString &manufacturer); + void modelChanged(const QString &model); + void physicalSizeChanged(const QSize &physicalSize); + void enabledChanged(bool enabled); + void globalPositionChanged(const QPoint &globalPosition); + void modeSizeChanged(const QSize &modeSize); + void pixelSizeChanged(const QSize &pixelSize); + void scaleChanged(qreal scale); + void geometryChanged(const QRect &geometry); + void refreshRateChanged(int refreshRate); + void powerStateChanged(Output::PowerState powerState); + void subpixelChanged(Output::Subpixel subpixel); + void transformChanged(Output::Transform transform); + void contentTypeChanged(Output::ContentType contentType); + void modeAdded(const Mode &mode); + void modeChanged(const Mode &mode); + +protected: + QScopedPointer const d_ptr; +}; + +LIRIAURORAPLATFORM_EXPORT QDebug operator<<(QDebug debug, const Output *output); + +typedef QList Outputs; + +Q_DECLARE_OPERATORS_FOR_FLAGS(Output::Capabilities) +Q_DECLARE_OPERATORS_FOR_FLAGS(Output::Mode::Flags) + +} // namespace Platform + +} // namespace Aurora + +Q_DECLARE_METATYPE(Aurora::Platform::Output::PowerState) +Q_DECLARE_METATYPE(Aurora::Platform::Output::Subpixel) +Q_DECLARE_METATYPE(Aurora::Platform::Output::Transform) +Q_DECLARE_METATYPE(Aurora::Platform::Output::ContentType) +Q_DECLARE_METATYPE(Aurora::Platform::Output::Mode) diff --git a/src/platform/output_p.h b/src/platform/output_p.h new file mode 100644 index 00000000..ae4ba366 --- /dev/null +++ b/src/platform/output_p.h @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Aurora API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +namespace Aurora { + +namespace Platform { + +class LIRIAURORAPLATFORM_EXPORT OutputPrivate +{ + Q_DECLARE_PUBLIC(Output) +public: + explicit OutputPrivate(Output *self); + + static OutputPrivate *get(Output *output) + { + return output->d_func(); + } + + void setManufacturer(const QString &manufacturer); + void setModel(const QString &model); + void setSubpixel(Output::Subpixel subpixel); + void setTransform(Output::Transform transform); + void setPhysicalSize(const QSize &physicalSize); + void setGlobalPosition(const QPoint &globalPosition); + void setScale(qreal scale); + + QUuid uuid; + QString name; + QString description; + QString manufacturer; + QString model; + QString serialNumber; + QSize physicalSize; + bool enabled = true; + QPoint globalPosition; + qreal scale = 1.0f; + int depth = 0; + QImage::Format format = QImage::Format_Invalid; + Output::PowerState powerState = Output::PowerState::On; + Output::Subpixel subpixel = Output::Subpixel::Unknown; + Output::Transform transform = Output::Transform::Normal; + Output::ContentType contentType = Output::ContentType::Unknown; + QList modes; + QList::iterator currentMode = modes.end(); + +protected: + Output *q_ptr = nullptr; +}; + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/pointerdevice.cpp b/src/platform/pointerdevice.cpp new file mode 100644 index 00000000..549a2fd2 --- /dev/null +++ b/src/platform/pointerdevice.cpp @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "pointerdevice.h" + +namespace Aurora { + +namespace Platform { + +PointerDevice::PointerDevice(QObject *parent) + : InputDevice(parent) +{ +} + +InputDevice::DeviceType PointerDevice::deviceType() +{ + return DeviceType::Pointer; +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/pointerdevice.h b/src/platform/pointerdevice.h new file mode 100644 index 00000000..076b00a4 --- /dev/null +++ b/src/platform/pointerdevice.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +namespace Aurora { + +namespace Platform { + +class LIRIAURORAPLATFORM_EXPORT PointerDevice : public InputDevice +{ + Q_OBJECT +public: + explicit PointerDevice(QObject *parent = nullptr); + + DeviceType deviceType() override; + +signals: + void motion(const QPointF &absPosition); + void buttonPressed(Qt::MouseButton button); + void buttonReleased(Qt::MouseButton button); +}; + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/session.cpp b/src/platform/session.cpp new file mode 100644 index 00000000..a4ecc4b5 --- /dev/null +++ b/src/platform/session.cpp @@ -0,0 +1,127 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-FileCopyrightText: 2020 Vlad Zahorodnii +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "session.h" +#include "session_noop_p.h" + +namespace Aurora { + +namespace Platform { + +/*! + \class Session + \inmodule AuroraCore + \brief The Session class represents the session controlled by the compositor. + + The Session class provides information about the virtual terminal where the compositor + is running and a way to open files that require special privileges, e.g. DRM devices or + input devices. + */ + +/*! + \enum Session::Type + + This enum type is used to specify the type of the session. + */ + +/*! + \enum Session::Capability + + This enum type is used to specify optional capabilities of the session. + */ + +/*! + \fn Capabilities Session::capabilities() + + Returns the capabilities supported by the session. + */ + +/*! + \fn bool Session::isActive() + + Returns \c true if the session is active; otherwise returns \c false. + */ + +/*! + \fn QString Session::seat() + + Returns the seat name for the Session. + */ + +/*! + \fn uint Session::terminal() + + Returns the terminal controlled by the Session. + */ + +/*! + \fn int Session::openRestricted(const QString &fileName) + + Opens the file with the specified \a fileName. Returns the file descriptor + of the file or \c -1 if an error has occurred. + */ + +/*! + \fn void Session::closeRestricted(int fileDescriptor) + + Closes a file that has been opened using the openRestricted() function. + */ + +/*! + \fn void switchTo(uint terminal) + + Switches to the specified virtual \a terminal. This function does nothing if the + Capability::SwitchTerminal capability is unsupported. + */ + +/*! + \fn void Session::awoke() + + This signal is emitted when the session is resuming from suspend. + */ + +/*! + \fn void Session::activeChanged(bool active) + + This signal is emitted when the active state of the session has changed. + */ + +/*! + \fn void Session::deviceResumed(dev_t deviceId) + + This signal is emitted when the specified device can be used again. + */ + +/*! + \fn void Session::devicePaused(dev_t deviceId) + + This signal is emitted when the given device cannot be used by the compositor + anymore. For example, this normally occurs when switching between VTs. + + Note that when this signal is emitted for a DRM device, master permissions can + be already revoked. + */ + +static const struct +{ + Session::Type type; + std::function()> createFunc; +} s_availableSessions[] = { + { Session::Type::Noop, &NoopSession::create }, +}; + +std::unique_ptr Session::create() +{ + for (const auto &sessionInfo : s_availableSessions) { + std::unique_ptr session = sessionInfo.createFunc(); + if (session) + return session; + } + + return nullptr; +} + +} // namespace Platform + +} // namespace Aurora \ No newline at end of file diff --git a/src/platform/session.h b/src/platform/session.h new file mode 100644 index 00000000..273f956a --- /dev/null +++ b/src/platform/session.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-FileCopyrightText: 2020 Vlad Zahorodnii +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include + +#include + +namespace Aurora { + +namespace Platform { + +class LIRIAURORAPLATFORM_EXPORT Session : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool active READ isActive NOTIFY activeChanged) +public: + Q_DISABLE_COPY_MOVE(Session) + + enum class Type { + Noop, + }; + Q_ENUM(Type) + + enum class Capability : uint { + SwitchTerminal = 0x1, + }; + Q_DECLARE_FLAGS(Capabilities, Capability) + + virtual Capabilities capabilities() const = 0; + + virtual bool isActive() const = 0; + + virtual QString seat() const = 0; + virtual uint terminal() const = 0; + + virtual int openRestricted(const QString &fileName) = 0; + virtual void closeRestricted(int fileDescriptor) = 0; + + virtual void switchTo(uint terminal) = 0; + + static std::unique_ptr create(); + +signals: + void activeChanged(bool active); + void awoke(); + void deviceResumed(dev_t deviceId); + void devicePaused(dev_t deviceId); + +protected: + explicit Session() = default; +}; + +} // namespace Platform + +} // namespace Aurora + +Q_DECLARE_OPERATORS_FOR_FLAGS(Aurora::Platform::Session::Capabilities) diff --git a/src/platform/session_noop.cpp b/src/platform/session_noop.cpp new file mode 100644 index 00000000..844b93d3 --- /dev/null +++ b/src/platform/session_noop.cpp @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-FileCopyrightText: 2021 Vlad Zahorodnii +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "session_noop_p.h" + +namespace Aurora { + +namespace Platform { + +std::unique_ptr NoopSession::create() +{ + return std::unique_ptr{ new NoopSession() }; +} + +NoopSession::~NoopSession() +{ +} + +NoopSession::Capabilities NoopSession::capabilities() const +{ + return Capabilities(); +} + +bool NoopSession::isActive() const +{ + return true; +} + +QString NoopSession::seat() const +{ + return QStringLiteral("seat0"); +} + +uint NoopSession::terminal() const +{ + return 0; +} + +int NoopSession::openRestricted(const QString &fileName) +{ + return -1; +} + +void NoopSession::closeRestricted(int fileDescriptor) +{ +} + +void NoopSession::switchTo(uint terminal) +{ +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/session_noop_p.h b/src/platform/session_noop_p.h new file mode 100644 index 00000000..f45cfe77 --- /dev/null +++ b/src/platform/session_noop_p.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-FileCopyrightText: 2021 Vlad Zahorodnii +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Aurora API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "session.h" + +namespace Aurora { + +namespace Platform { + +class NoopSession : public Session +{ + Q_OBJECT +public: + static std::unique_ptr create(); + ~NoopSession() override; + + Capabilities capabilities() const override; + + bool isActive() const override; + + QString seat() const override; + uint terminal() const override; + + int openRestricted(const QString &fileName) override; + void closeRestricted(int fileDescriptor) override; + + void switchTo(uint terminal) override; + +private: + explicit NoopSession() = default; +}; + +} // namespace Platform + +} // namespace Aurora \ No newline at end of file diff --git a/src/platform/touchdevice.cpp b/src/platform/touchdevice.cpp new file mode 100644 index 00000000..dbb78c44 --- /dev/null +++ b/src/platform/touchdevice.cpp @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "touchdevice.h" + +namespace Aurora { + +namespace Platform { + +TouchDevice::TouchDevice(QObject *parent) + : InputDevice(parent) +{ +} + +InputDevice::DeviceType TouchDevice::deviceType() +{ + return DeviceType::Touch; +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/touchdevice.h b/src/platform/touchdevice.h new file mode 100644 index 00000000..4cda8ef7 --- /dev/null +++ b/src/platform/touchdevice.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +namespace Aurora { + +namespace Platform { + +class LIRIAURORAPLATFORM_EXPORT TouchDevice : public InputDevice +{ + Q_OBJECT +public: + explicit TouchDevice(QObject *parent = nullptr); + + DeviceType deviceType() override; +}; + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/window.cpp b/src/platform/window.cpp new file mode 100644 index 00000000..0cacae02 --- /dev/null +++ b/src/platform/window.cpp @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "output.h" +#include "window.h" +#include "window_p.h" + +namespace Aurora { + +namespace Platform { + +Window::Window(Output *output, QObject *parent) + : QObject(parent) + , d_ptr(new WindowPrivate(this)) +{ + d_ptr->output = output; +} + +Window::~Window() +{ +} + +Output *Window::output() const +{ + Q_D(const Window); + return d->output; +} + +void *Window::resource(const QByteArray &name) +{ + Q_UNUSED(name) + return nullptr; +} + +/* + * WindowPrivate + */ + +WindowPrivate::WindowPrivate(Window *self) + : q_ptr(self) +{ +} + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/window.h b/src/platform/window.h new file mode 100644 index 00000000..f82d3f0e --- /dev/null +++ b/src/platform/window.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +#include + +namespace Aurora { + +namespace Platform { + +class Output; +class WindowPrivate; + +class LIRIAURORAPLATFORM_EXPORT Window : public QObject +{ + Q_OBJECT + Q_PROPERTY(Output *output READ output CONSTANT) + Q_DECLARE_PRIVATE(Window) +public: + ~Window(); + + Output *output() const; + + virtual void *resource(const QByteArray &name); + + virtual bool create() = 0; + virtual void destroy() = 0; + +protected: + explicit Window(Output *output, QObject *parent = nullptr); + + QScopedPointer const d_ptr; +}; + +} // namespace Platform + +} // namespace Aurora diff --git a/src/platform/window_p.h b/src/platform/window_p.h new file mode 100644 index 00000000..b986b7ee --- /dev/null +++ b/src/platform/window_p.h @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: 2023 Pier Luigi Fiorini +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Aurora API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +namespace Aurora { + +namespace Platform { + +class Output; + +class LIRIAURORAPLATFORM_EXPORT WindowPrivate +{ + Q_DECLARE_PUBLIC(Window) +public: + explicit WindowPrivate(Window *self); + + static WindowPrivate *get(Window *window) + { + return window->d_func(); + } + + Output *output = nullptr; + +protected: + Window *q_ptr = nullptr; +}; + +} // namespace Platform + +} // namespace Aurora