File indexing completed on 2024-04-21 16:17:33

0001 /*
0002  *  SPDX-FileCopyrightText: 2012 Alejandro Fiestas Olivares <afiestas@kde.org>
0003  *  SPDX-FileCopyrightText: 2014 Daniel Vrátil <dvratil@redhat.com>
0004  *
0005  *  SPDX-License-Identifier: LGPL-2.1-or-later
0006  */
0007 
0008 #ifndef KSCREEN_CONFIG_H
0009 #define KSCREEN_CONFIG_H
0010 
0011 #include "kscreen_export.h"
0012 #include "output.h"
0013 #include "screen.h"
0014 #include "types.h"
0015 
0016 #include <QHash>
0017 #include <QMetaType>
0018 #include <QObject>
0019 
0020 #include <cstdint>
0021 #include <optional>
0022 
0023 namespace KScreen
0024 {
0025 class Output;
0026 
0027 /**
0028  * Represents a (or the) screen configuration.
0029  *
0030  * This is the main class of KScreen, with it you can use
0031  * the static methods current() to get the systems config and
0032  * setConfig() to apply a config to the system.
0033  *
0034  * Also, you can instantiate an empty Config, this is usually done
0035  * to create a config (with the objective of setting it) from scratch
0036  * and for example unserialize a saved config to it.
0037  *
0038  */
0039 class KSCREEN_EXPORT Config : public QObject
0040 {
0041     Q_OBJECT
0042     Q_PROPERTY(ScreenPtr screen READ screen)
0043     Q_PROPERTY(OutputList outputs READ outputs)
0044 
0045 public:
0046     enum class ValidityFlag {
0047         None = 0x0,
0048         RequireAtLeastOneEnabledScreen = 0x1,
0049     };
0050     Q_ENUM(ValidityFlag)
0051     Q_DECLARE_FLAGS(ValidityFlags, ValidityFlag)
0052 
0053     /** This indicates which features the used backend supports.
0054      *
0055      * @see supportedFeatures
0056      * @since 5.7
0057      */
0058     enum class Feature {
0059         None = 0, ///< None of the mentioned features are supported.
0060         PrimaryDisplay = 1, ///< The backend knows about the concept of a primary display
0061         Writable = 1 << 1, ///< The backend supports setting the config, it's not read-only.
0062         PerOutputScaling = 1 << 2, ///< The backend supports scaling each output individually.
0063         OutputReplication = 1 << 3, ///< The backend supports replication of outputs.
0064         AutoRotation = 1 << 4, ///< The backend supports automatic rotation of outputs.
0065         TabletMode = 1 << 5, ///< The backend supports querying if a device is in tablet mode.
0066         SynchronousOutputChanges = 1 << 6, ///< The backend supports blocking until the output setting changes are applied
0067         XwaylandScales = 1 << 7, ///< The backend supports adapting Xwayland clients to a certain scale
0068     };
0069     Q_ENUM(Feature)
0070     Q_DECLARE_FLAGS(Features, Feature)
0071 
0072     /**
0073      * Validates that a config can be applied in the current system
0074      *
0075      * Each system has different constrains, this method will test
0076      * the given config with those constrains to see if it
0077      * can be applied.
0078      *
0079      * @arg config to be checked
0080      * @flags enable additional optional checks
0081      * @return true if the configuration can be applied, false if not.
0082      * @since 5.3.0
0083      */
0084     static bool canBeApplied(const ConfigPtr &config, ValidityFlags flags);
0085 
0086     /**
0087      * Validates that a config can be applied in the current system
0088      *
0089      * Each system has different constrains, this method will test
0090      * the given config with those constrains to see if it
0091      * can be applied.
0092      *
0093      * @arg config to be checked
0094      * @return true if the configuration can be applied, false if not.
0095      */
0096     static bool canBeApplied(const ConfigPtr &config);
0097 
0098     /**
0099      * Instantiate an empty config
0100      *
0101      * Usually you do not want to use this constructor since there are some
0102      * values that make no sense to set (for example you want the Screen of
0103      * the current systme).
0104      *
0105      * So usually what you do is call current() and then modify
0106      * whatever you need.
0107      */
0108     explicit Config();
0109     ~Config() override;
0110 
0111     /**
0112      * Duplicates the config
0113      *
0114      * @return a new Config instance with same property values
0115      */
0116     ConfigPtr clone() const;
0117 
0118     /**
0119      * Returns an identifying hash for this config in regards to its
0120      * connected outputs.
0121      *
0122      * The hash is calculated with a sorted combination of all
0123      * connected output hashes.
0124      *
0125      * @return sorted hash combination of all connected outputs
0126      * @since 5.15
0127      */
0128     QString connectedOutputsHash() const;
0129 
0130     ScreenPtr screen() const;
0131     void setScreen(const ScreenPtr &screen);
0132 
0133     OutputPtr output(int outputId) const;
0134     OutputList outputs() const;
0135     OutputList connectedOutputs() const;
0136 
0137     /**
0138      * Find primary output. Primary output is the output with priority 1. May be
0139      * null.
0140      */
0141     OutputPtr primaryOutput() const;
0142     /**
0143      * Setting output to be the primary one is equivalent to setting its
0144      * priority to 1.
0145      */
0146     void setPrimaryOutput(const OutputPtr &output);
0147     /**
0148      * Add an output to this configuration.
0149      *
0150      * This method does not ensure consistency of priorities, it is up to the
0151      * caller to perform necessary adjustments afterwards. The reason is that it
0152      * might be used in a loop (such as adding all outputs) where committing
0153      * intermediate states is undesirable.
0154      */
0155     void addOutput(const OutputPtr &output);
0156     /**
0157      * Remove an output with matching ID from this configuration.
0158      *
0159      * This method does not ensure consistency of priorities, it is up to the
0160      * caller to perform necessary adjustments afterwards. The reason is that it
0161      * might be used in a loop (such as removing all outputs) where committing
0162      * intermediate states is undesirable.
0163      */
0164     void removeOutput(int outputId);
0165     /**
0166      * Replace all existing outputs with the given ones.
0167      *
0168      * Unlike addOutput and removeOutput which operate on individual items
0169      * presumably in a loop, this method will call adjustPriorities() before
0170      * returning.
0171      */
0172     void setOutputs(const OutputList &outputs);
0173 
0174     /**
0175      * Set output's priority and call adjustPriorities() trying to retain
0176      * relative ordering of the output. Setting priority to zero with this
0177      * method will disable the output, otherwise the output will be enabled.
0178      */
0179     void setOutputPriority(const OutputPtr &output, uint32_t priority);
0180 
0181     void setOutputPriorities(QMap<OutputPtr, uint32_t> &priorities);
0182 
0183     /**
0184      * Ensure consistency and continuity of priorities.
0185      *
0186      * Most methods operating on outputs are doing so in loop, where committing
0187      * intermediate states is undesirable. This method restores the balance by
0188      * settings priority of all disabled outputs to 0, disabling all outputs
0189      * whose priority is 0 (i.e. it works in both directions), and sorting all
0190      * the remaining ones, such that they are numbered strictly sequentially
0191      * starting from 1.
0192      * @param keep The output, which priority should stay as close as possible
0193      * to its current one. It is not possible to guarantee, but the algorithm
0194      * will do its best to prioritize this output among others, if there happens
0195      * to be multiple ones with the same priority number.
0196      */
0197     void adjustPriorities(std::optional<OutputPtr> keep = std::nullopt);
0198 
0199     bool isValid() const;
0200     void setValid(bool valid);
0201 
0202     void apply(const ConfigPtr &other);
0203 
0204     /** Indicates features supported by the backend. This exists to allow the user
0205      * to find out which of the features offered by libkscreen are actually supported
0206      * by the backend. Not all backends are writable (QScreen, for example is
0207      * read-only, only XRandR, but not KWayland support the primary display, etc.).
0208      *
0209      * @return Flags for features that are supported for this config, determined by
0210      * the backend.
0211      * @see setSupportedFeatures
0212      * @since 5.7
0213      */
0214     Features supportedFeatures() const;
0215 
0216     /** Sets the features supported by this backend. This should not be called by the
0217      * user, but by the backend.
0218      *
0219      * @see supportedFeatures
0220      * @since 5.7
0221      */
0222     void setSupportedFeatures(const Features &features);
0223 
0224     /**
0225      * Indicates that the device supports switching between a default and a tablet mode. This is
0226      * common for convertibles.
0227      *
0228      * @return true when tablet mode is available, otherwise false
0229      * @see setTabletModeAvailable
0230      * @since 5.18
0231      */
0232     bool tabletModeAvailable() const;
0233 
0234     /** Sets if the device supports a tablet mode. This should not be called by the
0235      * user, but by the backend.
0236      *
0237      * @see tabletModeAvailable
0238      * @since 5.18
0239      */
0240     void setTabletModeAvailable(bool available);
0241 
0242     /**
0243      * Indicates that the device is currently in tablet mode.
0244      *
0245      * @return true when in tablet mode, otherwise false
0246      * @see setTabletModeEngaged
0247      * @since 5.18
0248      */
0249     bool tabletModeEngaged() const;
0250 
0251     /**
0252      * Sets if the device is currently in tablet mode. This should not be called by the
0253      * user, but by the backend.
0254      *
0255      * @see tabletModeEngaged
0256      * @since 5.18
0257      */
0258     void setTabletModeEngaged(bool engaged);
0259 
0260     QRect outputGeometryForOutput(const KScreen::Output &output) const;
0261 
0262     QSizeF logicalSizeForOutput(const KScreen::Output &output) const;
0263 
0264 Q_SIGNALS:
0265     void outputAdded(const KScreen::OutputPtr &output);
0266     void outputRemoved(int outputId);
0267     void prioritiesChanged();
0268 
0269 private:
0270     Q_DISABLE_COPY(Config)
0271 
0272     class Private;
0273     Private *const d;
0274 };
0275 
0276 } // KScreen namespace
0277 
0278 Q_DECLARE_OPERATORS_FOR_FLAGS(KScreen::Config::Features)
0279 
0280 KSCREEN_EXPORT QDebug operator<<(QDebug dbg, const KScreen::ConfigPtr &config);
0281 
0282 #endif // KSCREEN_CONFIG_H