File indexing completed on 2024-04-28 05:27:39

0001 /*
0002     SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #pragma once
0007 
0008 #include <kscreen/config.h>
0009 #include <kscreen/output.h>
0010 
0011 #include <QAbstractListModel>
0012 #include <QPoint>
0013 #include <optional>
0014 
0015 class ConfigHandler;
0016 
0017 class OutputModel : public QAbstractListModel
0018 {
0019     Q_OBJECT
0020 public:
0021     enum OutputRoles {
0022         EnabledRole = Qt::UserRole + 1,
0023         InternalRole,
0024         PriorityRole,
0025         SizeRole,
0026         /** Position in the graphical view relative to some arbitrary but fixed origin. */
0027         PositionRole,
0028         /** Position for backend relative to most northwest display corner. */
0029         NormalizedPositionRole,
0030         AutoRotateRole,
0031         RotationRole,
0032         ScaleRole,
0033         ResolutionIndexRole,
0034         ResolutionsRole,
0035         ResolutionRole,
0036         RefreshRateIndexRole,
0037         RefreshRatesRole,
0038         ReplicationSourceModelRole,
0039         ReplicationSourceIndexRole,
0040         ReplicasModelRole,
0041         CapabilitiesRole,
0042         OverscanRole,
0043         VrrPolicyRole,
0044         RgbRangeRole,
0045         IccProfileRole,
0046         HdrRole,
0047         SdrBrightnessRole,
0048         MaxBrightnessRole,
0049         SdrGamutWideness,
0050         InteractiveMoveRole, // This output is currently repositioned interactively
0051     };
0052 
0053     explicit OutputModel(ConfigHandler *configHandler);
0054     ~OutputModel() override = default;
0055 
0056     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0057     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0058     bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
0059 
0060     void add(const KScreen::OutputPtr &output);
0061     void remove(int outputId);
0062 
0063     /**
0064      * Resets the origin for calculation of positions to the most northwest display corner
0065      * while keeping the normalized positions untouched.
0066      *
0067      * @return true if some (unnormalized) output position changed on this call, otherwise false.
0068      */
0069     bool normalizePositions();
0070     bool positionsNormalized() const;
0071 
0072     bool isMoving() const;
0073 
0074 Q_SIGNALS:
0075     void positionChanged();
0076     void sizeChanged();
0077 
0078 protected:
0079     QHash<int, QByteArray> roleNames() const override;
0080 
0081 private:
0082     struct Output {
0083         Output()
0084         {
0085         }
0086         Output(const Output &output)
0087             : ptr(output.ptr)
0088             , pos(output.pos)
0089         {
0090         }
0091         Output(Output &&) noexcept = default;
0092         Output(KScreen::OutputPtr _ptr, const QPoint &_pos)
0093             : ptr(_ptr)
0094             , pos(_pos)
0095         {
0096         }
0097         Output &operator=(const Output &output)
0098         {
0099             ptr = output.ptr;
0100             pos = output.pos;
0101             posReset = std::nullopt;
0102             return *this;
0103         }
0104         Output &operator=(Output &&) noexcept = default;
0105 
0106         KScreen::OutputPtr ptr;
0107         QPoint pos;
0108         // Indicates how to restore position when enabling or un-mirroring a screen.
0109         // Negative value of x means that the output was the left-most, and restoring it would require shifting all the other ones to the right.
0110         // Same for the y and shifting down.
0111         std::optional<QPoint> posReset = std::nullopt;
0112         bool moving = false;
0113     };
0114 
0115     void rolesChanged(int outputId, const QList<int> &roles);
0116     QModelIndex indexForOutputId(int outputId) const;
0117 
0118     void resetPosition(Output &output);
0119     void reposition();
0120     void updatePositions();
0121 
0122     /**
0123      * @brief Snaps moved output to others
0124      * @param output the moved output
0125      * @param dest the desired destination to be adjusted by snapping
0126      */
0127     void snap(const Output &output, QPoint &dest);
0128     void maintainSnapping(const Output &changedOutput, const QSize &oldSize, const QSize &newSize);
0129     QPoint mostTopLeftLocationOfPositionableOutputOptionallyIgnoringOneOfThem(std::optional<KScreen::OutputPtr> ignored = std::nullopt) const;
0130 
0131     bool setEnabled(int outputIndex, bool enable);
0132 
0133     bool setResolution(int outputIndex, int resIndex);
0134     bool setRefreshRate(int outputIndex, int refIndex);
0135     bool setRotation(int outputIndex, KScreen::Output::Rotation rotation);
0136 
0137     int resolutionIndex(const KScreen::OutputPtr &output) const;
0138     int refreshRateIndex(const KScreen::OutputPtr &output) const;
0139     QSize resolution(const KScreen::OutputPtr &output) const;
0140     QVariantList resolutionsStrings(const KScreen::OutputPtr &output) const;
0141     QList<QSize> resolutions(const KScreen::OutputPtr &output) const;
0142     QList<float> refreshRates(const KScreen::OutputPtr &output) const;
0143 
0144     bool positionable(const Output &output) const;
0145 
0146     QStringList replicationSourceModel(const KScreen::OutputPtr &output) const;
0147     bool setReplicationSourceIndex(int outputIndex, int sourceIndex);
0148     int replicationSourceIndex(int outputIndex) const;
0149     int replicationSourceId(const Output &output) const;
0150 
0151     QVariantList replicasModel(const KScreen::OutputPtr &output) const;
0152 
0153     QList<Output> m_outputs;
0154 
0155     ConfigHandler *m_config;
0156 };