File indexing completed on 2024-05-05 09:51:11

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