feat: begin work on docs, also minor refactoring

This commit is contained in:
outfoxxed 2024-02-12 04:21:24 -08:00
parent 5de0ae095b
commit 424a45be05
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
12 changed files with 197 additions and 13 deletions

View file

@ -69,6 +69,7 @@ IndentWidth: 2
TabWidth: 2 TabWidth: 2
AllowAllConstructorInitializersOnNextLine: false AllowAllConstructorInitializersOnNextLine: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
CommentPragmas: '.*'
NamespaceIndentation: None NamespaceIndentation: None
IncludeBlocks: Regroup IncludeBlocks: Regroup
IncludeCategories: IncludeCategories:

11
.editorconfig Normal file
View file

@ -0,0 +1,11 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
[*.nix]
indent_style = space
indent_size = 2

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "docs"]
path = docs
url = https://git.outfoxxed.me/outfoxxed/quickshell-docs

1
docs Submodule

@ -0,0 +1 @@
Subproject commit 27b3274027251ebf382e31546ef2b350ae2f7b0e

View file

@ -56,13 +56,23 @@ Q_ENUM_NS(Enum);
} // namespace Layer } // namespace Layer
/// Type of keyboard focus that will be accepted by a [ProxyShellWindow]
///
/// [ProxyShellWindow]: ../proxyshellwindow
namespace KeyboardFocus { // NOLINT namespace KeyboardFocus { // NOLINT
Q_NAMESPACE; Q_NAMESPACE;
QML_ELEMENT; QML_ELEMENT;
enum Enum { enum Enum {
/// No keyboard input will be accepted.
None = 0, None = 0,
/// Exclusive access to the keyboard, locking out all other windows.
Exclusive = 1, Exclusive = 1,
/// Access to the keyboard as determined by the operating system.
///
/// > [!WARNING] On some systems, `OnDemand` may cause the shell window to
/// > retain focus over another window unexpectedly.
/// > You should try `None` if you experience issues.
OnDemand = 2, OnDemand = 2,
}; };
Q_ENUM_NS(Enum); Q_ENUM_NS(Enum);
@ -81,19 +91,57 @@ Q_ENUM_NS(Enum);
} // namespace ScreenConfiguration } // namespace ScreenConfiguration
///! Decorationless window attached to screen edges by anchors.
/// Decorationless window attached to screen edges by anchors.
///
/// #### Example
/// The following snippet creates a white bar attached to the bottom of [TODO] screen.
///
/// ```qml
/// ProxyShellWindow {
/// anchors {
/// left: true
/// bottom: true
/// right: true
/// }
///
/// Text {
/// anchors.horizontalCenter: parent.horizontalCenter
/// anchors.verticalCenter: parent.verticalCenter
/// text: "Hello!"
/// }
/// }
/// ```
class ProxyShellWindow: public ProxyWindowBase { class ProxyShellWindow: public ProxyWindowBase {
// clang-format off // clang-format off
Q_OBJECT; Q_OBJECT;
/// The screen that the shell window currently occupies.
///
/// > [!INFO] This cannot be changed while the shell window is visible.
Q_PROPERTY(QuickShellScreenInfo* screen READ screen WRITE setScreen NOTIFY screenChanged); Q_PROPERTY(QuickShellScreenInfo* screen READ screen WRITE setScreen NOTIFY screenChanged);
/// Anchors attach a shell window to the sides of the screen.
/// By default all anchors are disabled to avoid blocking the entire screen due to a misconfiguration.
///
/// > [!INFO] When two opposite anchors are attached at the same time, the corrosponding dimension
/// > (width or height) will be forced to equal the screen width/height.
/// > Margins can be used to create anchored windows that are also disconnected from the monitor sides.
Q_PROPERTY(Anchors anchors READ anchors WRITE setAnchors NOTIFY anchorsChanged); Q_PROPERTY(Anchors anchors READ anchors WRITE setAnchors NOTIFY anchorsChanged);
Q_PROPERTY(qint32 exclusionZone READ exclusiveZone WRITE setExclusiveZone NOTIFY exclusionZoneChanged) /// The amount of space reserved for the shell layer relative to its anchors.
Q_PROPERTY(Margins margins READ margins WRITE setMargins NOTIFY marginsChanged) ///
Q_PROPERTY(Layer::Enum layer READ layer WRITE setLayer NOTIFY layerChanged) /// > [!INFO] Some systems will require exactly 3 anchors to be attached for the exclusion zone to take
Q_PROPERTY(QString scope READ scope WRITE setScope) /// > effect.
Q_PROPERTY(KeyboardFocus::Enum keyboardFocus READ keyboardFocus WRITE setKeyboardFocus NOTIFY keyboardFocusChanged) Q_PROPERTY(qint32 exclusionZone READ exclusiveZone WRITE setExclusiveZone NOTIFY exclusionZoneChanged);
Q_PROPERTY(ScreenConfiguration::Enum screenConfiguration READ screenConfiguration WRITE setScreenConfiguration) /// Offsets from the sides of the screen.
///
/// > [!INFO] Only applies to edges with anchors
Q_PROPERTY(Margins margins READ margins WRITE setMargins NOTIFY marginsChanged);
/// The shell layer the window sits in. Defaults to `Layer.Top`.
Q_PROPERTY(Layer::Enum layer READ layer WRITE setLayer NOTIFY layerChanged);
Q_PROPERTY(QString scope READ scope WRITE setScope);
/// The degree of keyboard focus taken. Defaults to `KeyboardFocus.None`.
Q_PROPERTY(KeyboardFocus::Enum keyboardFocus READ keyboardFocus WRITE setKeyboardFocus NOTIFY keyboardFocusChanged);
Q_PROPERTY(ScreenConfiguration::Enum screenConfiguration READ screenConfiguration WRITE setScreenConfiguration);
Q_PROPERTY(bool closeOnDismissed READ closeOnDismissed WRITE setCloseOnDismissed); Q_PROPERTY(bool closeOnDismissed READ closeOnDismissed WRITE setCloseOnDismissed);
Q_CLASSINFO("DefaultProperty", "data");
QML_ELEMENT; QML_ELEMENT;
// clang-format on // clang-format on

13
src/cpp/module.md Normal file
View file

@ -0,0 +1,13 @@
name = "QuickShell"
description = "Core QuickShell types"
headers = [
"qmlglobal.hpp",
"qmlscreen.hpp",
"scavenge.hpp",
"shell.hpp",
"variants.hpp",
"proxywindow.hpp",
"layershell.hpp",
]
-----
The core types provided by QuickShell

View file

@ -20,10 +20,29 @@
// like anchors must use `item`. // like anchors must use `item`.
class ProxyWindowBase: public Scavenger { class ProxyWindowBase: public Scavenger {
Q_OBJECT; Q_OBJECT;
/// The content item of the window.
Q_PROPERTY(QQuickItem* item READ item CONSTANT); Q_PROPERTY(QQuickItem* item READ item CONSTANT);
/// The visibility of the window.
///
/// > [!INFO] Windows are not visible by default so you will need to set this to make the window
/// appear.
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged); Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged);
Q_PROPERTY(qint32 width READ width WRITE setWidth NOTIFY widthChanged); Q_PROPERTY(qint32 width READ width WRITE setWidth NOTIFY widthChanged);
Q_PROPERTY(qint32 height READ height WRITE setHeight NOTIFY heightChanged); Q_PROPERTY(qint32 height READ height WRITE setHeight NOTIFY heightChanged);
/// The background color of the window. Defaults to white.
///
/// > [!WARNING] This seems to behave weirdly when using transparent colors on some systems.
/// > Using a colored content item over a transparent window is the recommended way to work around this:
/// > ```qml
/// > ProxyWindow {
/// > Rectangle {
/// > anchors.fill: parent
/// > color: "#20ffffff"
/// >
/// > // your content here
/// > }
/// > }
/// > ```
Q_PROPERTY(QColor color READ color WRITE setColor); Q_PROPERTY(QColor color READ color WRITE setColor);
Q_PROPERTY(QQmlListProperty<QObject> data READ data); Q_PROPERTY(QQmlListProperty<QObject> data READ data);
Q_CLASSINFO("DefaultProperty", "data"); Q_CLASSINFO("DefaultProperty", "data");

View file

@ -33,7 +33,8 @@ qsizetype QuickShellGlobal::screensCount(QQmlListProperty<QuickShellScreenInfo>*
return static_cast<QuickShellGlobal*>(prop->object)->mScreens.size(); // NOLINT return static_cast<QuickShellGlobal*>(prop->object)->mScreens.size(); // NOLINT
} }
QuickShellScreenInfo* QuickShellGlobal::screenAt(QQmlListProperty<QuickShellScreenInfo>* prop, qsizetype i) { QuickShellScreenInfo*
QuickShellGlobal::screenAt(QQmlListProperty<QuickShellScreenInfo>* prop, qsizetype i) {
return static_cast<QuickShellGlobal*>(prop->object)->mScreens.at(i); // NOLINT return static_cast<QuickShellGlobal*>(prop->object)->mScreens.at(i); // NOLINT
} }

View file

@ -11,6 +11,26 @@
class QuickShellGlobal: public QObject { class QuickShellGlobal: public QObject {
Q_OBJECT; Q_OBJECT;
/// All currently connected screens.
///
/// This property updates as connected screens change.
///
/// #### Reusing a window on every screen
/// ```qml
/// ShellRoot {
/// Variants {
/// ProxyShellWindow {
/// // ...
/// }
///
/// // see Variants for details
/// variants: QuickShell.screens.map(screen => ({ screen }))
/// }
/// }
/// ```
///
/// This creates an instance of your window once on every screen.
/// As screens are added or removed your window will be created or destroyed on those screens.
Q_PROPERTY(QQmlListProperty<QuickShellScreenInfo> screens READ screens NOTIFY screensChanged); Q_PROPERTY(QQmlListProperty<QuickShellScreenInfo> screens READ screens NOTIFY screensChanged);
QML_SINGLETON; QML_SINGLETON;
QML_NAMED_ELEMENT(QuickShell); QML_NAMED_ELEMENT(QuickShell);
@ -20,11 +40,47 @@ public:
QQmlListProperty<QuickShellScreenInfo> screens(); QQmlListProperty<QuickShellScreenInfo> screens();
/// Reload the shell from the [ShellRoot].
///
/// `hard` - perform a hard reload. If this is false, QuickShell will attempt to reuse windows
/// that already exist. If true windows will be recreated.
///
/// > [!INFO] QuickShell can only reuse windows that are in a hierarchy of elements known
/// > internally as `Scavengeable`. These types are [ShellRoot] and [Variants].
/// >
/// > ```qml
/// > // this will reuse the window on reload
/// > ShellRoot {
/// > Varaints {
/// > ProxyShellWindow {
/// > // ...
/// > }
/// >
/// > // ...
/// > }
/// > }
/// >
/// > // this will NOT reuse the window on reload,
/// > // and will destroy the old one / create a new one every time
/// > ShellRoot {
/// > AnyNonScavengeableType {
/// > ProxyShellWindow {
/// > // ...
/// > }
/// >
/// > // ...
/// > }
/// > }
/// > ```
/// >
/// > [ShellRoot]: ../shellroot
/// > [Variants]: ../variants
Q_INVOKABLE void reload(bool hard);
signals: signals:
void screensChanged(); void screensChanged();
public slots: public slots:
void reload(bool hard);
void updateScreens(); void updateScreens();
private: private:

View file

@ -8,16 +8,34 @@
#include <qtypes.h> #include <qtypes.h>
// unfortunately QQuickScreenInfo is private. // unfortunately QQuickScreenInfo is private.
/// Monitor object useful for setting the monitor for a [ProxyShellWindow]
/// or querying information about the monitor.
///
/// > [!WARNING] If the monitor is disconnected than any stored copies of its ShellMonitor will
/// > be marked as dangling and all properties will return default values.
/// > Reconnecting the monitor will not reconnect it to the ShellMonitor object.
///
/// Due to some technical limitations, it was not possible to reuse the native qml [Screen] type.
///
/// [ProxyShellWindow]: ../proxyshellwindow
/// [Screen]: https://doc.qt.io/qt-6/qml-qtquick-screen.html
class QuickShellScreenInfo: public QObject { class QuickShellScreenInfo: public QObject {
Q_OBJECT; Q_OBJECT;
QML_ELEMENT; QML_NAMED_ELEMENT(ShellScreen);
QML_UNCREATABLE("QuickShellScreenInfo can only be obtained via QuickShell.screens"); QML_UNCREATABLE("ShellScreen can only be obtained via QuickShell.screens");
// clang-format off // clang-format off
/// The name of the screen as seen by the operating system.
///
/// Usually something like `DP-1`, `HDMI-1`, `eDP-1`.
Q_PROPERTY(QString name READ name NOTIFY nameChanged); Q_PROPERTY(QString name READ name NOTIFY nameChanged);
Q_PROPERTY(qint32 width READ width NOTIFY widthChanged); Q_PROPERTY(qint32 width READ width NOTIFY widthChanged);
Q_PROPERTY(qint32 height READ height NOTIFY heightChanged); Q_PROPERTY(qint32 height READ height NOTIFY heightChanged);
/// The number of physical pixels per millimeter.
Q_PROPERTY(qreal pixelDensity READ pixelDensity NOTIFY logicalPixelDensityChanged); Q_PROPERTY(qreal pixelDensity READ pixelDensity NOTIFY logicalPixelDensityChanged);
/// The number of device-independent (scaled) pixels per millimeter.
Q_PROPERTY(qreal logicalPixelDensity READ logicalPixelDensity NOTIFY logicalPixelDensityChanged); Q_PROPERTY(qreal logicalPixelDensity READ logicalPixelDensity NOTIFY logicalPixelDensityChanged);
/// The ratio between physical pixels and device-independent (scaled) pixels.
Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio NOTIFY devicePixelRatioChanged); Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio NOTIFY devicePixelRatioChanged);
Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged); Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged);
Q_PROPERTY(Qt::ScreenOrientation primatyOrientation READ primaryOrientation NOTIFY primaryOrientationChanged); Q_PROPERTY(Qt::ScreenOrientation primatyOrientation READ primaryOrientation NOTIFY primaryOrientationChanged);

View file

@ -17,10 +17,13 @@ public:
bool mWatchFiles = true; bool mWatchFiles = true;
}; };
///! Root config element
class ShellRoot: public Scavenger, virtual public Scavengeable { class ShellRoot: public Scavenger, virtual public Scavengeable {
Q_OBJECT; Q_OBJECT;
/// If `config.watchFiles` is true the configuration will be reloaded whenever it changes.
/// Defaults to true.
Q_PROPERTY(ShellConfig config READ config WRITE setConfig); Q_PROPERTY(ShellConfig config READ config WRITE setConfig);
Q_PROPERTY(QQmlListProperty<QObject> components READ components FINAL); Q_PROPERTY(QQmlListProperty<QObject> components READ components);
Q_CLASSINFO("DefaultProperty", "components"); Q_CLASSINFO("DefaultProperty", "components");
QML_ELEMENT; QML_ELEMENT;

View file

@ -21,10 +21,20 @@ public:
QList<QPair<K, V>> values; QList<QPair<K, V>> values;
}; };
///! Creates instances of a component based on a given set of variants.
/// Creates and destroys instances of the given component when the given property changes.
///
/// See [QuickShell.screens] for an example of using `Variants` to create copies of a window per
/// screen.
///
/// [QuickShell.screens]: ../quickshell#prop.screens
class Variants: public Scavenger, virtual public Scavengeable { class Variants: public Scavenger, virtual public Scavengeable {
Q_OBJECT; Q_OBJECT;
/// The component to create instances of
Q_PROPERTY(QQmlComponent* component MEMBER mComponent); Q_PROPERTY(QQmlComponent* component MEMBER mComponent);
Q_PROPERTY(QVariantList variants MEMBER mVariants WRITE setVariants); /// The list of sets of properties to create instances with.
/// Each set creates an instance of the component, which are updated when the input sets update.
Q_PROPERTY(QList<QVariant> variants MEMBER mVariants WRITE setVariants);
Q_CLASSINFO("DefaultProperty", "component"); Q_CLASSINFO("DefaultProperty", "component");
QML_ELEMENT; QML_ELEMENT;