1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "cairo-dock-log.h"
21 #include "cairo-dock-desklet-manager.h" // cairo_dock_foreach_desklet
22 #include "cairo-dock-desklet-factory.h"
23 #include "cairo-dock-draw-opengl.h" // cairo_dock_create_texture_from_surface
24 #include "cairo-dock-compiz-integration.h"
25 #include "cairo-dock-kwin-integration.h"
26 #include "cairo-dock-gnome-shell-integration.h"
27 #include "cairo-dock-cinnamon-integration.h"
28 #define _MANAGER_DEF_
29 #include "cairo-dock-desktop-manager.h"
30
31 // public (manager, config, data)
32 GldiManager myDesktopMgr;
33 GldiDesktopGeometry g_desktopGeometry;
34
35 // dependancies
36 extern GldiContainer *g_pPrimaryContainer;
37
38 // private
39 static GldiDesktopBackground *s_pDesktopBg = NULL; // une fois alloue, le pointeur restera le meme tout le temps.
40 static GldiDesktopManagerBackend s_backend;
41
42 static void _reload_desktop_background (void);
43
44
45 //////////////////////
46 /// desktop access ///
47 //////////////////////
48
gldi_desktop_get_current(int * iCurrentDesktop,int * iCurrentViewportX,int * iCurrentViewportY)49 void gldi_desktop_get_current (int *iCurrentDesktop, int *iCurrentViewportX, int *iCurrentViewportY)
50 {
51 *iCurrentDesktop = g_desktopGeometry.iCurrentDesktop;
52 *iCurrentViewportX = g_desktopGeometry.iCurrentViewportX;
53 *iCurrentViewportY = g_desktopGeometry.iCurrentViewportY;
54 }
55
56
57 //////////////////////////////
58 /// DESKTOP MANAGER BACKEND ///
59 //////////////////////////////
60
_set_desklets_on_widget_layer(CairoDesklet * pDesklet,G_GNUC_UNUSED gpointer data)61 static gboolean _set_desklets_on_widget_layer (CairoDesklet *pDesklet, G_GNUC_UNUSED gpointer data)
62 {
63 if (pDesklet->iVisibility == CAIRO_DESKLET_ON_WIDGET_LAYER)
64 gldi_desktop_set_on_widget_layer (CAIRO_CONTAINER (pDesklet), TRUE);
65 return FALSE; // continue
66 }
gldi_desktop_manager_register_backend(GldiDesktopManagerBackend * pBackend)67 void gldi_desktop_manager_register_backend (GldiDesktopManagerBackend *pBackend)
68 {
69 gpointer *ptr = (gpointer*)&s_backend;
70 gpointer *src = (gpointer*)pBackend;
71 gpointer *src_end = (gpointer*)(pBackend + 1);
72 while (src != src_end)
73 {
74 if (*src != NULL)
75 *ptr = *src;
76 src ++;
77 ptr ++;
78 }
79
80 // since we have a backend, set up the desklets that are supposed to be on the widget layer.
81 if (s_backend.set_on_widget_layer != NULL)
82 {
83 gldi_desklets_foreach ((GldiDeskletForeachFunc) _set_desklets_on_widget_layer, NULL);
84 }
85 }
86
gldi_desktop_present_class(const gchar * cClass)87 gboolean gldi_desktop_present_class (const gchar *cClass) // scale matching class
88 {
89 g_return_val_if_fail (cClass != NULL, FALSE);
90 if (s_backend.present_class != NULL)
91 {
92 return s_backend.present_class (cClass);
93 }
94 return FALSE;
95 }
96
gldi_desktop_present_windows(void)97 gboolean gldi_desktop_present_windows (void) // scale
98 {
99 if (s_backend.present_windows != NULL)
100 {
101 return s_backend.present_windows ();
102 }
103 return FALSE;
104 }
105
gldi_desktop_present_desktops(void)106 gboolean gldi_desktop_present_desktops (void) // expose
107 {
108 if (s_backend.present_desktops != NULL)
109 {
110 return s_backend.present_desktops ();
111 }
112 return FALSE;
113 }
114
gldi_desktop_show_widget_layer(void)115 gboolean gldi_desktop_show_widget_layer (void) // widget
116 {
117 if (s_backend.show_widget_layer != NULL)
118 {
119 return s_backend.show_widget_layer ();
120 }
121 return FALSE;
122 }
123
gldi_desktop_set_on_widget_layer(GldiContainer * pContainer,gboolean bOnWidgetLayer)124 gboolean gldi_desktop_set_on_widget_layer (GldiContainer *pContainer, gboolean bOnWidgetLayer)
125 {
126 if (s_backend.set_on_widget_layer != NULL)
127 {
128 return s_backend.set_on_widget_layer (pContainer, bOnWidgetLayer);
129 }
130 return FALSE;
131 }
132
gldi_desktop_can_present_class(void)133 gboolean gldi_desktop_can_present_class (void)
134 {
135 return (s_backend.present_class != NULL);
136 }
137
gldi_desktop_can_present_windows(void)138 gboolean gldi_desktop_can_present_windows (void)
139 {
140 return (s_backend.present_windows != NULL);
141 }
142
gldi_desktop_can_present_desktops(void)143 gboolean gldi_desktop_can_present_desktops (void)
144 {
145 return (s_backend.present_desktops != NULL);
146 }
147
gldi_desktop_can_show_widget_layer(void)148 gboolean gldi_desktop_can_show_widget_layer (void)
149 {
150 return (s_backend.show_widget_layer != NULL);
151 }
152
gldi_desktop_can_set_on_widget_layer(void)153 gboolean gldi_desktop_can_set_on_widget_layer (void)
154 {
155 return (s_backend.set_on_widget_layer != NULL);
156 }
157
158
gldi_desktop_show_hide(gboolean bShow)159 gboolean gldi_desktop_show_hide (gboolean bShow)
160 {
161 if (s_backend.show_hide_desktop)
162 {
163 s_backend.show_hide_desktop (bShow);
164 return TRUE;
165 }
166 return FALSE;
167 }
gldi_desktop_is_visible(void)168 gboolean gldi_desktop_is_visible (void)
169 {
170 if (s_backend.desktop_is_visible)
171 return s_backend.desktop_is_visible ();
172 return FALSE; // default state = not visible
173 }
gldi_desktop_get_names(void)174 gchar** gldi_desktop_get_names (void)
175 {
176 if (s_backend.get_desktops_names)
177 return s_backend.get_desktops_names ();
178 return NULL;
179 }
gldi_desktop_set_names(gchar ** cNames)180 gboolean gldi_desktop_set_names (gchar **cNames)
181 {
182 if (s_backend.set_desktops_names)
183 return s_backend.set_desktops_names (cNames);
184 return FALSE;
185 }
186
_get_desktop_bg_surface(void)187 static cairo_surface_t *_get_desktop_bg_surface (void)
188 {
189 if (s_backend.get_desktop_bg_surface)
190 return s_backend.get_desktop_bg_surface ();
191 return NULL;
192 }
193
gldi_desktop_set_current(int iDesktopNumber,int iViewportNumberX,int iViewportNumberY)194 gboolean gldi_desktop_set_current (int iDesktopNumber, int iViewportNumberX, int iViewportNumberY)
195 {
196 if (s_backend.set_current_desktop)
197 return s_backend.set_current_desktop (iDesktopNumber, iViewportNumberX, iViewportNumberY);
198 return FALSE;
199 }
200
gldi_desktop_set_nb_desktops(int iNbDesktops,int iNbViewportX,int iNbViewportY)201 gboolean gldi_desktop_set_nb_desktops (int iNbDesktops, int iNbViewportX, int iNbViewportY)
202 {
203 if (s_backend.set_nb_desktops)
204 return s_backend.set_nb_desktops (iNbDesktops, iNbViewportX, iNbViewportY);
205 return FALSE;
206 }
207
gldi_desktop_refresh(void)208 void gldi_desktop_refresh (void)
209 {
210 if (s_backend.refresh)
211 s_backend.refresh ();
212 }
213
gldi_desktop_notify_startup(const gchar * cClass)214 void gldi_desktop_notify_startup (const gchar *cClass)
215 {
216 if (s_backend.notify_startup)
217 s_backend.notify_startup (cClass);
218 }
219
gldi_desktop_grab_shortkey(guint keycode,guint modifiers,gboolean grab)220 gboolean gldi_desktop_grab_shortkey (guint keycode, guint modifiers, gboolean grab)
221 {
222 if (s_backend.grab_shortkey)
223 return s_backend.grab_shortkey (keycode, modifiers, grab);
224 return FALSE;
225 }
226
227 //////////////////
228 /// DESKTOP BG ///
229 //////////////////
230
gldi_desktop_background_get(gboolean bWithTextureToo)231 GldiDesktopBackground *gldi_desktop_background_get (gboolean bWithTextureToo)
232 {
233 //g_print ("%s (%d, %d)\n", __func__, bWithTextureToo, s_pDesktopBg?s_pDesktopBg->iRefCount:-1);
234 if (s_pDesktopBg == NULL)
235 {
236 s_pDesktopBg = g_new0 (GldiDesktopBackground, 1);
237 }
238 if (s_pDesktopBg->pSurface == NULL)
239 {
240 s_pDesktopBg->pSurface = _get_desktop_bg_surface ();
241 }
242 if (s_pDesktopBg->iTexture == 0 && bWithTextureToo)
243 {
244 s_pDesktopBg->iTexture = cairo_dock_create_texture_from_surface (s_pDesktopBg->pSurface);
245 }
246
247 s_pDesktopBg->iRefCount ++;
248 if (s_pDesktopBg->iSidDestroyBg != 0)
249 {
250 //g_print ("cancel pending destroy\n");
251 g_source_remove (s_pDesktopBg->iSidDestroyBg);
252 s_pDesktopBg->iSidDestroyBg = 0;
253 }
254 return s_pDesktopBg;
255 }
256
_destroy_bg(GldiDesktopBackground * pDesktopBg)257 static gboolean _destroy_bg (GldiDesktopBackground *pDesktopBg)
258 {
259 //g_print ("%s ()\n", __func__);
260 g_return_val_if_fail (pDesktopBg != NULL, 0);
261 if (pDesktopBg->pSurface != NULL)
262 {
263 cairo_surface_destroy (pDesktopBg->pSurface);
264 pDesktopBg->pSurface = NULL;
265 //g_print ("--- surface destroyed\n");
266 }
267 if (pDesktopBg->iTexture != 0)
268 {
269 _cairo_dock_delete_texture (pDesktopBg->iTexture);
270 pDesktopBg->iTexture = 0;
271 }
272 pDesktopBg->iSidDestroyBg = 0;
273 return FALSE;
274 }
gldi_desktop_background_destroy(GldiDesktopBackground * pDesktopBg)275 void gldi_desktop_background_destroy (GldiDesktopBackground *pDesktopBg)
276 {
277 //g_print ("%s ()\n", __func__);
278 if (!pDesktopBg)
279 return;
280 if (pDesktopBg->iRefCount > 0)
281 pDesktopBg->iRefCount --;
282 if (pDesktopBg->iRefCount == 0 && pDesktopBg->iSidDestroyBg == 0)
283 {
284 //g_print ("add pending destroy\n");
285 pDesktopBg->iSidDestroyBg = g_timeout_add_seconds (3, (GSourceFunc)_destroy_bg, pDesktopBg);
286 }
287 }
288
gldi_desktop_background_get_surface(GldiDesktopBackground * pDesktopBg)289 cairo_surface_t *gldi_desktop_background_get_surface (GldiDesktopBackground *pDesktopBg)
290 {
291 g_return_val_if_fail (pDesktopBg != NULL, NULL);
292 return pDesktopBg->pSurface;
293 }
294
gldi_desktop_background_get_texture(GldiDesktopBackground * pDesktopBg)295 GLuint gldi_desktop_background_get_texture (GldiDesktopBackground *pDesktopBg)
296 {
297 g_return_val_if_fail (pDesktopBg != NULL, 0);
298 return pDesktopBg->iTexture;
299 }
300
_reload_desktop_background(void)301 static void _reload_desktop_background (void)
302 {
303 //g_print ("%s ()\n", __func__);
304 if (s_pDesktopBg == NULL) // rien a recharger.
305 return ;
306 if (s_pDesktopBg->pSurface == NULL && s_pDesktopBg->iTexture == 0) // rien a recharger.
307 return ;
308
309 if (s_pDesktopBg->pSurface != NULL)
310 {
311 cairo_surface_destroy (s_pDesktopBg->pSurface);
312 //g_print ("--- surface destroyed\n");
313 }
314 s_pDesktopBg->pSurface = _get_desktop_bg_surface ();
315
316 if (s_pDesktopBg->iTexture != 0)
317 {
318 _cairo_dock_delete_texture (s_pDesktopBg->iTexture);
319 s_pDesktopBg->iTexture = cairo_dock_create_texture_from_surface (s_pDesktopBg->pSurface);
320 }
321 }
322
323
324 //////////////
325 /// UNLOAD ///
326 //////////////
327
unload(void)328 static void unload (void)
329 {
330 /*if (s_pDesktopBg != NULL && s_pDesktopBg->iTexture != 0)
331 {
332 _cairo_dock_delete_texture (s_pDesktopBg->iTexture);
333 s_pDesktopBg->iTexture = 0;
334 }*/
335 if (s_pDesktopBg) // on decharge le desktop-bg de force.
336 {
337 if (s_pDesktopBg->iSidDestroyBg != 0)
338 {
339 g_source_remove (s_pDesktopBg->iSidDestroyBg);
340 s_pDesktopBg->iSidDestroyBg = 0;
341 }
342 s_pDesktopBg->iRefCount = 0;
343 _destroy_bg (s_pDesktopBg); // detruit ses ressources immediatement, mais pas le pointeur.
344 }
345 }
346
347
on_wallpaper_changed(G_GNUC_UNUSED gpointer data)348 static gboolean on_wallpaper_changed (G_GNUC_UNUSED gpointer data)
349 {
350 _reload_desktop_background ();
351 return GLDI_NOTIFICATION_LET_PASS;
352 }
353
354 ////////////
355 /// INIT ///
356 ////////////
357
init(void)358 static void init (void)
359 {
360 //\__________________ Init the Window Manager backends.
361 cd_init_compiz_backend ();
362 cd_init_kwin_backend ();
363 cd_init_gnome_shell_backend ();
364 cd_init_cinnamon_backend ();
365 }
366
367
368 ///////////////
369 /// MANAGER ///
370 ///////////////
371
gldi_register_desktop_manager(void)372 void gldi_register_desktop_manager (void)
373 {
374 // Manager
375 memset (&myDesktopMgr, 0, sizeof (GldiManager));
376 gldi_object_init (GLDI_OBJECT(&myDesktopMgr), &myManagerObjectMgr, NULL);
377 myDesktopMgr.cModuleName = "Desktop";
378 // interface
379 myDesktopMgr.init = init;
380 myDesktopMgr.load = NULL;
381 myDesktopMgr.unload = unload;
382 myDesktopMgr.reload = (GldiManagerReloadFunc)NULL;
383 myDesktopMgr.get_config = (GldiManagerGetConfigFunc)NULL;
384 myDesktopMgr.reset_config = (GldiManagerResetConfigFunc)NULL;
385 // Config
386 myDesktopMgr.pConfig = (GldiManagerConfigPtr)NULL;
387 myDesktopMgr.iSizeOfConfig = 0;
388 // data
389 myDesktopMgr.iSizeOfData = 0;
390 myDesktopMgr.pData = (GldiManagerDataPtr)NULL;
391 memset (&s_backend, 0, sizeof (GldiDesktopManagerBackend));
392 // signals
393 gldi_object_install_notifications (&myDesktopMgr, NB_NOTIFICATIONS_DESKTOP); // we don't have a Desktop Object, so let's put the signals here
394
395 // init
396 gldi_object_register_notification (&myDesktopMgr,
397 NOTIFICATION_DESKTOP_WALLPAPER_CHANGED,
398 (GldiNotificationFunc) on_wallpaper_changed,
399 GLDI_RUN_FIRST, NULL);
400 }
401
402