1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2020 Red Hat
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18 
19 #include "config.h"
20 
21 #include "gdktoplevellayout.h"
22 
23 #include "gdkmonitor.h"
24 
25 /**
26  * GdkToplevelLayout:
27  *
28  * The `GdkToplevelLayout` struct contains information that
29  * is necessary to present a sovereign window on screen.
30  *
31  * The `GdkToplevelLayout` struct is necessary for using
32  * [method@Gdk.Toplevel.present].
33  *
34  * Toplevel surfaces are sovereign windows that can be presented
35  * to the user in various states (maximized, on all workspaces,
36  * etc).
37  */
38 struct _GdkToplevelLayout
39 {
40   /* < private >*/
41   grefcount ref_count;
42 
43   guint resizable  : 1;
44 
45   guint maximized_valid : 1;
46   guint maximized  : 1;
47   guint fullscreen_valid : 1;
48   guint fullscreen : 1;
49   GdkMonitor *fullscreen_monitor;
50 };
51 
G_DEFINE_BOXED_TYPE(GdkToplevelLayout,gdk_toplevel_layout,gdk_toplevel_layout_ref,gdk_toplevel_layout_unref)52 G_DEFINE_BOXED_TYPE (GdkToplevelLayout, gdk_toplevel_layout,
53                      gdk_toplevel_layout_ref,
54                      gdk_toplevel_layout_unref)
55 
56 /**
57  * gdk_toplevel_layout_new: (constructor)
58  *
59  * Create a toplevel layout description.
60  *
61  * Used together with gdk_toplevel_present() to describe
62  * how a toplevel surface should be placed and behave on-screen.
63  *
64  * The size is in ”application pixels”, not
65  * ”device pixels” (see gdk_surface_get_scale_factor()).
66  *
67  * Returns: (transfer full): newly created instance of `GdkToplevelLayout`
68  */
69 GdkToplevelLayout *
70 gdk_toplevel_layout_new (void)
71 {
72   GdkToplevelLayout *layout;
73 
74   layout = g_new0 (GdkToplevelLayout, 1);
75   g_ref_count_init (&layout->ref_count);
76   layout->resizable = TRUE;
77   layout->maximized_valid = FALSE;
78   layout->maximized = FALSE;
79   layout->fullscreen_valid = FALSE;
80   layout->fullscreen = FALSE;
81   layout->fullscreen_monitor = NULL;
82 
83   return layout;
84 }
85 
86 /**
87  * gdk_toplevel_layout_ref:
88  * @layout: a `GdkToplevelLayout`
89  *
90  * Increases the reference count of @layout.
91  *
92  * Returns: the same @layout
93  */
94 GdkToplevelLayout *
gdk_toplevel_layout_ref(GdkToplevelLayout * layout)95 gdk_toplevel_layout_ref (GdkToplevelLayout *layout)
96 {
97   g_ref_count_inc (&layout->ref_count);
98   return layout;
99 }
100 
101 /**
102  * gdk_toplevel_layout_unref:
103  * @layout: a `GdkToplevelLayout`
104  *
105  * Decreases the reference count of @layout.
106  */
107 void
gdk_toplevel_layout_unref(GdkToplevelLayout * layout)108 gdk_toplevel_layout_unref (GdkToplevelLayout *layout)
109 {
110   if (g_ref_count_dec (&layout->ref_count))
111     {
112       g_clear_object (&layout->fullscreen_monitor);
113       g_free (layout);
114     }
115 }
116 
117 /**
118  * gdk_toplevel_layout_copy:
119  * @layout: a `GdkToplevelLayout`
120  *
121  * Create a new `GdkToplevelLayout` and copy the contents of @layout into it.
122  *
123  * Returns: (transfer full): a copy of @layout.
124  */
125 GdkToplevelLayout *
gdk_toplevel_layout_copy(GdkToplevelLayout * layout)126 gdk_toplevel_layout_copy (GdkToplevelLayout *layout)
127 {
128   GdkToplevelLayout *new_layout;
129 
130   new_layout = g_new0 (GdkToplevelLayout, 1);
131   g_ref_count_init (&new_layout->ref_count);
132 
133   new_layout->resizable = layout->resizable;
134   new_layout->maximized_valid = layout->maximized_valid;
135   new_layout->maximized = layout->maximized;
136   new_layout->fullscreen_valid = layout->fullscreen_valid;
137   new_layout->fullscreen = layout->fullscreen;
138   if (layout->fullscreen_monitor)
139     new_layout->fullscreen_monitor = g_object_ref (layout->fullscreen_monitor);
140 
141   return new_layout;
142 }
143 
144 /**
145  * gdk_toplevel_layout_equal:
146  * @layout: a `GdkToplevelLayout`
147  * @other: another `GdkToplevelLayout`
148  *
149  * Check whether @layout and @other has identical layout properties.
150  *
151  * Returns: %TRUE if @layout and @other have identical layout properties,
152  *   otherwise %FALSE.
153  */
154 gboolean
gdk_toplevel_layout_equal(GdkToplevelLayout * layout,GdkToplevelLayout * other)155 gdk_toplevel_layout_equal (GdkToplevelLayout *layout,
156                            GdkToplevelLayout *other)
157 {
158   g_return_val_if_fail (layout, FALSE);
159   g_return_val_if_fail (other, FALSE);
160 
161   return layout->resizable == other->resizable &&
162          layout->maximized_valid == other->maximized_valid &&
163          layout->maximized == other->maximized &&
164          layout->fullscreen_valid == other->fullscreen_valid &&
165          layout->fullscreen == other->fullscreen &&
166          layout->fullscreen_monitor == other->fullscreen_monitor;
167 }
168 
169 /**
170  * gdk_toplevel_layout_set_resizable:
171  * @layout: a `GdkToplevelLayout`
172  * @resizable: %TRUE to allow resizing
173  *
174  * Sets whether the layout should allow the user
175  * to resize the surface after it has been presented.
176  */
177 void
gdk_toplevel_layout_set_resizable(GdkToplevelLayout * layout,gboolean resizable)178 gdk_toplevel_layout_set_resizable (GdkToplevelLayout *layout,
179                                    gboolean           resizable)
180 {
181   layout->resizable = resizable;
182 }
183 
184 /**
185  * gdk_toplevel_layout_get_resizable:
186  * @layout: a `GdkToplevelLayout`
187  *
188  * Returns whether the layout should allow the user
189  * to resize the surface.
190  *
191  * Returns: %TRUE if the layout is resizable
192  */
193 gboolean
gdk_toplevel_layout_get_resizable(GdkToplevelLayout * layout)194 gdk_toplevel_layout_get_resizable (GdkToplevelLayout *layout)
195 {
196   return layout->resizable;
197 }
198 
199 /**
200  * gdk_toplevel_layout_set_maximized:
201  * @layout: a `GdkToplevelLayout`
202  * @maximized: %TRUE to maximize
203  *
204  * Sets whether the layout should cause the surface
205  * to be maximized when presented.
206  */
207 void
gdk_toplevel_layout_set_maximized(GdkToplevelLayout * layout,gboolean maximized)208 gdk_toplevel_layout_set_maximized (GdkToplevelLayout *layout,
209                                    gboolean           maximized)
210 {
211   layout->maximized_valid = TRUE;
212   layout->maximized = maximized;
213 }
214 
215 /**
216  * gdk_toplevel_layout_get_maximized:
217  * @layout: a `GdkToplevelLayout`
218  * @maximized: (out): set to %TRUE if the toplevel should be maximized
219  *
220  * If the layout specifies whether to the toplevel should go maximized,
221  * the value pointed to by @maximized is set to %TRUE if it should go
222  * fullscreen, or %FALSE, if it should go unmaximized.
223  *
224  * Returns: whether the @layout specifies the maximized state for the toplevel
225  */
226 gboolean
gdk_toplevel_layout_get_maximized(GdkToplevelLayout * layout,gboolean * maximized)227 gdk_toplevel_layout_get_maximized (GdkToplevelLayout *layout,
228                                    gboolean          *maximized)
229 {
230   if (layout->maximized_valid)
231     {
232       *maximized = layout->maximized;
233       return TRUE;
234     }
235 
236   return FALSE;
237 }
238 
239 /**
240  * gdk_toplevel_layout_set_fullscreen:
241  * @layout: a `GdkToplevelLayout`
242  * @fullscreen: %TRUE to fullscreen the surface
243  * @monitor: (nullable): the monitor to fullscreen on
244  *
245  * Sets whether the layout should cause the surface
246  * to be fullscreen when presented.
247  */
248 void
gdk_toplevel_layout_set_fullscreen(GdkToplevelLayout * layout,gboolean fullscreen,GdkMonitor * monitor)249 gdk_toplevel_layout_set_fullscreen (GdkToplevelLayout *layout,
250                                     gboolean           fullscreen,
251                                     GdkMonitor        *monitor)
252 {
253   layout->fullscreen_valid = TRUE;
254   layout->fullscreen = fullscreen;
255   if (monitor)
256     layout->fullscreen_monitor = g_object_ref (monitor);
257 }
258 
259 /**
260  * gdk_toplevel_layout_get_fullscreen:
261  * @layout: a ``GdkToplevelLayout`
262  * @fullscreen: (out): location to store whether the toplevel should be fullscreen
263  *
264  * If the layout specifies whether to the toplevel should go fullscreen,
265  * the value pointed to by @fullscreen is set to %TRUE if it should go
266  * fullscreen, or %FALSE, if it should go unfullscreen.
267  *
268  * Returns: whether the @layout specifies the fullscreen state for the toplevel
269  */
270 gboolean
gdk_toplevel_layout_get_fullscreen(GdkToplevelLayout * layout,gboolean * fullscreen)271 gdk_toplevel_layout_get_fullscreen (GdkToplevelLayout *layout,
272                                     gboolean          *fullscreen)
273 {
274   if (layout->fullscreen_valid)
275     {
276       *fullscreen = layout->fullscreen;
277       return TRUE;
278     }
279 
280   return FALSE;
281 }
282 
283 /**
284  * gdk_toplevel_layout_get_fullscreen_monitor:
285  * @layout: a `GdkToplevelLayout`
286  *
287  * Returns the monitor that the layout is fullscreening
288  * the surface on.
289  *
290  * Returns: (nullable) (transfer none): the monitor on which @layout fullscreens
291  */
292 GdkMonitor *
gdk_toplevel_layout_get_fullscreen_monitor(GdkToplevelLayout * layout)293 gdk_toplevel_layout_get_fullscreen_monitor (GdkToplevelLayout *layout)
294 {
295   return layout->fullscreen_monitor;
296 }
297