1 /*************************************************************************************
2  *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
3  *  Copyright (C) 2014 by Daniel Vrátil <dvratil@redhat.com>                         *
4  *                                                                                   *
5  *  This library is free software; you can redistribute it and/or                    *
6  *  modify it under the terms of the GNU Lesser General Public                       *
7  *  License as published by the Free Software Foundation; either                     *
8  *  version 2.1 of the License, or (at your option) any later version.               *
9  *                                                                                   *
10  *  This library is distributed in the hope that it will be useful,                  *
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                *
13  *  Lesser General Public License for more details.                                  *
14  *                                                                                   *
15  *  You should have received a copy of the GNU Lesser General Public                 *
16  *  License along with this library; if not, write to the Free Software              *
17  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA       *
18  *************************************************************************************/
19 #ifndef DISMAN_CONFIG_H
20 #define DISMAN_CONFIG_H
21 
22 #include "disman_export.h"
23 #include "screen.h"
24 #include "types.h"
25 
26 #include <QHash>
27 #include <QMetaType>
28 #include <QObject>
29 
30 namespace Disman
31 {
32 
33 /**
34  * Represents a (or the) screen configuration.
35  *
36  * This is the main class of Disman, with it you can use
37  * the static methods current() to get the systems config and
38  * setConfig() to apply a config to the system.
39  *
40  * Also, you can instantiate an empty Config, this is usually done
41  * to create a config (with the objective of setting it) from scratch
42  * and for example unserialize a saved config to it.
43  *
44  */
45 class DISMAN_EXPORT Config : public QObject
46 {
47     Q_OBJECT
48 
49 public:
50     enum class Cause {
51         unknown,
52         file,
53         generated,
54         interactive,
55     };
56 
57     enum class ValidityFlag {
58         None = 0x0,
59         RequireAtLeastOneEnabledScreen = 0x1,
60     };
61     Q_DECLARE_FLAGS(ValidityFlags, ValidityFlag)
62 
63     /** This indicates which features the used backend supports.
64      *
65      * @see supported_features
66      * @since 5.7
67      */
68     enum class Feature {
69         None = 0,           ///< None of the mentioned features are supported.
70         PrimaryDisplay = 1, ///< The backend knows about the concept of a primary display, this is
71                             ///< mostly limited to X11.
72         Writable = 1 << 1,  ///< The backend supports setting the config, it's not read-only.
73         PerOutputScaling = 1 << 2,  ///< The backend supports scaling each output individually.
74         OutputReplication = 1 << 3, ///< The backend supports replication of outputs.
75         AutoRotation = 1 << 4,      ///< The backend supports automatic rotation of outputs.
76         TabletMode = 1 << 5, ///< The backend supports querying if a device is in tablet mode.
77     };
78     Q_DECLARE_FLAGS(Features, Feature)
79 
80     /**
81      * Validates that a config can be applied in the current system
82      *
83      * Each system has different constrains, this method will test
84      * the given config with those constrains to see if it
85      * can be applied.
86      *
87      * @arg config to be checked
88      * @flags enable additional optional checks
89      * @return true if the configuration can be applied, false if not.
90      * @since 5.3.0
91      */
92     static bool can_be_applied(const ConfigPtr& config, ValidityFlags flags);
93 
94     /**
95      * Validates that a config can be applied in the current system
96      *
97      * Each system has different constrains, this method will test
98      * the given config with those constrains to see if it
99      * can be applied.
100      *
101      * @arg config to be checked
102      * @return true if the configuration can be applied, false if not.
103      */
104     static bool can_be_applied(const ConfigPtr& config);
105 
106     /**
107      * Instantiate an empty config
108      *
109      * Usually you do not want to use this constructor since there are some
110      * values that make no sense to set (for example you want the Screen of
111      * the current systme).
112      *
113      * So usually what you do is call current() and then modify
114      * whatever you need.
115      */
116     Config();
117     explicit Config(Cause cause);
118     ~Config() override;
119 
120     /**
121      * Duplicates the config
122      *
123      * @return a new Config instance with same property values
124      */
125     ConfigPtr clone() const;
126 
127     /**
128      * Compares the data of this object with @param config.
129      *
130      * @return true if data is same otherwise false
131      */
132     bool compare(ConfigPtr config) const;
133 
134     /**
135      * Returns an identifying hash for this config in regards to its
136      * connected outputs.
137      *
138      * The hash is calculated with a sorted combination of all
139      * connected output hashes.
140      *
141      * @return sorted hash combination of all connected outputs
142      * @since 5.15
143      */
144     QString hash() const;
145 
146     Cause cause() const;
147     void set_cause(Cause cause);
148 
149     ScreenPtr screen() const;
150     void setScreen(const ScreenPtr& screen);
151 
152     OutputPtr output(int outputId) const;
153     OutputMap outputs() const;
154 
155     OutputPtr primary_output() const;
156     void set_primary_output(const OutputPtr& output);
157 
158     void add_output(const OutputPtr& output);
159     void remove_output(int outputId);
160     void set_outputs(OutputMap const& outputs);
161 
162     bool valid() const;
163     void set_valid(bool valid);
164 
165     void apply(const ConfigPtr& other);
166 
167     /** Indicates features supported by the backend. This exists to allow the user
168      * to find out which of the features offered by disman are actually supported
169      * by the backend. Not all backends are writable (QScreen, for example is
170      * read-only, only XRandR, but not KWayland support the primary display, etc.).
171      *
172      * @return Flags for features that are supported for this config, determined by
173      * the backend.
174      * @see set_supported_features
175      * @since 5.7
176      */
177     Features supported_features() const;
178 
179     /** Sets the features supported by this backend. This should not be called by the
180      * user, but by the backend.
181      *
182      * @see supported_features
183      * @since 5.7
184      */
185     void set_supported_features(const Features& features);
186 
187     /**
188      * Indicates that the device supports switching between a default and a tablet mode. This is
189      * common for convertibles.
190      *
191      * @return true when tablet mode is available, otherwise false
192      * @see set_tablet_mode_available
193      * @since 5.18
194      */
195     bool tablet_mode_available() const;
196 
197     /** Sets if the device supports a tablet mode. This should not be called by the
198      * user, but by the backend.
199      *
200      * @see tablet_mode_available
201      * @since 5.18
202      */
203     void set_tablet_mode_available(bool available);
204 
205     /**
206      * Indicates that the device is currently in tablet mode.
207      *
208      * @return true when in tablet mode, otherwise false
209      * @see set_tablet_mode_engaged
210      * @since 5.18
211      */
212     bool tablet_mode_engaged() const;
213 
214     /**
215      * Sets if the device is currently in tablet mode. This should not be called by the
216      * user, but by the backend.
217      *
218      * @see tabletModeEngaged
219      * @since 5.18
220      */
221     void set_tablet_mode_engaged(bool engaged);
222 
223     /**
224      * Returns the Output @param output replicates if @param output is a replica, otherwise null.
225      *
226      * @param output to find replication source for
227      * @return replication source or null
228      */
229     OutputPtr replication_source(OutputPtr const& output);
230 
231     std::string log() const;
232 
233 Q_SIGNALS:
234     void output_added(const Disman::OutputPtr& output);
235     void output_removed(int outputId);
236     void primary_output_changed(const Disman::OutputPtr& output);
237 
238 private:
239     Q_DISABLE_COPY(Config)
240 
241     class Private;
242     Private* const d;
243 };
244 
245 }
246 
247 Q_DECLARE_OPERATORS_FOR_FLAGS(Disman::Config::Features)
248 
249 DISMAN_EXPORT QDebug operator<<(QDebug dbg, const Disman::ConfigPtr& config);
250 
251 #endif
252