1 /*
2  * Copyright (C) 2021 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17  * 02111-1307, USA.
18  *
19  */
20 
21 #include "config.h"
22 
23 #include "backends/meta-virtual-monitor.h"
24 
25 #include "backends/meta-crtc.h"
26 #include "backends/meta-crtc-mode.h"
27 #include "backends/meta-output.h"
28 
29 enum
30 {
31   DESTROY,
32 
33   N_SIGNALS
34 };
35 
36 static guint signals[N_SIGNALS] = { 0 };
37 
38 enum
39 {
40   PROP_0,
41 
42   PROP_CRTC,
43   PROP_CRTC_MODE,
44   PROP_OUTPUT,
45 
46   N_PROPS
47 };
48 
49 static GParamSpec *obj_props[N_PROPS];
50 
51 typedef struct _MetaVirtualMonitorPrivate
52 {
53   MetaCrtc *crtc;
54   MetaCrtcMode *crtc_mode;
55   MetaOutput *output;
56 
57   gboolean is_destroyed;
58 } MetaVirtualMonitorPrivate;
59 
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(MetaVirtualMonitor,meta_virtual_monitor,G_TYPE_OBJECT)60 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaVirtualMonitor, meta_virtual_monitor,
61                                      G_TYPE_OBJECT)
62 
63 MetaVirtualMonitorInfo *
64 meta_virtual_monitor_info_new (int         width,
65                                int         height,
66                                float       refresh_rate,
67                                const char *vendor,
68                                const char *product,
69                                const char *serial)
70 {
71   MetaVirtualMonitorInfo *info;
72 
73   info = g_new0 (MetaVirtualMonitorInfo, 1);
74   info->width = width;
75   info->height = height;
76   info->refresh_rate = refresh_rate;
77   info->vendor = g_strdup (vendor);
78   info->product = g_strdup (product);
79   info->serial = g_strdup (serial);
80 
81   return info;
82 }
83 
84 void
meta_virtual_monitor_info_free(MetaVirtualMonitorInfo * info)85 meta_virtual_monitor_info_free (MetaVirtualMonitorInfo *info)
86 {
87   g_free (info->vendor);
88   g_free (info->product);
89   g_free (info->serial);
90   g_free (info);
91 }
92 
93 MetaCrtc *
meta_virtual_monitor_get_crtc(MetaVirtualMonitor * virtual_monitor)94 meta_virtual_monitor_get_crtc (MetaVirtualMonitor *virtual_monitor)
95 {
96   MetaVirtualMonitorPrivate *priv =
97     meta_virtual_monitor_get_instance_private (virtual_monitor);
98 
99   return priv->crtc;
100 }
101 
102 MetaCrtcMode *
meta_virtual_monitor_get_crtc_mode(MetaVirtualMonitor * virtual_monitor)103 meta_virtual_monitor_get_crtc_mode (MetaVirtualMonitor *virtual_monitor)
104 {
105   MetaVirtualMonitorPrivate *priv =
106     meta_virtual_monitor_get_instance_private (virtual_monitor);
107 
108   return priv->crtc_mode;
109 }
110 
111 MetaOutput *
meta_virtual_monitor_get_output(MetaVirtualMonitor * virtual_monitor)112 meta_virtual_monitor_get_output (MetaVirtualMonitor *virtual_monitor)
113 {
114   MetaVirtualMonitorPrivate *priv =
115     meta_virtual_monitor_get_instance_private (virtual_monitor);
116 
117   return priv->output;
118 }
119 
120 static void
meta_virtual_monitor_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)121 meta_virtual_monitor_set_property (GObject      *object,
122                                    guint         prop_id,
123                                    const GValue *value,
124                                    GParamSpec   *pspec)
125 {
126   MetaVirtualMonitor *virtual_monitor = META_VIRTUAL_MONITOR (object);
127   MetaVirtualMonitorPrivate *priv =
128     meta_virtual_monitor_get_instance_private (virtual_monitor);
129 
130   switch (prop_id)
131     {
132     case PROP_CRTC:
133       priv->crtc = g_value_get_object (value);
134       break;
135     case PROP_CRTC_MODE:
136       priv->crtc_mode = g_value_get_object (value);
137       break;
138     case PROP_OUTPUT:
139       priv->output = g_value_get_object (value);
140       break;
141     default:
142       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
143     }
144 }
145 
146 static void
meta_virtual_monitor_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)147 meta_virtual_monitor_get_property (GObject    *object,
148                                    guint       prop_id,
149                                    GValue     *value,
150                                    GParamSpec *pspec)
151 {
152   MetaVirtualMonitor *virtual_monitor = META_VIRTUAL_MONITOR (object);
153   MetaVirtualMonitorPrivate *priv =
154     meta_virtual_monitor_get_instance_private (virtual_monitor);
155 
156   switch (prop_id)
157     {
158     case PROP_CRTC:
159       g_value_set_object (value, priv->crtc);
160       break;
161     case PROP_CRTC_MODE:
162       g_value_set_object (value, priv->crtc_mode);
163       break;
164     case PROP_OUTPUT:
165       g_value_set_object (value, priv->output);
166       break;
167     default:
168       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
169     }
170 }
171 
172 static void
meta_virtual_monitor_dispose(GObject * object)173 meta_virtual_monitor_dispose (GObject *object)
174 {
175   MetaVirtualMonitor *virtual_monitor = META_VIRTUAL_MONITOR (object);
176   MetaVirtualMonitorPrivate *priv =
177     meta_virtual_monitor_get_instance_private (virtual_monitor);
178 
179   if (!priv->is_destroyed)
180     {
181       g_signal_emit (virtual_monitor, signals[DESTROY], 0);
182       priv->is_destroyed = TRUE;
183     }
184 
185   g_clear_object (&priv->crtc);
186   g_clear_object (&priv->crtc_mode);
187   g_clear_object (&priv->output);
188 
189   G_OBJECT_CLASS (meta_virtual_monitor_parent_class)->dispose (object);
190 }
191 
192 static void
meta_virtual_monitor_init(MetaVirtualMonitor * virtual_monitor)193 meta_virtual_monitor_init (MetaVirtualMonitor *virtual_monitor)
194 {
195 }
196 
197 static void
meta_virtual_monitor_class_init(MetaVirtualMonitorClass * klass)198 meta_virtual_monitor_class_init (MetaVirtualMonitorClass *klass)
199 {
200   GObjectClass *object_class = G_OBJECT_CLASS (klass);
201 
202   object_class->set_property = meta_virtual_monitor_set_property;
203   object_class->get_property = meta_virtual_monitor_get_property;
204   object_class->dispose = meta_virtual_monitor_dispose;
205 
206   obj_props[PROP_CRTC] =
207     g_param_spec_object ("crtc",
208                          "crtc",
209                          "The virtual CRTC",
210                          META_TYPE_CRTC,
211                          G_PARAM_READWRITE |
212                          G_PARAM_CONSTRUCT_ONLY |
213                          G_PARAM_STATIC_STRINGS);
214   obj_props[PROP_CRTC_MODE] =
215     g_param_spec_object ("crtc-mode",
216                          "crtc-mode",
217                          "The virtual CRTC mode",
218                          META_TYPE_CRTC_MODE,
219                          G_PARAM_READWRITE |
220                          G_PARAM_CONSTRUCT_ONLY |
221                          G_PARAM_STATIC_STRINGS);
222   obj_props[PROP_OUTPUT] =
223     g_param_spec_object ("output",
224                          "output",
225                          "The virtual output",
226                          META_TYPE_OUTPUT,
227                          G_PARAM_READWRITE |
228                          G_PARAM_CONSTRUCT_ONLY |
229                          G_PARAM_STATIC_STRINGS);
230   g_object_class_install_properties (object_class, N_PROPS, obj_props);
231 
232   signals[DESTROY] =
233     g_signal_new ("destroy",
234                   G_TYPE_FROM_CLASS (klass),
235                   G_SIGNAL_RUN_LAST, 0,
236                   NULL, NULL, NULL,
237                   G_TYPE_NONE, 0);
238 }
239