1 #ifdef HAVE_CONFIG_H
2 #include "clutter-build-config.h"
3 #endif
4 
5 #include <glib-object.h>
6 
7 #include "clutter-actor.h"
8 #include "clutter-stage-window.h"
9 #include "clutter-private.h"
10 
11 #define clutter_stage_window_get_type   _clutter_stage_window_get_type
12 
13 typedef ClutterStageWindowIface ClutterStageWindowInterface;
14 
15 G_DEFINE_INTERFACE (ClutterStageWindow, clutter_stage_window, G_TYPE_OBJECT);
16 
17 static void
clutter_stage_window_default_init(ClutterStageWindowInterface * iface)18 clutter_stage_window_default_init (ClutterStageWindowInterface *iface)
19 {
20   GParamSpec *pspec;
21 
22   pspec = g_param_spec_object ("backend",
23                                "Backend",
24                                "Back pointer to the Backend instance",
25                                CLUTTER_TYPE_BACKEND,
26                                G_PARAM_WRITABLE |
27                                G_PARAM_CONSTRUCT_ONLY |
28                                G_PARAM_STATIC_STRINGS);
29   g_object_interface_install_property (iface, pspec);
30 
31   pspec = g_param_spec_object ("wrapper",
32                                "Wrapper",
33                                "Back pointer to the Stage actor",
34                                CLUTTER_TYPE_STAGE,
35                                G_PARAM_WRITABLE |
36                                G_PARAM_CONSTRUCT_ONLY |
37                                G_PARAM_STATIC_STRINGS);
38   g_object_interface_install_property (iface, pspec);
39 }
40 
41 ClutterActor *
_clutter_stage_window_get_wrapper(ClutterStageWindow * window)42 _clutter_stage_window_get_wrapper (ClutterStageWindow *window)
43 {
44   return CLUTTER_STAGE_WINDOW_GET_IFACE (window)->get_wrapper (window);
45 }
46 
47 void
_clutter_stage_window_set_title(ClutterStageWindow * window,const gchar * title)48 _clutter_stage_window_set_title (ClutterStageWindow *window,
49                                  const gchar        *title)
50 {
51   ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
52 
53   if (iface->set_title)
54     iface->set_title (window, title);
55 }
56 
57 void
_clutter_stage_window_set_fullscreen(ClutterStageWindow * window,gboolean is_fullscreen)58 _clutter_stage_window_set_fullscreen (ClutterStageWindow *window,
59                                       gboolean            is_fullscreen)
60 {
61   ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
62 
63   if (iface->set_fullscreen)
64     iface->set_fullscreen (window, is_fullscreen);
65 }
66 
67 void
_clutter_stage_window_set_cursor_visible(ClutterStageWindow * window,gboolean is_visible)68 _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window,
69                                           gboolean            is_visible)
70 {
71   ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
72 
73   if (iface->set_cursor_visible)
74     iface->set_cursor_visible (window, is_visible);
75 }
76 
77 void
_clutter_stage_window_set_user_resizable(ClutterStageWindow * window,gboolean is_resizable)78 _clutter_stage_window_set_user_resizable (ClutterStageWindow *window,
79                                           gboolean            is_resizable)
80 {
81   CLUTTER_STAGE_WINDOW_GET_IFACE (window)->set_user_resizable (window,
82                                                                is_resizable);
83 }
84 
85 gboolean
_clutter_stage_window_realize(ClutterStageWindow * window)86 _clutter_stage_window_realize (ClutterStageWindow *window)
87 {
88   return CLUTTER_STAGE_WINDOW_GET_IFACE (window)->realize (window);
89 }
90 
91 void
_clutter_stage_window_unrealize(ClutterStageWindow * window)92 _clutter_stage_window_unrealize (ClutterStageWindow *window)
93 {
94   CLUTTER_STAGE_WINDOW_GET_IFACE (window)->unrealize (window);
95 }
96 
97 void
_clutter_stage_window_show(ClutterStageWindow * window,gboolean do_raise)98 _clutter_stage_window_show (ClutterStageWindow *window,
99                             gboolean            do_raise)
100 {
101   CLUTTER_STAGE_WINDOW_GET_IFACE (window)->show (window, do_raise);
102 }
103 
104 void
_clutter_stage_window_hide(ClutterStageWindow * window)105 _clutter_stage_window_hide (ClutterStageWindow *window)
106 {
107   CLUTTER_STAGE_WINDOW_GET_IFACE (window)->hide (window);
108 }
109 
110 void
_clutter_stage_window_resize(ClutterStageWindow * window,gint width,gint height)111 _clutter_stage_window_resize (ClutterStageWindow *window,
112                               gint                width,
113                               gint                height)
114 {
115   CLUTTER_STAGE_WINDOW_GET_IFACE (window)->resize (window, width, height);
116 }
117 
118 void
_clutter_stage_window_get_geometry(ClutterStageWindow * window,cairo_rectangle_int_t * geometry)119 _clutter_stage_window_get_geometry (ClutterStageWindow    *window,
120                                     cairo_rectangle_int_t *geometry)
121 {
122   CLUTTER_STAGE_WINDOW_GET_IFACE (window)->get_geometry (window, geometry);
123 }
124 
125 void
_clutter_stage_window_schedule_update(ClutterStageWindow * window,int sync_delay)126 _clutter_stage_window_schedule_update  (ClutterStageWindow *window,
127                                         int                 sync_delay)
128 {
129   ClutterStageWindowIface *iface;
130 
131   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
132 
133   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
134   if (iface->schedule_update == NULL)
135     {
136       g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS));
137       return;
138     }
139 
140   iface->schedule_update (window, sync_delay);
141 }
142 
143 gint64
_clutter_stage_window_get_update_time(ClutterStageWindow * window)144 _clutter_stage_window_get_update_time (ClutterStageWindow *window)
145 {
146   ClutterStageWindowIface *iface;
147 
148   g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0);
149 
150   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
151   if (iface->get_update_time == NULL)
152     {
153       g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS));
154       return 0;
155     }
156 
157   return iface->get_update_time (window);
158 }
159 
160 void
_clutter_stage_window_clear_update_time(ClutterStageWindow * window)161 _clutter_stage_window_clear_update_time (ClutterStageWindow *window)
162 {
163   ClutterStageWindowIface *iface;
164 
165   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
166 
167   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
168   if (iface->clear_update_time == NULL)
169     {
170       g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS));
171       return;
172     }
173 
174   iface->clear_update_time (window);
175 }
176 
177 void
_clutter_stage_window_add_redraw_clip(ClutterStageWindow * window,cairo_rectangle_int_t * stage_clip)178 _clutter_stage_window_add_redraw_clip (ClutterStageWindow    *window,
179                                        cairo_rectangle_int_t *stage_clip)
180 {
181   ClutterStageWindowIface *iface;
182 
183   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
184 
185   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
186   if (iface->add_redraw_clip != NULL)
187     iface->add_redraw_clip (window, stage_clip);
188 }
189 
190 /* Determines if the backend will clip the rendering of the next
191  * frame.
192  *
193  * Note: at the start of each new frame there is an implied clip that
194  * clips everything (i.e. nothing would be drawn) so this function
195  * will return True at the start of a new frame if the backend
196  * supports clipped redraws.
197  */
198 gboolean
_clutter_stage_window_has_redraw_clips(ClutterStageWindow * window)199 _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window)
200 {
201   ClutterStageWindowIface *iface;
202 
203   g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
204 
205   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
206   if (iface->has_redraw_clips != NULL)
207     return iface->has_redraw_clips (window);
208 
209   return FALSE;
210 }
211 
212 /* Determines if the backend will discard any additional redraw clips
213  * and instead promote them to a full stage redraw.
214  *
215  * The ideas is that backend may have some heuristics that cause it to
216  * give up tracking redraw clips so this can be used to avoid the cost
217  * of calculating a redraw clip when we know it's going to be ignored
218  * anyway.
219  */
220 gboolean
_clutter_stage_window_ignoring_redraw_clips(ClutterStageWindow * window)221 _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window)
222 {
223   ClutterStageWindowIface *iface;
224 
225   g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
226 
227   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
228   if (iface->ignoring_redraw_clips != NULL)
229     return iface->ignoring_redraw_clips (window);
230 
231   return TRUE;
232 }
233 
234 gboolean
_clutter_stage_window_get_redraw_clip_bounds(ClutterStageWindow * window,cairo_rectangle_int_t * stage_clip)235 _clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow    *window,
236                                               cairo_rectangle_int_t *stage_clip)
237 {
238   ClutterStageWindowIface *iface;
239 
240   g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
241 
242   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
243   if (iface->get_redraw_clip_bounds != NULL)
244     return iface->get_redraw_clip_bounds (window, stage_clip);
245 
246   return FALSE;
247 }
248 
249 void
_clutter_stage_window_set_accept_focus(ClutterStageWindow * window,gboolean accept_focus)250 _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
251                                         gboolean            accept_focus)
252 {
253   ClutterStageWindowIface *iface;
254 
255   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
256 
257   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
258   if (iface->set_accept_focus)
259     iface->set_accept_focus (window, accept_focus);
260 }
261 
262 void
_clutter_stage_window_redraw(ClutterStageWindow * window)263 _clutter_stage_window_redraw (ClutterStageWindow *window)
264 {
265   ClutterStageWindowIface *iface;
266 
267   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
268 
269   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
270   if (iface->redraw)
271     iface->redraw (window);
272 }
273 
274 
275 void
_clutter_stage_window_get_dirty_pixel(ClutterStageWindow * window,ClutterStageView * view,int * x,int * y)276 _clutter_stage_window_get_dirty_pixel (ClutterStageWindow *window,
277                                        ClutterStageView   *view,
278                                        int *x, int *y)
279 {
280   ClutterStageWindowIface *iface;
281 
282   *x = 0;
283   *y = 0;
284 
285   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
286 
287   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
288   if (iface->get_dirty_pixel)
289     iface->get_dirty_pixel (window, view, x, y);
290 }
291 
292 gboolean
_clutter_stage_window_can_clip_redraws(ClutterStageWindow * window)293 _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window)
294 {
295   ClutterStageWindowIface *iface;
296 
297   g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
298 
299   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
300   if (iface->can_clip_redraws != NULL)
301     return iface->can_clip_redraws (window);
302 
303   return FALSE;
304 }
305 
306 GList *
_clutter_stage_window_get_views(ClutterStageWindow * window)307 _clutter_stage_window_get_views (ClutterStageWindow *window)
308 {
309   ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
310 
311   return iface->get_views (window);
312 }
313 
314 void
_clutter_stage_window_finish_frame(ClutterStageWindow * window)315 _clutter_stage_window_finish_frame (ClutterStageWindow *window)
316 {
317   ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
318 
319   if (iface->finish_frame)
320     iface->finish_frame (window);
321 }
322 
323 int64_t
_clutter_stage_window_get_frame_counter(ClutterStageWindow * window)324 _clutter_stage_window_get_frame_counter (ClutterStageWindow *window)
325 {
326   ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
327 
328   if (iface->get_frame_counter)
329     return iface->get_frame_counter (window);
330   else
331     return 0;
332 }
333