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 <math.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 
25 #include <glib/gstdio.h>
26 #include <gtk/gtk.h>
27 
28 #include <cairo.h>
29 
30 #include "gldi-config.h"
31 #include "cairo-dock-image-buffer.h"
32 #include "cairo-dock-config.h"
33 #include "cairo-dock-icon-factory.h"
34 #include "cairo-dock-icon-facility.h"
35 #include "cairo-dock-separator-manager.h"  // gldi_automatic_separators_add_in_list
36 #include "cairo-dock-launcher-manager.h"
37 #include "cairo-dock-applet-manager.h"
38 #include "cairo-dock-stack-icon-manager.h"
39 #include "cairo-dock-class-icon-manager.h"
40 #include "cairo-dock-backends-manager.h"
41 #include "cairo-dock-desktop-manager.h"
42 #include "cairo-dock-log.h"
43 #include "cairo-dock-keyfile-utilities.h"
44 #include "cairo-dock-themes-manager.h"  // cairo_dock_add_conf_file
45 #include "cairo-dock-dock-factory.h"
46 #include "cairo-dock-dock-facility.h"
47 #include "cairo-dock-draw.h"
48 #include "cairo-dock-draw-opengl.h"
49 #include "cairo-dock-animations.h"
50 #include "cairo-dock-container.h"
51 #include "cairo-dock-keybinder.h"
52 #include "cairo-dock-indicator-manager.h"  // myIndicatorsParam.bUseClassIndic
53 #include "cairo-dock-style-manager.h"
54 #include "cairo-dock-opengl.h"
55 #include "cairo-dock-dock-visibility.h"
56 #include "cairo-dock-dock-manager.h"
57 
58 // public (manager, config, data)
59 CairoDocksParam myDocksParam;
60 GldiManager myDocksMgr;
61 GldiObjectManager myDockObjectMgr;
62 CairoDockImageBuffer g_pVisibleZoneBuffer;
63 CairoDock *g_pMainDock = NULL;  // pointeur sur le dock principal.
64 CairoDockHidingEffect *g_pHidingBackend = NULL;
65 CairoDockHidingEffect *g_pKeepingBelowBackend = NULL;
66 
67 // dependancies
68 extern gchar *g_cConfFile;
69 extern gchar *g_cCurrentThemePath;
70 extern gboolean g_bUseOpenGL;
71 extern CairoDockGLConfig g_openglConfig;
72 
73 // private
74 static GHashTable *s_hDocksTable = NULL;  // table des docks existant.
75 static GList *s_pRootDockList = NULL;
76 static guint s_iSidPollScreenEdge = 0;
77 static int s_iNbPolls = 0;
78 static gboolean s_bQuickHide = FALSE;
79 static gboolean s_bKeepAbove = FALSE;
80 static GldiShortkey *s_pPopupBinding = NULL;  // option 'pop up on shortkey'
81 static gboolean s_bResetAll = FALSE;
82 
83 #define MOUSE_POLLING_DT 150  // mouse polling delay in ms
84 
85 static gboolean _get_root_dock_config (CairoDock *pDock);
86 static void _start_polling_screen_edge (void);
87 static void _stop_polling_screen_edge (void);
88 static void _synchronize_sub_docks_orientation (CairoDock *pDock, gboolean bUpdateDockSize);
89 static void _set_dock_orientation (CairoDock *pDock, CairoDockPositionType iScreenBorder);
90 static void _remove_root_dock_config (const gchar *cDockName);
91 
92 typedef struct {
93 	gboolean bUpToDate;
94 	gint x;
95 	gint y;
96 	gboolean bNoMove;
97 	gdouble dx;
98 	gdouble dy;
99 } CDMousePolling;
100 
101   /////////////
102  // MANAGER //
103 /////////////
104 
105 
cairo_dock_force_docks_above(void)106 void cairo_dock_force_docks_above (void)
107 {
108 	if (g_pMainDock != NULL)
109 	{
110 		cd_warning ("this function must be called before any dock is created.");
111 		return;
112 	}
113 	s_bKeepAbove = TRUE;
114 }
115 
116 
117 // UNLOAD //
_free_one_dock(G_GNUC_UNUSED const gchar * cDockName,CairoDock * pDock,G_GNUC_UNUSED gpointer data)118 static gboolean _free_one_dock (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data)
119 {
120 	g_free (pDock->cDockName);
121 	pDock->cDockName = NULL;  // to not remove it from the table/list
122 	gldi_object_unref (GLDI_OBJECT(pDock));
123 	return TRUE;
124 }
cairo_dock_reset_docks_table(void)125 void cairo_dock_reset_docks_table (void)
126 {
127 	s_bResetAll = TRUE;
128 	g_hash_table_foreach_remove (s_hDocksTable, (GHRFunc) _free_one_dock, NULL);
129 	g_pMainDock = NULL;
130 
131 	g_list_free (s_pRootDockList);
132 	s_pRootDockList = NULL;
133 	s_bResetAll = FALSE;
134 }
135 
136 
_make_sub_dock(CairoDock * pDock,CairoDock * pParentDock,const gchar * cRendererName)137 static void _make_sub_dock (CairoDock *pDock, CairoDock *pParentDock, const gchar *cRendererName)
138 {
139 	//\__________________ set sub-dock flag
140 	pDock->iRefCount = 1;
141 	gtk_window_set_title (GTK_WINDOW (pDock->container.pWidget), "cairo-dock-sub");
142 
143 	//\__________________ set the orientation relatively to the parent dock
144 	pDock->container.bIsHorizontal = pParentDock->container.bIsHorizontal;
145 	pDock->container.bDirectionUp = pParentDock->container.bDirectionUp;
146 	pDock->iNumScreen = pParentDock->iNumScreen;
147 
148 	//\__________________ set a renderer
149 	cairo_dock_set_renderer (pDock, cRendererName);
150 
151 	//\__________________ update the icons size and the ratio.
152 	double fPrevRatio = pDock->container.fRatio;
153 	pDock->container.fRatio = MIN (pDock->container.fRatio, myBackendsParam.fSubDockSizeRatio);
154 	pDock->iIconSize = pParentDock->iIconSize;
155 
156 	Icon *icon;
157 	GList *ic;
158 	pDock->fFlatDockWidth = - myIconsParam.iIconGap;
159 	for (ic = pDock->icons; ic != NULL; ic = ic->next)
160 	{
161 		icon = ic->data;
162 		cairo_dock_icon_set_requested_size (icon, 0, 0);  // no request
163 		icon->fWidth = icon->fHeight = 0;  /// useful ?...
164 		cairo_dock_set_icon_size_in_dock (pDock, icon);
165 		pDock->fFlatDockWidth += icon->fWidth + myIconsParam.iIconGap;
166 	}
167 	pDock->iMaxIconHeight *= pDock->container.fRatio / fPrevRatio;
168 
169 	//\__________________ remove any input shape
170 	if (pDock->pShapeBitmap != NULL)
171 	{
172 		cairo_region_destroy (pDock->pShapeBitmap);
173 		pDock->pShapeBitmap = NULL;
174 		if (pDock->iInputState != CAIRO_DOCK_INPUT_ACTIVE)
175 		{
176 			cairo_dock_set_input_shape_active (pDock);
177 			pDock->iInputState = CAIRO_DOCK_INPUT_ACTIVE;
178 		}
179 	}
180 
181 	//\__________________ hide the dock
182 	pDock->bAutoHide = FALSE;
183 	gtk_widget_hide (pDock->container.pWidget);
184 }
gldi_dock_make_subdock(CairoDock * pDock,CairoDock * pParentDock,const gchar * cRendererName)185 void gldi_dock_make_subdock (CairoDock *pDock, CairoDock *pParentDock, const gchar *cRendererName)
186 {
187 	//g_print ("%s (%s)\n", __func__, cRendererName);
188 	if (pDock->iRefCount == 0)  // il devient un sous-dock.
189 	{
190 		//\__________________ make it a sub-dock.
191 		if (pParentDock == NULL)
192 			pParentDock = g_pMainDock;
193 		_make_sub_dock (pDock, pParentDock, cRendererName);
194 		cairo_dock_update_dock_size (pDock);
195 
196 		//\__________________ remove from main-dock land
197 		_remove_root_dock_config (pDock->cDockName);  // just in case.
198 
199 		s_pRootDockList = g_list_remove (s_pRootDockList, pDock);
200 
201 		gldi_dock_set_visibility (pDock, CAIRO_DOCK_VISI_KEEP_ABOVE);  // si la visibilite n'avait pas ete mise (sub-dock), ne fera rien (vu que la visibilite par defaut est KEEP_ABOVE).
202 	}
203 }
204 
205 
206 
_find_similar_root_dock(CairoDock * pDock,gpointer * data)207 static void _find_similar_root_dock (CairoDock *pDock, gpointer *data)
208 {
209 	CairoDock *pDock0 = data[0];
210 	if (pDock == pDock0)
211 		data[2] = GINT_TO_POINTER (TRUE);
212 	if (data[2])
213 		return;
214 	if (pDock->container.bIsHorizontal == pDock0->container.bIsHorizontal
215 		&& pDock->container.bDirectionUp == pDock0->container.bDirectionUp)
216 	{
217 		int *i = data[1];
218 		*i = *i + 1;
219 	}
220 }
gldi_dock_get_readable_name(CairoDock * pDock)221 gchar *gldi_dock_get_readable_name (CairoDock *pDock)
222 {
223 	g_return_val_if_fail (pDock != NULL, NULL);
224 	gchar *cUserName = NULL;
225 	if (pDock->iRefCount == 0)
226 	{
227 		int i = 0;
228 		gpointer data[3] = {pDock, &i, NULL};
229 		GList *d = g_list_last (s_pRootDockList);
230 		for (;d != NULL; d = d->prev)  // parse the list from the end to get the main dock first (docks are prepended).
231 			_find_similar_root_dock (d->data, data);
232 		const gchar *cPosition;
233 		if (pDock->container.bIsHorizontal)
234 		{
235 			if (pDock->container.bDirectionUp)
236 				cPosition = _("Bottom dock");
237 			else
238 				cPosition = _("Top dock");
239 		}
240 		else
241 		{
242 			if (pDock->container.bDirectionUp)
243 				cPosition = _("Right dock");
244 			else
245 				cPosition = _("Left dock");
246 		}
247 		if (i > 0)
248 			cUserName = g_strdup_printf ("%s (%d)", cPosition, i+1);
249 		else
250 			cUserName = g_strdup (cPosition);
251 	}
252 
253 	return cUserName;
254 }
255 
gldi_dock_get(const gchar * cDockName)256 CairoDock *gldi_dock_get (const gchar *cDockName)
257 {
258 	if (cDockName == NULL)
259 		return NULL;
260 	return g_hash_table_lookup (s_hDocksTable, cDockName);
261 }
262 
_cairo_dock_search_icon_from_subdock(G_GNUC_UNUSED gchar * cDockName,CairoDock * pDock,gpointer * data)263 static gboolean _cairo_dock_search_icon_from_subdock (G_GNUC_UNUSED gchar *cDockName, CairoDock *pDock, gpointer *data)
264 {
265 	if (pDock == data[0])
266 		return FALSE;
267 	Icon **pIconFound = data[1];
268 	CairoDock **pDockFound = data[2];
269 	Icon *icon = cairo_dock_get_icon_with_subdock (pDock->icons, data[0]);
270 	if (icon != NULL)
271 	{
272 		*pIconFound = icon;
273 		if (pDockFound != NULL)
274 			*pDockFound = pDock;
275 		return TRUE;
276 	}
277 	else
278 		return FALSE;
279 }
cairo_dock_search_icon_pointing_on_dock(CairoDock * pDock,CairoDock ** pParentDock)280 Icon *cairo_dock_search_icon_pointing_on_dock (CairoDock *pDock, CairoDock **pParentDock)  // pParentDock peut etre NULL.
281 {
282 	if (pDock == NULL || pDock->bIsMainDock)  // par definition. On n'utilise pas iRefCount, car si on est en train de detruire un dock, sa reference est deja decrementee. C'est dommage mais c'est comme ca.
283 		return NULL;
284 	Icon *pPointingIcon = NULL;
285 	gpointer data[3] = {pDock, &pPointingIcon, pParentDock};
286 	g_hash_table_find (s_hDocksTable, (GHRFunc)_cairo_dock_search_icon_from_subdock, data);
287 	return pPointingIcon;
288 }
289 
cairo_dock_get_unique_dock_name(const gchar * cPrefix)290 gchar *cairo_dock_get_unique_dock_name (const gchar *cPrefix)
291 {
292 	const gchar *cNamepattern = (cPrefix != NULL && *cPrefix != '\0' && strcmp (cPrefix, "cairo-dock") != 0 ? cPrefix : "dock");
293 	GString *sNameString = g_string_new (cNamepattern);
294 
295 	int i = 2;
296 	while (g_hash_table_lookup (s_hDocksTable, sNameString->str) != NULL)
297 	{
298 		g_string_printf (sNameString, "%s-%d", cNamepattern, i);
299 		i ++;
300 	}
301 
302 	gchar *cUniqueName = sNameString->str;
303 	g_string_free (sNameString, FALSE);
304 	return cUniqueName;
305 }
306 
cairo_dock_check_unique_subdock_name(Icon * pIcon)307 gboolean cairo_dock_check_unique_subdock_name (Icon *pIcon)
308 {
309 	cd_debug ("%s (%s)", __func__, pIcon->cName);
310 	gchar *cUniqueName = cairo_dock_get_unique_dock_name (pIcon->cName);
311 	if (pIcon->cName == NULL || strcmp (pIcon->cName, cUniqueName) != 0)
312 	{
313 		g_free (pIcon->cName);
314 		pIcon->cName = cUniqueName;
315 		cd_debug (" cName <- %s", cUniqueName);
316 		return TRUE;
317 	}
318 	return FALSE;
319 }
320 
321 
gldi_dock_rename(CairoDock * pDock,const gchar * cNewName)322 void gldi_dock_rename (CairoDock *pDock, const gchar *cNewName)
323 {
324 	// ensure everything is ok
325 	g_return_if_fail (pDock != NULL && cNewName != NULL);
326 	g_return_if_fail (g_hash_table_lookup (s_hDocksTable, cNewName) == NULL);
327 
328 	// rename in the hash table
329 	g_hash_table_remove (s_hDocksTable, pDock->cDockName);
330 	g_free (pDock->cDockName);
331 	pDock->cDockName = g_strdup (cNewName);
332 	g_hash_table_insert (s_hDocksTable, pDock->cDockName, pDock);
333 
334 	// rename in each icons
335 	GList* ic;
336 	Icon *icon;
337 	for (ic = pDock->icons; ic != NULL; ic = ic->next)
338 	{
339 		icon = ic->data;
340 		gldi_theme_icon_write_container_name_in_conf_file (icon, cNewName);
341 		g_free (icon->cParentDockName);
342 		icon->cParentDockName = g_strdup (cNewName);
343 	}
344 }
345 
346 
gldi_docks_foreach(GHFunc pFunction,gpointer data)347 void gldi_docks_foreach (GHFunc pFunction, gpointer data)
348 {
349 	g_hash_table_foreach (s_hDocksTable, pFunction, data);
350 }
351 
gldi_docks_foreach_root(GFunc pFunction,gpointer data)352 void gldi_docks_foreach_root (GFunc pFunction, gpointer data)
353 {
354 	g_list_foreach (s_pRootDockList, pFunction, data);
355 }
356 
_gldi_icons_foreach_in_dock(G_GNUC_UNUSED gchar * cDockName,CairoDock * pDock,gpointer * data)357 static void _gldi_icons_foreach_in_dock (G_GNUC_UNUSED gchar *cDockName, CairoDock *pDock, gpointer *data)
358 {
359 	GldiIconFunc pFunction = data[0];
360 	gpointer pUserData = data[1];
361 	GList *ic = pDock->icons, *next_ic;
362 	while (ic != NULL)
363 	{
364 		next_ic = ic->next;  // the function below may remove the current icon
365 		pFunction ((Icon*)ic->data, pUserData);
366 		ic = next_ic;
367 	}
368 }
gldi_icons_foreach_in_docks(GldiIconFunc pFunction,gpointer pUserData)369 void gldi_icons_foreach_in_docks (GldiIconFunc pFunction, gpointer pUserData)
370 {
371 	gpointer data[2] = {pFunction, pUserData};
372 	g_hash_table_foreach (s_hDocksTable, (GHFunc) _gldi_icons_foreach_in_dock, data);
373 }
374 
375 
376 
_reload_buffer_in_one_dock(CairoDock * pDock,gpointer data)377 static void _reload_buffer_in_one_dock (/**const gchar *cDockName, */CairoDock *pDock, gpointer data)
378 {
379 	cairo_dock_reload_buffers_in_dock (pDock, TRUE, GPOINTER_TO_INT (data));
380 }
_cairo_dock_draw_one_subdock_icon(G_GNUC_UNUSED const gchar * cDockName,CairoDock * pDock,G_GNUC_UNUSED gpointer data)381 static void _cairo_dock_draw_one_subdock_icon (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data)
382 {
383 	Icon *icon;
384 	GList *ic;
385 	for (ic = pDock->icons; ic != NULL; ic = ic->next)
386 	{
387 		icon = ic->data;
388 		if (icon->pSubDock != NULL
389 		&& (GLDI_OBJECT_IS_STACK_ICON (icon) || CAIRO_DOCK_IS_MULTI_APPLI (icon) || GLDI_OBJECT_IS_APPLET_ICON (icon))
390 		&& (icon->iSubdockViewType != 0
391 			|| (CAIRO_DOCK_IS_MULTI_APPLI (icon) && !myIndicatorsParam.bUseClassIndic))
392 		/**&& icon->iSidRedrawSubdockContent == 0*/)  // icone de sous-dock ou de classe ou d'applets.
393 		{
394 			cairo_dock_trigger_redraw_subdock_content_on_icon (icon);
395 		}
396 	}
397 }
cairo_dock_reload_buffers_in_all_docks(gboolean bUpdateIconSize)398 void cairo_dock_reload_buffers_in_all_docks (gboolean bUpdateIconSize)
399 {
400 	g_list_foreach (s_pRootDockList, (GFunc)_reload_buffer_in_one_dock, GINT_TO_POINTER (bUpdateIconSize));  // we load the root docks first, so that sub-docks can have the correct icon size.
401 
402 	// now that all icons in sub-docks are drawn, redraw icons pointing to a sub-dock
403 	g_hash_table_foreach (s_hDocksTable, (GHFunc)_cairo_dock_draw_one_subdock_icon, NULL);
404 }
405 
406 
407 
_cairo_dock_set_one_dock_view_to_default(G_GNUC_UNUSED gchar * cDockName,CairoDock * pDock,gpointer data)408 static void _cairo_dock_set_one_dock_view_to_default (G_GNUC_UNUSED gchar *cDockName, CairoDock *pDock, gpointer data)
409 {
410 	//g_print ("%s (%s)\n", __func__, cDockName);
411 	int iDockType = GPOINTER_TO_INT (data);
412 	if (iDockType == 0 || (iDockType == 1 && pDock->iRefCount == 0) || (iDockType == 2 && pDock->iRefCount != 0))
413 	{
414 		cairo_dock_set_default_renderer (pDock);
415 		cairo_dock_update_dock_size (pDock);
416 	}
417 }
cairo_dock_set_all_views_to_default(int iDockType)418 void cairo_dock_set_all_views_to_default (int iDockType)
419 {
420 	//g_print ("%s ()\n", __func__);
421 	g_hash_table_foreach (s_hDocksTable, (GHFunc) _cairo_dock_set_one_dock_view_to_default, GINT_TO_POINTER (iDockType));
422 }
423 
424 
425   //////////////////////
426  // ROOT DOCK CONFIG //
427 //////////////////////
428 
gldi_rootdock_write_gaps(CairoDock * pDock)429 void gldi_rootdock_write_gaps (CairoDock *pDock)
430 {
431 	if (pDock->iRefCount > 0)
432 		return;
433 
434 	cairo_dock_prevent_dock_from_out_of_screen (pDock);
435 	if (pDock->bIsMainDock)
436 	{
437 		cairo_dock_update_conf_file (g_cConfFile,
438 			G_TYPE_INT, "Position", "x gap", pDock->iGapX,
439 			G_TYPE_INT, "Position", "y gap", pDock->iGapY,
440 			G_TYPE_INVALID);
441 	}
442 	else
443 	{
444 		const gchar *cDockName = gldi_dock_get_name (pDock);
445 		gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, cDockName);
446 		if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))  // shouldn't happen
447 		{
448 			cairo_dock_add_conf_file (GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_MAIN_DOCK_CONF_FILE, cConfFilePath);
449 		}
450 
451 		cairo_dock_update_conf_file (cConfFilePath,
452 			G_TYPE_INT, "Behavior", "x gap", pDock->iGapX,
453 			G_TYPE_INT, "Behavior", "y gap", pDock->iGapY,
454 			G_TYPE_INVALID);
455 		g_free (cConfFilePath);
456 	}
457 }
458 
cairo_dock_convert_icon_size_to_pixels(GldiIconSizeEnum s,double * fMaxScale,double * fReflectSize,int * iIconGap)459 int cairo_dock_convert_icon_size_to_pixels (GldiIconSizeEnum s, double *fMaxScale, double *fReflectSize, int *iIconGap)
460 {
461 	int iIconSize;
462 	switch (s)
463 	{
464 		case ICON_DEFAULT:
465 		default:
466 			iIconSize = myIconsParam.iIconWidth;
467 			*fMaxScale = 1 + myIconsParam.fAmplitude;
468 			*iIconGap = myIconsParam.iIconGap;
469 			*fReflectSize = myIconsParam.fReflectHeightRatio;
470 		break;
471 		case ICON_TINY:
472 			iIconSize = ICON_SIZE_TINY;
473 			*fMaxScale = 2;
474 			*iIconGap = 4;
475 			*fReflectSize = .4;
476 		break;
477 		case ICON_VERY_SMALL:
478 			iIconSize = ICON_SIZE_VERY_SMALL;
479 			*fMaxScale = 1.8;
480 			*iIconGap = 4;
481 			*fReflectSize = .4;
482 		break;
483 		case ICON_SMALL:
484 			iIconSize = ICON_SIZE_SMALL;
485 			*fMaxScale = 1.8;
486 			*iIconGap = 4;
487 			*fReflectSize = .4;
488 		break;
489 		case ICON_MEDIUM:
490 			iIconSize = ICON_SIZE_MEDIUM;
491 			*fMaxScale = 1.6;
492 			*iIconGap = 3;
493 			*fReflectSize = .5;
494 		break;
495 		case ICON_BIG:
496 			iIconSize = ICON_SIZE_BIG;
497 			*fMaxScale = 1.5;
498 			*iIconGap = 2;
499 			*fReflectSize = .6;
500 		break;
501 		case ICON_HUGE:
502 			iIconSize = ICON_SIZE_HUGE;
503 			*fMaxScale = 1.3;
504 			*iIconGap = 2;
505 			*fReflectSize = .6;
506 		break;
507 	}
508 	return iIconSize;
509 }
510 
cairo_dock_convert_icon_size_to_enum(int iIconSize)511 GldiIconSizeEnum cairo_dock_convert_icon_size_to_enum (int iIconSize)
512 {
513 	GldiIconSizeEnum s = ICON_DEFAULT;
514 	if (iIconSize <= ICON_SIZE_TINY+2)
515 		s = ICON_TINY;
516 	else if (iIconSize <= ICON_SIZE_VERY_SMALL+2)
517 		s = ICON_VERY_SMALL;
518 	else if (iIconSize >= ICON_SIZE_HUGE-2)
519 		s = ICON_HUGE;
520 	else if (iIconSize > ICON_SIZE_MEDIUM)
521 		s = ICON_BIG;
522 	else
523 	{
524 		if (myIconsParam.fAmplitude >= 2 || iIconSize <= ICON_SIZE_SMALL)
525 			s = ICON_SMALL;
526 		else
527 			s = ICON_MEDIUM;  // moyennes.
528 	}
529 	return s;
530 }
531 
_get_root_dock_config(CairoDock * pDock)532 static gboolean _get_root_dock_config (CairoDock *pDock)
533 {
534 	g_return_val_if_fail (pDock != NULL, FALSE);
535 	if (pDock->iRefCount > 0)
536 		return FALSE;
537 
538 	if (pDock->bIsMainDock)  // the main dock doesn't have a config file, it uses the global params (that we already got from the Dock-manager)
539 	{
540 		pDock->iGapX = myDocksParam.iGapX;
541 		pDock->iGapY = myDocksParam.iGapY;
542 
543 		pDock->fAlign = myDocksParam.fAlign;
544 
545 		pDock->iNumScreen = myDocksParam.iNumScreen;
546 
547 		_set_dock_orientation (pDock, myDocksParam.iScreenBorder);  // do it after all position parameters have been set; it sets the sub-docks orientation too.
548 
549 		gldi_dock_set_visibility (pDock, myDocksParam.iVisibility);
550 
551 		pDock->bGlobalIconSize = TRUE;  // default icon size
552 
553 		pDock->bGlobalBg = TRUE;  // default background
554 		// pDock->cRendererName and pDock->iIconSize stay at 0
555 
556 		pDock->bExtendedMode = myDocksParam.bExtendedMode;
557 
558 		return TRUE;
559 	}
560 
561 	//\______________ On verifie la presence du fichier de conf associe.
562 	//g_print ("%s (%s)\n", __func__, pDock->cDockName);
563 	gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, pDock->cDockName);
564 	if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))  // pas encore de fichier de conf pour ce dock.
565 	{
566 		pDock->container.bIsHorizontal = g_pMainDock->container.bIsHorizontal;
567 		pDock->container.bDirectionUp = g_pMainDock->container.bDirectionUp;
568 		pDock->fAlign = g_pMainDock->fAlign;
569 
570 		g_free (cConfFilePath);
571 		return FALSE;
572 	}
573 
574 	//\______________ On ouvre le fichier de conf.
575 	GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
576 	if (pKeyFile == NULL)
577 	{
578 		cd_warning ("wrong conf file (%s) !", cConfFilePath);
579 		g_free (cConfFilePath);
580 		return FALSE;
581 	}
582 
583 	//\______________ Position.
584 	gboolean bFlushConfFileNeeded = FALSE;
585 	pDock->iGapX = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "x gap", &bFlushConfFileNeeded, 0, "Position", NULL);
586 	pDock->iGapY = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "y gap", &bFlushConfFileNeeded, 0, "Position", NULL);
587 
588 	pDock->fAlign = cairo_dock_get_double_key_value (pKeyFile, "Behavior", "alignment", &bFlushConfFileNeeded, 0.5, "Position", NULL);
589 
590 	pDock->iNumScreen = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "num_screen", &bFlushConfFileNeeded, GLDI_DEFAULT_SCREEN, "Position", NULL);
591 
592 	CairoDockPositionType iScreenBorder = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "screen border", &bFlushConfFileNeeded, 0, "Position", NULL);
593 	_set_dock_orientation (pDock, iScreenBorder);  // do it after all position parameters have been set; it sets the sub-docks orientation too.
594 
595 	//\______________ Visibility.
596 	CairoDockVisibility iVisibility = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "visibility", &bFlushConfFileNeeded, FALSE, "Position", NULL);
597 	gldi_dock_set_visibility (pDock, iVisibility);
598 
599 	//\______________ Icons size.
600 	int s = cairo_dock_get_integer_key_value (pKeyFile, "Appearance", "icon size", &bFlushConfFileNeeded, ICON_DEFAULT, NULL, NULL);  // ICON_DEFAULT <=> same as main dock
601 	double fMaxScale, fReflectSize;
602 	int iIconGap;
603 	pDock->iIconSize = cairo_dock_convert_icon_size_to_pixels (s, &fMaxScale, &fReflectSize, &iIconGap);
604 	pDock->bGlobalIconSize = (s == ICON_DEFAULT);
605 
606 	//\______________ View.
607 	g_free (pDock->cRendererName);
608 	pDock->cRendererName = cairo_dock_get_string_key_value (pKeyFile, "Appearance", "main dock view", &bFlushConfFileNeeded, NULL, "Views", NULL);
609 
610 	//\______________ Background.
611 	int iBgType = cairo_dock_get_integer_key_value (pKeyFile, "Appearance", "fill bg", &bFlushConfFileNeeded, 0, NULL, NULL);
612 
613 	pDock->bGlobalBg = (iBgType == 0);
614 
615 	if (!pDock->bGlobalBg)
616 	{
617 		if (iBgType == 1)
618 		{
619 			gchar *cBgImage = cairo_dock_get_string_key_value (pKeyFile, "Appearance", "background image", &bFlushConfFileNeeded, NULL, NULL, NULL);
620 			g_free (pDock->cBgImagePath);
621 			if (cBgImage != NULL)
622 			{
623 				pDock->cBgImagePath = cairo_dock_search_image_s_path (cBgImage);
624 				g_free (cBgImage);
625 			}
626 			else
627 				pDock->cBgImagePath = NULL;
628 
629 			pDock->bBgImageRepeat = cairo_dock_get_boolean_key_value (pKeyFile, "Appearance", "repeat image", &bFlushConfFileNeeded, FALSE, NULL, NULL);
630 		}
631 		// on recupere la couleur tout le temps pour avoir un plan B.
632 		GldiColor couleur = {{.7, .7, 1., .7}};
633 		cairo_dock_get_color_key_value (pKeyFile, "Appearance", "stripes color dark", &bFlushConfFileNeeded, &pDock->fBgColorDark, &couleur, NULL, NULL);
634 
635 		GldiColor couleur2 = {{.7, .9, .7, .4}};
636 		cairo_dock_get_color_key_value (pKeyFile, "Appearance", "stripes color bright", &bFlushConfFileNeeded, &pDock->fBgColorBright, &couleur2, NULL, NULL);
637 	}
638 
639 	pDock->bExtendedMode = cairo_dock_get_boolean_key_value (pKeyFile, "Appearance", "extended", &bFlushConfFileNeeded, FALSE, NULL, NULL);
640 
641 	//\______________ On met a jour le fichier de conf.
642 	if (! bFlushConfFileNeeded)
643 		bFlushConfFileNeeded = cairo_dock_conf_file_needs_update (pKeyFile, GLDI_VERSION);
644 	if (bFlushConfFileNeeded)
645 	{
646 		//g_print ("update %s conf file\n", pDock->cDockName);
647 		cairo_dock_upgrade_conf_file (cConfFilePath, pKeyFile, GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_MAIN_DOCK_CONF_FILE);
648 	}
649 
650 	g_key_file_free (pKeyFile);
651 	g_free (cConfFilePath);
652 	return TRUE;
653 }
654 
_remove_root_dock_config(const gchar * cDockName)655 static void _remove_root_dock_config (const gchar *cDockName)
656 {
657 	if (! cDockName || strcmp (cDockName, "cairo-dock") == 0)
658 		return ;
659 	gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, cDockName);
660 	if (g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))
661 	{
662 		cairo_dock_delete_conf_file (cConfFilePath);
663 	}
664 	g_free (cConfFilePath);
665 }
666 
gldi_dock_add_conf_file_for_name(const gchar * cDockName)667 void gldi_dock_add_conf_file_for_name (const gchar *cDockName)
668 {
669 	// on cree le fichier de conf a partir du template.
670 	cd_debug ("%s (%s)", __func__, cDockName);
671 	gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, cDockName);
672 	cairo_dock_add_conf_file (GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_MAIN_DOCK_CONF_FILE, cConfFilePath);
673 
674 	// on placera le nouveau dock a l'oppose du main dock, meme ecran et meme visibilite.
675 	cairo_dock_update_conf_file (cConfFilePath,
676 		G_TYPE_INT, "Behavior", "screen border",
677 		(g_pMainDock->container.bIsHorizontal ?
678 			(g_pMainDock->container.bDirectionUp ? 1 : 0) :
679 			(g_pMainDock->container.bDirectionUp ? 3 : 2)),
680 		G_TYPE_INT, "Behavior", "visibility",
681 		g_pMainDock->iVisibility,
682 		G_TYPE_INT, "Behavior", "num_screen",
683 		g_pMainDock->iNumScreen,
684 		G_TYPE_INVALID);
685 	g_free (cConfFilePath);
686 }
687 
gldi_dock_add_conf_file(void)688 gchar *gldi_dock_add_conf_file (void)
689 {
690 	// on genere un nom unique.
691 	gchar *cValidDockName = cairo_dock_get_unique_dock_name (CAIRO_DOCK_MAIN_DOCK_NAME);  // meme nom que le main dock avec un numero en plus, plus facile pour les reperer.
692 
693 	// on genere un fichier de conf pour ce nom.
694 	gldi_dock_add_conf_file_for_name (cValidDockName);
695 
696 	return cValidDockName;
697 }
698 
699 
gldi_docks_redraw_all_root(void)700 void gldi_docks_redraw_all_root (void)
701 {
702 	gldi_docks_foreach_root ((GFunc)cairo_dock_redraw_container, NULL);
703 }
704 
705 
_reposition_one_root_dock(G_GNUC_UNUSED const gchar * cDockName,CairoDock * pDock,gpointer data)706 static void _reposition_one_root_dock (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, gpointer data)
707 {
708 	if (pDock->iRefCount == 0 && ! (data && pDock->bIsMainDock))
709 	{
710 		if (!pDock->bIsMainDock)
711 			_get_root_dock_config (pDock);  // relit toute la conf.
712 
713 		cairo_dock_update_dock_size (pDock);  // la taille max du dock depend de la taille de l'ecran, donc on recalcule son ratio.
714 		cairo_dock_move_resize_dock (pDock);
715 		gtk_widget_show (pDock->container.pWidget);
716 		gtk_widget_queue_draw (pDock->container.pWidget);
717 		_synchronize_sub_docks_orientation (pDock, TRUE);
718 	}
719 }
_reposition_root_docks(gboolean bExceptMainDock)720 static void _reposition_root_docks (gboolean bExceptMainDock)
721 {
722 	g_hash_table_foreach (s_hDocksTable, (GHFunc)_reposition_one_root_dock, GINT_TO_POINTER (bExceptMainDock));
723 }
724 
gldi_subdock_synchronize_orientation(CairoDock * pSubDock,CairoDock * pDock,gboolean bUpdateDockSize)725 void gldi_subdock_synchronize_orientation (CairoDock *pSubDock, CairoDock *pDock, gboolean bUpdateDockSize)
726 {
727 	if (pSubDock->container.bDirectionUp != pDock->container.bDirectionUp)
728 	{
729 		pSubDock->container.bDirectionUp = pDock->container.bDirectionUp;
730 		bUpdateDockSize = TRUE;
731 	}
732 	if (pSubDock->container.bIsHorizontal != pDock->container.bIsHorizontal)
733 	{
734 		pSubDock->container.bIsHorizontal = pDock->container.bIsHorizontal;
735 		bUpdateDockSize = TRUE;
736 	}
737 	if (pSubDock->iNumScreen != pDock->iNumScreen)
738 	{
739 		pSubDock->iNumScreen = pDock->iNumScreen;
740 		bUpdateDockSize = TRUE;
741 	}
742 
743 	if (bUpdateDockSize)
744 	{
745 		cairo_dock_update_dock_size (pSubDock);
746 	}
747 
748 	_synchronize_sub_docks_orientation (pSubDock, bUpdateDockSize);
749 }
750 
_synchronize_sub_docks_orientation(CairoDock * pDock,gboolean bUpdateDockSize)751 static void _synchronize_sub_docks_orientation (CairoDock *pDock, gboolean bUpdateDockSize)
752 {
753 	GList* ic;
754 	Icon *icon;
755 	for (ic = pDock->icons; ic != NULL; ic = ic->next)
756 	{
757 		icon = ic->data;
758 		if (icon->pSubDock != NULL)
759 		{
760 			gldi_subdock_synchronize_orientation (icon->pSubDock, pDock, bUpdateDockSize);  // recursively synchronize all children (no need to check for loops, as it shouldn't occur... if it does, then the problem is to fix upstream).
761 		}
762 	}
763 }
764 
_set_dock_orientation(CairoDock * pDock,CairoDockPositionType iScreenBorder)765 static void _set_dock_orientation (CairoDock *pDock, CairoDockPositionType iScreenBorder)
766 {
767 	switch (iScreenBorder)
768 	{
769 		case CAIRO_DOCK_BOTTOM :
770 			pDock->container.bIsHorizontal = CAIRO_DOCK_HORIZONTAL;
771 			pDock->container.bDirectionUp = TRUE;
772 		break;
773 		case CAIRO_DOCK_TOP :
774 			pDock->container.bIsHorizontal = CAIRO_DOCK_HORIZONTAL;
775 			pDock->container.bDirectionUp = FALSE;
776 		break;
777 		case CAIRO_DOCK_RIGHT :
778 			pDock->container.bIsHorizontal = CAIRO_DOCK_VERTICAL;
779 			pDock->container.bDirectionUp = TRUE;
780 		break;
781 		case CAIRO_DOCK_LEFT :
782 			pDock->container.bIsHorizontal = CAIRO_DOCK_VERTICAL;
783 			pDock->container.bDirectionUp = FALSE;
784 		break;
785 		case CAIRO_DOCK_INSIDE_SCREEN :
786 		case CAIRO_DOCK_NB_POSITIONS :
787 		break;
788 	}
789 	_synchronize_sub_docks_orientation (pDock, FALSE);
790 }
791 
792 
793   ////////////////
794  // VISIBILITY //
795 ////////////////
796 
_cairo_dock_quick_hide_one_root_dock(G_GNUC_UNUSED const gchar * cDockName,CairoDock * pDock,G_GNUC_UNUSED gpointer data)797 static void _cairo_dock_quick_hide_one_root_dock (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data)
798 {
799 	if (pDock->iRefCount == 0)
800 	{
801 		pDock->bAutoHide = TRUE;
802 		cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pDock));
803 	}
804 }
cairo_dock_quick_hide_all_docks(void)805 void cairo_dock_quick_hide_all_docks (void)
806 {
807 	if (! s_bQuickHide)
808 	{
809 		s_bQuickHide = TRUE;
810 		g_hash_table_foreach (s_hDocksTable, (GHFunc) _cairo_dock_quick_hide_one_root_dock, NULL);
811 		_start_polling_screen_edge ();
812 	}
813 }
814 
_cairo_dock_stop_quick_hide_one_root_dock(G_GNUC_UNUSED const gchar * cDockName,CairoDock * pDock,G_GNUC_UNUSED gpointer data)815 static void _cairo_dock_stop_quick_hide_one_root_dock (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data)
816 {
817 	if (pDock->iRefCount == 0 && ! pDock->bTemporaryHidden && pDock->bAutoHide && pDock->iVisibility != CAIRO_DOCK_VISI_AUTO_HIDE)
818 	{
819 		pDock->bAutoHide = FALSE;
820 
821 		if (! pDock->container.bInside)  // on le fait re-apparaitre.
822 		{
823 			cairo_dock_start_showing (pDock);  // l'input shape sera mise lors du configure.
824 		}
825 	}
826 }
cairo_dock_stop_quick_hide(void)827 void cairo_dock_stop_quick_hide (void)
828 {
829 	if (s_bQuickHide)
830 	{
831 		s_bQuickHide = FALSE;
832 		_stop_polling_screen_edge ();
833 
834 		g_hash_table_foreach (s_hDocksTable, (GHFunc) _cairo_dock_stop_quick_hide_one_root_dock, NULL);
835 	}
836 }
837 
cairo_dock_allow_entrance(CairoDock * pDock)838 void cairo_dock_allow_entrance (CairoDock *pDock)
839 {
840 	pDock->bEntranceDisabled = FALSE;
841 }
842 
cairo_dock_disable_entrance(CairoDock * pDock)843 void cairo_dock_disable_entrance (CairoDock *pDock)
844 {
845 	pDock->bEntranceDisabled = TRUE;
846 }
847 
cairo_dock_entrance_is_allowed(CairoDock * pDock)848 gboolean cairo_dock_entrance_is_allowed (CairoDock *pDock)
849 {
850 	return (! pDock->bEntranceDisabled);
851 }
852 
cairo_dock_activate_temporary_auto_hide(CairoDock * pDock)853 void cairo_dock_activate_temporary_auto_hide (CairoDock *pDock)
854 {
855 	if (pDock->iRefCount == 0 && ! pDock->bTemporaryHidden && pDock->iVisibility != CAIRO_DOCK_VISI_AUTO_HIDE)
856 	{
857 		pDock->bAutoHide = TRUE;
858 		pDock->bTemporaryHidden = TRUE;
859 		if (!pDock->container.bInside)  // on ne declenche pas le cachage lorsque l'on change par exemple de bureau via le switcher ou un clic sur une appli.
860 		{
861 			cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pDock));  // un cairo_dock_start_hiding ne cacherait pas les sous-docks.
862 		}
863 	}
864 }
865 
cairo_dock_deactivate_temporary_auto_hide(CairoDock * pDock)866 void cairo_dock_deactivate_temporary_auto_hide (CairoDock *pDock)
867 {
868 	//g_print ("%s ()\n", __func__);
869 	if (pDock->iRefCount == 0 && pDock->bTemporaryHidden && ! s_bQuickHide)
870 	{
871 		pDock->bTemporaryHidden = FALSE;
872 		pDock->bAutoHide = FALSE;
873 
874 		if (! pDock->container.bInside)  // on le fait re-apparaitre.
875 		{
876 			cairo_dock_start_showing (pDock);
877 		}
878 	}
879 }
880 
881 
_cairo_dock_hide_back_dock(CairoDock * pDock)882 static gboolean _cairo_dock_hide_back_dock (CairoDock *pDock)
883 {
884 	//g_print ("hide back\n");
885 	if (pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW && ! pDock->container.bInside)
886 		cairo_dock_pop_down (pDock);
887 	else if (pDock->bAutoHide)
888 		cairo_dock_start_hiding (pDock);
889 	pDock->iSidHideBack = 0;
890 	return FALSE;
891 }
_cairo_dock_unhide_dock_delayed(CairoDock * pDock)892 static gboolean _cairo_dock_unhide_dock_delayed (CairoDock *pDock)
893 {
894 	//g_print ("%s (%d, %d)\n", __func__, pDock->container.bInside, pDock->iInputState);
895 	if (pDock->container.bInside && pDock->iInputState != CAIRO_DOCK_INPUT_HIDDEN && !pDock->bIsBelow)  // already inside and reachable (caution) => no need to show it again.
896 	{
897 		pDock->iSidUnhideDelayed = 0;
898 		return FALSE;
899 	}
900 
901 	//g_print ("let's show this dock (%d)\n", pDock->bIsMainDock);
902 	if (pDock->bAutoHide)
903 		cairo_dock_start_showing (pDock);
904 	if (pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW)
905 		cairo_dock_pop_up (pDock);
906 
907 	if (pDock->iSidHideBack == 0)  // on se recachera dans 2s si on n'est pas entre dans le dock entre-temps.
908 		pDock->iSidHideBack = g_timeout_add (2000, (GSourceFunc) _cairo_dock_hide_back_dock, (gpointer) pDock);
909 	pDock->iSidUnhideDelayed = 0;
910 	return FALSE;
911 }
_cairo_dock_unhide_root_dock_on_mouse_hit(CairoDock * pDock,CDMousePolling * pMouse)912 static void _cairo_dock_unhide_root_dock_on_mouse_hit (CairoDock *pDock, CDMousePolling *pMouse)
913 {
914 	if (! pDock->bAutoHide && pDock->iVisibility != CAIRO_DOCK_VISI_KEEP_BELOW)
915 		return;
916 
917 	int iScreenWidth = gldi_dock_get_screen_width (pDock);
918 	int iScreenHeight = gldi_dock_get_screen_height (pDock);
919 	int iScreenX = gldi_dock_get_screen_offset_x (pDock);
920 	int iScreenY = gldi_dock_get_screen_offset_y (pDock);
921 
922 	//\________________ On recupere la position du pointeur.
923 	gint x, y;
924 	if (! pMouse->bUpToDate)  // pas encore recupere le pointeur.
925 	{
926 		pMouse->bUpToDate = TRUE;
927 		gldi_display_get_pointer (&x, &y);
928 		if (x == pMouse->x && y == pMouse->y)  // le pointeur n'a pas bouge, on quitte.
929 		{
930 			pMouse->bNoMove = TRUE;
931 			return ;
932 		}
933 		pMouse->bNoMove = FALSE;
934 		pMouse->dx = (x - pMouse->x);
935 		pMouse->dy = (y - pMouse->y);
936 		double d = sqrt (pMouse->dx * pMouse->dx + pMouse->dy * pMouse->dy);
937 		pMouse->dx /= d;
938 		pMouse->dy /= d;
939 		pMouse->x = x;
940 		pMouse->y = y;
941 	}
942 	else  // le pointeur a ete recupere auparavant.
943 	{
944 		if (pMouse->bNoMove)  // position inchangee.
945 			return;
946 		x = pMouse->x;
947 		y = pMouse->y;
948 	}
949 
950 	if (!pDock->container.bIsHorizontal)
951 	{
952 		x = pMouse->y;
953 		y = pMouse->x;
954 	}
955 	y -= iScreenY;  // relative to the border of the dock's screen.
956 	if (pDock->container.bDirectionUp)
957 	{
958 		y = iScreenHeight - 1 - y;
959 
960 	}
961 
962 	//\________________ On verifie les conditions.
963 	int x1, x2;  // coordinates range on the X screen edge.
964 	gboolean bShow = FALSE;
965 	int Ws = (pDock->container.bIsHorizontal ? gldi_desktop_get_width() : gldi_desktop_get_height());
966 	switch (myDocksParam.iCallbackMethod)
967 	{
968 		case CAIRO_HIT_SCREEN_BORDER:
969 		default:
970 			if (y != 0)
971 				break;
972 			if (x < iScreenX || x > iScreenX + iScreenWidth - 1)  // only check the border of the dock's screen.
973 				break ;
974 			bShow = TRUE;
975 		break;
976 		case CAIRO_HIT_DOCK_PLACE:
977 
978 			if (y != 0)
979 				break;
980 			x1 = pDock->container.iWindowPositionX + (pDock->container.iWidth - pDock->iActiveWidth) * pDock->fAlign;
981 			x2 = x1 + pDock->iActiveWidth;
982 			if (x1 < 8)  // avoid corners, since this is actually the purpose of this option (corners can be used by the WM to trigger actions).
983 				x1 = 8;
984 			if (x2 > Ws - 8)
985 				x2 = Ws - 8;
986 			if (x < x1 || x > x2)
987 				break;
988 			bShow = TRUE;
989 		break;
990 		case CAIRO_HIT_SCREEN_CORNER:
991 			if (y != 0)
992 				break;
993 			if (x > 0 && x < Ws - 1)  // avoid the corners of the X screen (since we can't actually hit the corner of a screen that would be inside the X screen).
994 				break ;
995 			bShow = TRUE;
996 		break;
997 		case CAIRO_HIT_ZONE:
998 			if (y > myDocksParam.iZoneHeight)
999 				break;
1000 			x1 = pDock->container.iWindowPositionX + (pDock->container.iWidth - myDocksParam.iZoneWidth) * pDock->fAlign;
1001 			x2 = x1 + myDocksParam.iZoneWidth;
1002 			if (x < x1 || x > x2)
1003 				break;
1004 			bShow = TRUE;
1005 		break;
1006 	}
1007 	if (! bShow)
1008 	{
1009 		if (pDock->iSidUnhideDelayed != 0)
1010 		{
1011 			g_source_remove (pDock->iSidUnhideDelayed);
1012 			pDock->iSidUnhideDelayed = 0;
1013 		}
1014 		return;
1015 	}
1016 
1017 	//\________________ On montre ou on programme le montrage du dock.
1018 	int nx, ny;  // normal vector to the screen edge.
1019 	double cost;  // cos (teta), where teta = angle between mouse vector and dock's normal
1020 	double f = 1.;  // delay factor
1021 	if (pDock->container.bIsHorizontal)
1022 	{
1023 		nx = 0;
1024 		ny = (pDock->container.bDirectionUp ? -1 : 1);
1025 	}
1026 	else
1027 	{
1028 		ny = 0;
1029 		nx = (pDock->container.bDirectionUp ? -1 : 1);
1030 	}
1031 	cost = nx * pMouse->dx + ny * pMouse->dy;
1032 	f = 2 + cost;  // so if cost = -1, we arrive straight onto the screen edge, and f = 1, => normal delay. if cost = 0, f = 2 and we have a bigger delay.
1033 
1034 	int iDelay = f * myDocksParam.iUnhideDockDelay;
1035 	//g_print (" dock will be shown in %dms (%.2f, %d)\n", iDelay, f, pDock->bIsMainDock);
1036 	if (iDelay != 0)  // on programme une apparition.
1037 	{
1038 		if (pDock->iSidUnhideDelayed == 0)
1039 			pDock->iSidUnhideDelayed = g_timeout_add (iDelay, (GSourceFunc) _cairo_dock_unhide_dock_delayed, (gpointer) pDock);
1040 	}
1041 	else  // on montre le dock tout de suite.
1042 	{
1043 		_cairo_dock_unhide_dock_delayed (pDock);
1044 	}
1045 }
1046 
_cairo_dock_poll_screen_edge(G_GNUC_UNUSED gpointer data)1047 static gboolean _cairo_dock_poll_screen_edge (G_GNUC_UNUSED gpointer data)  // thanks to Smidgey for the pop-up patch !
1048 {
1049 	static CDMousePolling mouse;
1050 
1051 	mouse.bUpToDate = FALSE;  // mouse position will be updated by the first hidden dock.
1052 	g_list_foreach (s_pRootDockList, (GFunc) _cairo_dock_unhide_root_dock_on_mouse_hit, &mouse);
1053 
1054 	return TRUE;
1055 }
_start_polling_screen_edge(void)1056 static void _start_polling_screen_edge (void)
1057 {
1058 	s_iNbPolls ++;
1059 	cd_debug ("%s (%d)", __func__, s_iNbPolls);
1060 	if (s_iSidPollScreenEdge == 0)
1061 		s_iSidPollScreenEdge = g_timeout_add (MOUSE_POLLING_DT, (GSourceFunc) _cairo_dock_poll_screen_edge, NULL);
1062 }
1063 
_stop_polling_screen_edge_now(void)1064 static void _stop_polling_screen_edge_now (void)
1065 {
1066 	if (s_iSidPollScreenEdge != 0)
1067 	{
1068 		g_source_remove (s_iSidPollScreenEdge);
1069 		s_iSidPollScreenEdge = 0;
1070 	}
1071 	s_iNbPolls = 0;
1072 }
_stop_polling_screen_edge(void)1073 static void _stop_polling_screen_edge (void)
1074 {
1075 	cd_debug ("%s (%d)", __func__, s_iNbPolls);
1076 	s_iNbPolls --;
1077 	if (s_iNbPolls <= 0)
1078 	{
1079 		_stop_polling_screen_edge_now ();  // remet tout a 0.
1080 	}
1081 }
1082 
gldi_dock_set_visibility(CairoDock * pDock,CairoDockVisibility iVisibility)1083 void gldi_dock_set_visibility (CairoDock *pDock, CairoDockVisibility iVisibility)
1084 {
1085 	//\_______________ jeu de parametres.
1086 	gboolean bReserveSpace = (iVisibility == CAIRO_DOCK_VISI_RESERVE);
1087 	gboolean bKeepBelow = (iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW);
1088 	gboolean bAutoHideOnOverlap = (iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP);
1089 	gboolean bAutoHideOnAnyOverlap = (iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY);
1090 	gboolean bAutoHide = (iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE);
1091 	gboolean bShortKey = (iVisibility == CAIRO_DOCK_VISI_SHORTKEY);
1092 
1093 	gboolean bReserveSpace0 = (pDock->iVisibility == CAIRO_DOCK_VISI_RESERVE);
1094 	gboolean bKeepBelow0 = (pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW);
1095 	gboolean bAutoHideOnOverlap0 = (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP);
1096 	gboolean bAutoHideOnAnyOverlap0 = (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY);
1097 	gboolean bAutoHide0 = (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE);
1098 	gboolean bShortKey0 = (pDock->iVisibility == CAIRO_DOCK_VISI_SHORTKEY);
1099 
1100 	pDock->iVisibility = iVisibility;
1101 
1102 	//\_______________ changement dans le Reserve Space.
1103 	if (bReserveSpace != bReserveSpace0)
1104 		cairo_dock_reserve_space_for_dock (pDock, bReserveSpace);
1105 
1106 	//\_______________ changement dans le Keep below.
1107 	if (bKeepBelow != bKeepBelow0)
1108 	{
1109 		if (bKeepBelow)
1110 			cairo_dock_pop_down (pDock);
1111 		else
1112 			cairo_dock_pop_up (pDock);
1113 	}
1114 
1115 	//\_______________ changement dans l'Auto-Hide
1116 	if (bAutoHideOnOverlap != bAutoHideOnOverlap0 ||
1117 		bAutoHideOnAnyOverlap != bAutoHideOnAnyOverlap0 ||
1118 		bAutoHide != bAutoHide0)
1119 	{
1120 		if (bAutoHide)
1121 		{
1122 			pDock->bTemporaryHidden = FALSE;
1123 			pDock->bAutoHide = TRUE;
1124 			cairo_dock_start_hiding (pDock);
1125 		}
1126 		else if (bAutoHideOnAnyOverlap)
1127 		{
1128 			pDock->bTemporaryHidden = pDock->bAutoHide;  // needed to use the following function
1129 			gldi_dock_hide_if_any_window_overlap_or_show (pDock);
1130 		}
1131 		else
1132 		{
1133 			if (! bAutoHideOnOverlap)
1134 			{
1135 				pDock->bTemporaryHidden = FALSE;
1136 				pDock->bAutoHide = FALSE;
1137 				cairo_dock_start_showing (pDock);
1138 			}
1139 			if (bAutoHideOnOverlap)
1140 			{
1141 				pDock->bTemporaryHidden = pDock->bAutoHide;  // needed to use the following function
1142 				gldi_dock_hide_show_if_current_window_is_on_our_way (pDock);
1143 			}
1144 		}
1145 	}
1146 
1147 	//\_______________ shortkey
1148 	if (pDock->bIsMainDock)
1149 	{
1150 		if (bShortKey)  // option is enabled.
1151 		{
1152 			if (s_pPopupBinding && gldi_shortkey_could_grab (s_pPopupBinding))  // a shortkey has been registered and grabbed to show/hide the dock => hide the dock.
1153 			{
1154 				gtk_widget_hide (pDock->container.pWidget);
1155 			}
1156 			else  // bind couldn't be done (no shortkey or couldn't grab it).
1157 			{
1158 				// g_print ("bind couldn't be done (no shortkey or couldn't grab it).\n");
1159 				pDock->iVisibility = CAIRO_DOCK_VISI_KEEP_ABOVE;
1160 			}
1161 		}
1162 		else if (bShortKey0)  // option is now disabled => show the dock.
1163 		{
1164 			_reposition_root_docks (FALSE);  // FALSE => tous.
1165 		}
1166 	}
1167 
1168 	//\_______________ on arrete/demarre la scrutation des bords.
1169 	gboolean bIsPolling = (bAutoHide0 || bAutoHideOnOverlap0 || bAutoHideOnAnyOverlap0 || bKeepBelow0);
1170 	gboolean bShouldPoll = (bAutoHide || bAutoHideOnOverlap || bAutoHideOnAnyOverlap || bKeepBelow);
1171 	if (bIsPolling && ! bShouldPoll)
1172 		_stop_polling_screen_edge ();
1173 	else if (!bIsPolling && bShouldPoll)
1174 		_start_polling_screen_edge ();
1175 }
1176 
1177 
1178   /////////////////
1179  /// CALLBACKS ///
1180 /////////////////
1181 
_autohide_after_shortkey(CairoDock * pDock)1182 static gboolean _autohide_after_shortkey (CairoDock *pDock)
1183 {
1184 	if (pDock->iVisibility == CAIRO_DOCK_VISI_SHORTKEY && gldi_container_is_visible (CAIRO_CONTAINER (pDock)) && ! pDock->container.bInside)
1185 		gtk_widget_hide (pDock->container.pWidget);
1186 	pDock->iSidHideBack = 0;
1187 	return FALSE;
1188 }
_show_dock_at_mouse(CairoDock * pDock,G_GNUC_UNUSED gpointer data)1189 static void _show_dock_at_mouse (CairoDock *pDock, G_GNUC_UNUSED gpointer data)
1190 {
1191 	if (pDock->iVisibility != CAIRO_DOCK_VISI_SHORTKEY)
1192 		return;
1193 
1194 	if (gldi_container_is_visible (CAIRO_CONTAINER (pDock)))  // already visible -> hide (toggle)
1195 	{
1196 		gtk_widget_hide (pDock->container.pWidget);
1197 	}
1198 	else  // invisible -> show
1199 	{
1200 		// calculate the position where the dock will be shown (under the mouse)
1201 		gldi_container_update_mouse_position (CAIRO_CONTAINER (pDock));
1202 
1203 		int W = gldi_dock_get_screen_width (pDock), H = gldi_dock_get_screen_height (pDock);
1204 		int iScreenOffsetX = gldi_dock_get_screen_offset_x (pDock), iScreenOffsetY = gldi_dock_get_screen_offset_y (pDock);
1205 		///pDock->iGapX = pDock->container.iWindowPositionX + iMouseX - g_desktopGeometry.iScreenWidth[pDock->container.bIsHorizontal] * pDock->fAlign;
1206 		///pDock->iGapY = (pDock->container.bDirectionUp ? g_desktopGeometry.iScreenHeight[pDock->container.bIsHorizontal] - (pDock->container.iWindowPositionY + iMouseY) : pDock->container.iWindowPositionY + iMouseY);
1207 		pDock->iGapX = pDock->container.iWindowPositionX + pDock->container.iMouseX - (W - pDock->container.iWidth) * pDock->fAlign - pDock->container.iWidth/2 - iScreenOffsetX;
1208 		pDock->iGapY = (pDock->container.bDirectionUp ? H - (pDock->container.iWindowPositionY + pDock->container.iMouseY) : pDock->container.iWindowPositionY + pDock->container.iMouseY) - iScreenOffsetY;
1209 		cd_debug (" => %d;%d", g_pMainDock->iGapX, g_pMainDock->iGapY);
1210 
1211 		int iNewPositionX, iNewPositionY;
1212 		cairo_dock_get_window_position_at_balance (pDock,
1213 			pDock->container.iWidth, pDock->container.iHeight,
1214 			&iNewPositionX, &iNewPositionY);
1215 		cd_debug (" ==> %d;%d", iNewPositionX, iNewPositionY);
1216 		if (iNewPositionX < 0)
1217 			iNewPositionX = 0;
1218 		else if (iNewPositionX + pDock->container.iWidth > W)
1219 			iNewPositionX = W - pDock->container.iWidth;
1220 
1221 		if (iNewPositionY < 0)
1222 			iNewPositionY = 0;
1223 		else if (iNewPositionY + pDock->container.iHeight > H)
1224 			iNewPositionY = H - pDock->container.iHeight;
1225 
1226 		// show the dock
1227 		gtk_window_move (GTK_WINDOW (pDock->container.pWidget),
1228 			(pDock->container.bIsHorizontal ? iNewPositionX : iNewPositionY),
1229 			(pDock->container.bIsHorizontal ? iNewPositionY : iNewPositionX));
1230 		gtk_widget_show (pDock->container.pWidget);
1231 
1232 		// schedule a hiding in a few seconds
1233 		if (pDock->iSidHideBack != 0)
1234 			g_source_remove (pDock->iSidHideBack);
1235 		pDock->iSidHideBack = g_timeout_add (3000, (GSourceFunc) _autohide_after_shortkey, (gpointer) pDock);
1236 	}
1237 }
_raise_from_shortcut(G_GNUC_UNUSED const char * cKeyShortcut,G_GNUC_UNUSED gpointer data)1238 static void _raise_from_shortcut (G_GNUC_UNUSED const char *cKeyShortcut, G_GNUC_UNUSED gpointer data)
1239 {
1240 	// g_print ("shortkey\n");
1241 	gldi_docks_foreach_root ((GFunc)_show_dock_at_mouse, NULL);
1242 }
1243 
_on_screen_geometry_changed(G_GNUC_UNUSED gpointer data,gboolean bSizeHasChanged)1244 static gboolean _on_screen_geometry_changed (G_GNUC_UNUSED gpointer data, gboolean bSizeHasChanged)
1245 {
1246 	if (bSizeHasChanged)
1247 		_reposition_root_docks (FALSE);  // FALSE <=> main dock included
1248 	return GLDI_NOTIFICATION_LET_PASS;
1249 }
1250 
_on_new_dialog(G_GNUC_UNUSED gpointer data,CairoDialog * pDialog)1251 static gboolean _on_new_dialog (G_GNUC_UNUSED gpointer data, CairoDialog *pDialog)
1252 {
1253 	//\________________ hide sub-dock or label that would overlap it
1254 	Icon *pIcon = pDialog->pIcon;
1255 	if (! pIcon)
1256 		return GLDI_NOTIFICATION_LET_PASS;
1257 
1258 	if (pIcon->pSubDock)  // un sous-dock par-dessus le dialogue est tres genant.
1259 	{
1260 		cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pIcon->pSubDock));
1261 	}
1262 
1263 	GldiContainer *pContainer = cairo_dock_get_icon_container (pIcon);
1264 	if (CAIRO_DOCK_IS_DOCK (pContainer) && cairo_dock_get_icon_max_scale (pIcon) < 1.01)  // view without zoom, the dialog is stuck to the icon, and therefore is under the label, so hide this one.
1265 	{
1266 		if (pIcon->iHideLabel == 0)
1267 			gtk_widget_queue_draw (pContainer->pWidget);
1268 		pIcon->iHideLabel ++;
1269 	}
1270 
1271 	return GLDI_NOTIFICATION_LET_PASS;
1272 }
1273 
_render_dock_notification(G_GNUC_UNUSED gpointer pUserData,CairoDock * pDock,cairo_t * pCairoContext)1274 static gboolean _render_dock_notification (G_GNUC_UNUSED gpointer pUserData, CairoDock *pDock, cairo_t *pCairoContext)
1275 {
1276 	if (pCairoContext)  // cairo
1277 	{
1278 		if (pDock->fHideOffset != 0 && g_pHidingBackend != NULL && g_pHidingBackend->pre_render)
1279 			g_pHidingBackend->pre_render (pDock, pDock->fHideOffset, pCairoContext);
1280 
1281 		if (pDock->iFadeCounter != 0 && g_pKeepingBelowBackend != NULL && g_pKeepingBelowBackend->pre_render)
1282 			g_pKeepingBelowBackend->pre_render (pDock, (double) pDock->iFadeCounter / myBackendsParam.iHideNbSteps, pCairoContext);
1283 
1284 		/// TODO: see if it's ok to not use the optimized rendering any more...
1285 		/// if not, we can probably get the clip on the cairo context
1286 		pDock->pRenderer->render (pCairoContext, pDock);
1287 
1288 		if (pDock->fHideOffset != 0 && g_pHidingBackend != NULL && g_pHidingBackend->post_render)
1289 			g_pHidingBackend->post_render (pDock, pDock->fHideOffset, pCairoContext);
1290 
1291 		if (pDock->iFadeCounter != 0 && g_pKeepingBelowBackend != NULL && g_pKeepingBelowBackend->post_render)
1292 			g_pKeepingBelowBackend->post_render (pDock, (double) pDock->iFadeCounter / myBackendsParam.iHideNbSteps, pCairoContext);
1293 	}
1294 	else  // opengl
1295 	{
1296 		if (pDock->fHideOffset != 0 && g_pHidingBackend != NULL && g_pHidingBackend->pre_render_opengl)
1297 			g_pHidingBackend->pre_render_opengl (pDock, pDock->fHideOffset);
1298 
1299 		if (pDock->iFadeCounter != 0 && g_pKeepingBelowBackend != NULL && g_pKeepingBelowBackend->pre_render_opengl)
1300 			g_pKeepingBelowBackend->pre_render_opengl (pDock, (double) pDock->iFadeCounter / myBackendsParam.iHideNbSteps);
1301 
1302 		pDock->pRenderer->render_opengl (pDock);
1303 
1304 		if (pDock->fHideOffset != 0 && g_pHidingBackend != NULL && g_pHidingBackend->post_render_opengl)
1305 			g_pHidingBackend->post_render_opengl (pDock, pDock->fHideOffset);
1306 
1307 		if (pDock->iFadeCounter != 0 && g_pKeepingBelowBackend != NULL && g_pKeepingBelowBackend->post_render_opengl)
1308 			g_pKeepingBelowBackend->post_render_opengl (pDock, (double) pDock->iFadeCounter / myBackendsParam.iHideNbSteps);
1309 	}
1310 	return GLDI_NOTIFICATION_LET_PASS;
1311 }
1312 
_on_leave_dock(G_GNUC_UNUSED gpointer data,CairoDock * pDock,G_GNUC_UNUSED gboolean * bStartAnimation)1313 static gboolean _on_leave_dock (G_GNUC_UNUSED gpointer data, CairoDock *pDock, G_GNUC_UNUSED gboolean *bStartAnimation)
1314 {
1315 	//g_print ("%s (%d, %d)\n", __func__, pDock->iRefCount, pDock->bHasModalWindow);
1316 
1317 	//\_______________ On lance l'animation du dock.
1318 	if (pDock->iRefCount == 0)
1319 	{
1320 		//g_print ("%s (auto-hide:%d)\n", __func__, pDock->bAutoHide);
1321 		if (pDock->bAutoHide)
1322 		{
1323 			///pDock->fFoldingFactor = (myBackendsParam.bAnimateOnAutoHide ? 0.001 : 0.);
1324 			cairo_dock_start_hiding (pDock);
1325 		}
1326 	}
1327 	else if (pDock->icons != NULL)
1328 	{
1329 		pDock->fFoldingFactor = (myDocksParam.bAnimateSubDock ? 0.001 : 0.);
1330 		Icon *pIcon = cairo_dock_search_icon_pointing_on_dock (pDock, NULL);
1331 		//g_print ("'%s' se replie\n", pIcon?pIcon->cName:"none");
1332 		gldi_object_notify (pIcon, NOTIFICATION_UNFOLD_SUBDOCK, pIcon);
1333 	}
1334 	//g_print ("start shrinking\n");
1335 	cairo_dock_start_shrinking (pDock);  // on commence a faire diminuer la taille des icones.
1336 	return GLDI_NOTIFICATION_LET_PASS;
1337 }
1338 
_update_removing_inserting_icon_size(Icon * icon)1339 static void _update_removing_inserting_icon_size (Icon *icon)
1340 {
1341 	icon->fInsertRemoveFactor *= .85;
1342 	if (icon->fInsertRemoveFactor > 0)
1343 	{
1344 		if (icon->fInsertRemoveFactor < 0.05)
1345 			icon->fInsertRemoveFactor = 0.05;
1346 	}
1347 	else if (icon->fInsertRemoveFactor < 0)
1348 	{
1349 		if (icon->fInsertRemoveFactor > -0.05)
1350 			icon->fInsertRemoveFactor = -0.05;
1351 	}
1352 }
1353 
on_update_inserting_removing_icon(G_GNUC_UNUSED gpointer pUserData,Icon * pIcon,CairoDock * pDock,gboolean * bContinueAnimation)1354 static gboolean on_update_inserting_removing_icon (G_GNUC_UNUSED gpointer pUserData, Icon *pIcon, CairoDock *pDock, gboolean *bContinueAnimation)
1355 {
1356 	if (pIcon->iGlideDirection != 0)
1357 	{
1358 		pIcon->fGlideOffset += pIcon->iGlideDirection * .1;
1359 		if (fabs (pIcon->fGlideOffset) > .99)
1360 		{
1361 			pIcon->fGlideOffset = pIcon->iGlideDirection;
1362 			pIcon->iGlideDirection = 0;
1363 		}
1364 		else if (fabs (pIcon->fGlideOffset) < .01)
1365 		{
1366 			pIcon->fGlideOffset = 0;
1367 			pIcon->iGlideDirection = 0;
1368 		}
1369 		*bContinueAnimation = TRUE;
1370 		cairo_dock_redraw_container (CAIRO_CONTAINER (pDock));
1371 	}
1372 
1373 	if (pIcon->fInsertRemoveFactor != 0) // the icon is being inserted/removed
1374 	{
1375 		_update_removing_inserting_icon_size (pIcon);
1376 		if (fabs (pIcon->fInsertRemoveFactor) > 0.05)  // the animation is not yet finished
1377 		{
1378 			cairo_dock_mark_icon_as_inserting_removing (pIcon);
1379 			*bContinueAnimation = TRUE;
1380 		}
1381 		cairo_dock_redraw_container (CAIRO_CONTAINER (pDock));
1382 	}
1383 	return GLDI_NOTIFICATION_LET_PASS;
1384 }
1385 
on_insert_remove_icon(G_GNUC_UNUSED gpointer pUserData,Icon * pIcon,G_GNUC_UNUSED CairoDock * pDock)1386 static gboolean on_insert_remove_icon (G_GNUC_UNUSED gpointer pUserData, Icon *pIcon, G_GNUC_UNUSED CairoDock *pDock)
1387 {
1388 	if (pIcon->fInsertRemoveFactor == 0)  // animation not needed.
1389 		return GLDI_NOTIFICATION_LET_PASS;
1390 
1391 	cairo_dock_mark_icon_as_inserting_removing (pIcon);  // On prend en charge le dessin de l'icone pendant sa phase d'insertion/suppression.
1392 
1393 	return GLDI_NOTIFICATION_LET_PASS;
1394 }
1395 
on_stop_inserting_removing_icon(G_GNUC_UNUSED gpointer pUserData,Icon * pIcon)1396 static gboolean on_stop_inserting_removing_icon (G_GNUC_UNUSED gpointer pUserData, Icon *pIcon)
1397 {
1398 	pIcon->fGlideOffset = 0;
1399 	pIcon->iGlideDirection = 0;
1400 	return GLDI_NOTIFICATION_LET_PASS;
1401 }
1402 
1403 
1404   //////////////////
1405  /// GET CONFIG ///
1406 //////////////////
1407 
get_config(GKeyFile * pKeyFile,CairoDocksParam * pDocksParam)1408 static gboolean get_config (GKeyFile *pKeyFile, CairoDocksParam *pDocksParam)
1409 {
1410 	gboolean bFlushConfFileNeeded = FALSE;
1411 
1412 	CairoDocksParam *pBackground = pDocksParam;
1413 	CairoDocksParam *pPosition = pDocksParam;
1414 	CairoDocksParam *pAccessibility = pDocksParam;
1415 	CairoDocksParam *pSystem = pDocksParam;
1416 
1417 	// frame
1418 	pBackground->iDockRadius = cairo_dock_get_integer_key_value (pKeyFile, "Background", "corner radius", &bFlushConfFileNeeded, 12, NULL, NULL);
1419 
1420 	pBackground->iDockLineWidth = cairo_dock_get_integer_key_value (pKeyFile, "Background", "line width", &bFlushConfFileNeeded, 2, NULL, NULL);
1421 
1422 	pBackground->iFrameMargin = cairo_dock_get_integer_key_value (pKeyFile, "Background", "frame margin", &bFlushConfFileNeeded, 2, NULL, NULL);
1423 
1424 	GldiColor couleur = {{0., 0., 0.6, 0.4}};
1425 	cairo_dock_get_color_key_value (pKeyFile, "Background", "line color", &bFlushConfFileNeeded, &pBackground->fLineColor, &couleur, NULL, NULL);
1426 
1427 	pBackground->bRoundedBottomCorner = cairo_dock_get_boolean_key_value (pKeyFile, "Background", "rounded bottom corner", &bFlushConfFileNeeded, TRUE, NULL, NULL);
1428 
1429 	// background image
1430 	int iStyle = cairo_dock_get_integer_key_value (pKeyFile, "Background", "style", &bFlushConfFileNeeded, -1, NULL, NULL);  // -1 pour intercepter le cas ou la cle n'existe pas.
1431 	if (iStyle == -1)  // old params < 3.4
1432 	{
1433 		iStyle = g_key_file_get_integer (pKeyFile, "Background", "fill bg", NULL);
1434 		iStyle ++;
1435 		g_key_file_set_integer (pKeyFile, "Background", "style", iStyle);
1436 	}
1437 
1438 	if (iStyle == 0)
1439 	{
1440 		pBackground->bUseDefaultColors = TRUE;
1441 		pBackground->iDockRadius = myStyleParam.iCornerRadius;
1442 		pBackground->iDockLineWidth = myStyleParam.iLineWidth;
1443 	}
1444 	else if (iStyle == 1)
1445 	{
1446 		gchar *cBgImage = (iStyle == 1 ? cairo_dock_get_string_key_value (pKeyFile, "Background", "background image", &bFlushConfFileNeeded, NULL, NULL, NULL) : NULL);
1447 		if (cBgImage != NULL)
1448 		{
1449 			pBackground->cBackgroundImageFile = cairo_dock_search_image_s_path (cBgImage);
1450 			g_free (cBgImage);
1451 			pBackground->fBackgroundImageAlpha = cairo_dock_get_double_key_value (pKeyFile, "Background", "image alpha", &bFlushConfFileNeeded, 0.5, NULL, NULL);
1452 			pBackground->bBackgroundImageRepeat = cairo_dock_get_boolean_key_value (pKeyFile, "Background", "repeat image", &bFlushConfFileNeeded, FALSE, NULL, NULL);
1453 		}
1454 	}
1455 
1456 	// background gradation
1457 	if (iStyle != 0 && pBackground->cBackgroundImageFile == NULL)
1458 	{
1459 		pBackground->iNbStripes = cairo_dock_get_integer_key_value (pKeyFile, "Background", "number of stripes", &bFlushConfFileNeeded, 10, NULL, NULL);
1460 
1461 		if (pBackground->iNbStripes != 0)
1462 		{
1463 			pBackground->fStripesWidth = MAX (.01, MIN (.99, cairo_dock_get_double_key_value (pKeyFile, "Background", "stripes width", &bFlushConfFileNeeded, 0.2, NULL, NULL))) / pBackground->iNbStripes;
1464 		}
1465 		GldiColor couleur3 = {{.7, .7, 1., .7}};
1466 		cairo_dock_get_color_key_value (pKeyFile, "Background", "stripes color dark", &bFlushConfFileNeeded, &pBackground->fStripesColorDark, &couleur3, NULL, NULL);
1467 
1468 		GldiColor couleur2 = {{.7, .9, .7, .4}};
1469 		cairo_dock_get_color_key_value (pKeyFile, "Background", "stripes color bright", &bFlushConfFileNeeded, &pBackground->fStripesColorBright, &couleur2, NULL, NULL);
1470 
1471 		pBackground->fStripesAngle = cairo_dock_get_double_key_value (pKeyFile, "Background", "stripes angle", &bFlushConfFileNeeded, 90., NULL, NULL);
1472 	}
1473 
1474 	pAccessibility->bExtendedMode = cairo_dock_get_boolean_key_value (pKeyFile, "Background", "extended", &bFlushConfFileNeeded, FALSE, "Accessibility", NULL);
1475 
1476 	// hidden bg
1477 	GldiColor hcolor = {{.8, .8, .8, .5}};
1478 	cairo_dock_get_color_key_value (pKeyFile, "Background", "hidden bg color", &bFlushConfFileNeeded, &pBackground->fHiddenBg, &hcolor, NULL, NULL);
1479 
1480 	// position
1481 	pPosition->iGapX = cairo_dock_get_integer_key_value (pKeyFile, "Position", "x gap", &bFlushConfFileNeeded, 0, NULL, NULL);
1482 	pPosition->iGapY = cairo_dock_get_integer_key_value (pKeyFile, "Position", "y gap", &bFlushConfFileNeeded, 0, NULL, NULL);
1483 
1484 	pPosition->iScreenBorder = cairo_dock_get_integer_key_value (pKeyFile, "Position", "screen border", &bFlushConfFileNeeded, 0, NULL, NULL);
1485 	if (pPosition->iScreenBorder >= CAIRO_DOCK_NB_POSITIONS)
1486 		pPosition->iScreenBorder = 0;
1487 
1488 	pPosition->fAlign = cairo_dock_get_double_key_value (pKeyFile, "Position", "alignment", &bFlushConfFileNeeded, 0.5, NULL, NULL);
1489 
1490 	pPosition->iNumScreen = cairo_dock_get_integer_key_value (pKeyFile, "Position", "num_screen", &bFlushConfFileNeeded, GLDI_DEFAULT_SCREEN, NULL, NULL);  // Note: if this screen doesn't exist at this time, we keep this number anyway, in case it is plugged later. Until then, it will point on the X screen.
1491 	if (g_key_file_has_key (pKeyFile, "Position", "xinerama", NULL))  // "xinerama" and "num screen" old keys
1492 	{
1493 		if (g_key_file_get_boolean (pKeyFile," Position", "xinerama", NULL))  // xinerama was used -> set num-screen back
1494 		{
1495 			pPosition->iNumScreen = g_key_file_get_integer (pKeyFile, "Position", "num screen", NULL); // "num screen" was the old key
1496 			g_key_file_set_integer (pKeyFile, "Position", "num_screen", pPosition->iNumScreen);
1497 		}
1498 	}
1499 
1500 	//\____________________ Visibilite
1501 	int iVisibility = cairo_dock_get_integer_key_value (pKeyFile, "Accessibility", "visibility", &bFlushConfFileNeeded, -1, NULL, NULL);  // -1 pour pouvoir intercepter le cas ou la cle n'existe pas.
1502 
1503 	gchar *cShortkey = cairo_dock_get_string_key_value (pKeyFile, "Accessibility", "raise shortcut", &bFlushConfFileNeeded, NULL, "Position", NULL);
1504 
1505 	pAccessibility->cHideEffect = cairo_dock_get_string_key_value (pKeyFile, "Accessibility", "hide effect", &bFlushConfFileNeeded, NULL, NULL, NULL);
1506 
1507 	if (iVisibility == -1)  // option nouvelle 2.1.3
1508 	{
1509 		if (g_key_file_get_boolean (pKeyFile, "Accessibility", "reserve space", NULL))
1510 			iVisibility = CAIRO_DOCK_VISI_KEEP_ABOVE;
1511 		else if (g_key_file_get_boolean (pKeyFile, "Accessibility", "pop-up", NULL))  // on force au nouveau mode.
1512 		{
1513 			iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY;
1514 			pAccessibility->cHideEffect = g_strdup_printf ("Fade out");  // on force a "fade out" pour garder le meme effet.
1515 			g_key_file_set_string (pKeyFile, "Accessibility", "hide effect", pAccessibility->cHideEffect);
1516 		}
1517 		else if (g_key_file_get_boolean (pKeyFile, "Accessibility", "auto-hide", NULL))
1518 			iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE;
1519 		else if (g_key_file_get_boolean (pKeyFile, "Accessibility", "auto quick hide on max", NULL))
1520 			iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY;
1521 		else if (cShortkey)
1522 		{
1523 			iVisibility = CAIRO_DOCK_VISI_SHORTKEY;
1524 			pAccessibility->cRaiseDockShortcut = cShortkey;
1525 			cShortkey = NULL;
1526 		}
1527 		else
1528 			iVisibility = CAIRO_DOCK_VISI_KEEP_ABOVE;
1529 
1530 		g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility);
1531 	}
1532 	else
1533 	{
1534 		if (pAccessibility->cHideEffect == NULL)  // nouvelle option 2.2.0, cela a change l'ordre du menu.
1535 		{
1536 			// avant c'etait : KEEP_ABOVE, RESERVE, KEEP_BELOW, AUTO_HIDE,       HIDE_ON_MAXIMIZED,   SHORTKEY
1537 			// mtn c'est     : KEEP_ABOVE, RESERVE, KEEP_BELOW, HIDE_ON_OVERLAP, HIDE_ON_OVERLAP_ANY, AUTO_HIDE, VISI_SHORTKEY,
1538 			if (iVisibility == 2)  // on force au nouveau mode.
1539 			{
1540 				iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY;
1541 				pAccessibility->cHideEffect = g_strdup_printf ("Fade out");  // on force a "fade out" pour garder le meme effet.
1542 				g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility);
1543 				g_key_file_set_string (pKeyFile, "Accessibility", "hide effect", pAccessibility->cHideEffect);
1544 			}
1545 			else if (iVisibility == 3)
1546 			{
1547 				iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE;
1548 				g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility);
1549 			}
1550 			else if (iVisibility == 4)
1551 			{
1552 				iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY;
1553 				g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility);
1554 			}
1555 			else if (iVisibility == 5)
1556 			{
1557 				iVisibility = CAIRO_DOCK_VISI_SHORTKEY;
1558 				g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility);
1559 			}
1560 		}
1561 		if (iVisibility == CAIRO_DOCK_VISI_SHORTKEY)
1562 		{
1563 			pAccessibility->cRaiseDockShortcut = cShortkey;
1564 			cShortkey = NULL;
1565 		}
1566 	}
1567 	pAccessibility->iVisibility = iVisibility;
1568 	g_free (cShortkey);
1569 	if (pAccessibility->cHideEffect == NULL)
1570 	{
1571 		pAccessibility->cHideEffect = g_strdup_printf ("Move down");
1572 		g_key_file_set_string (pKeyFile, "Accessibility", "hide effect", pAccessibility->cHideEffect);
1573 	}
1574 
1575 	pAccessibility->iCallbackMethod = cairo_dock_get_integer_key_value (pKeyFile, "Accessibility", "callback", &bFlushConfFileNeeded, CAIRO_HIT_DOCK_PLACE, NULL, NULL);
1576 
1577 	if (pAccessibility->iCallbackMethod == CAIRO_HIT_ZONE)
1578 	{
1579 		if (! g_key_file_has_key (pKeyFile, "Accessibility", "zone size", NULL))
1580 		{
1581 			pAccessibility->iZoneWidth = 100;
1582 			pAccessibility->iZoneHeight = 10;
1583 			int list[2] = {pAccessibility->iZoneWidth, pAccessibility->iZoneHeight};
1584 			g_key_file_set_integer_list (pKeyFile, "Accessibility", "zone size", list, 2);
1585 		}
1586 		cairo_dock_get_size_key_value_helper (pKeyFile, "Accessibility", "zone ", bFlushConfFileNeeded, pAccessibility->iZoneWidth, pAccessibility->iZoneHeight);
1587 		if (pAccessibility->iZoneWidth < 20)
1588 			pAccessibility->iZoneWidth = 20;
1589 		if (pAccessibility->iZoneHeight < 2)
1590 			pAccessibility->iZoneHeight = 2;
1591 		pAccessibility->cZoneImage = cairo_dock_get_string_key_value (pKeyFile, "Accessibility", "callback image", &bFlushConfFileNeeded, 0, "Background", NULL);
1592 		pAccessibility->fZoneAlpha = 1.;  // on laisse l'utilisateur definir la transparence qu'il souhaite directement dans l'image.
1593 	}
1594 
1595 	//\____________________ Autres parametres.
1596 	double fSensitivity = cairo_dock_get_double_key_value (pKeyFile, "Accessibility", "edge sensitivity", &bFlushConfFileNeeded, -1, NULL, NULL);  // replace "unhide delay"
1597 	if (fSensitivity < 0)  // old param
1598 	{
1599 		int iUnhideDockDelay = g_key_file_get_integer (pKeyFile, "Accessibility", "unhide delay", NULL);
1600 		fSensitivity = iUnhideDockDelay / 1500.;  // 0 -> 0 = sensitive, 1500 -> 1 = not sensitive
1601 		g_key_file_set_double (pKeyFile, "Accessibility", "edge sensitivity", fSensitivity);
1602 	}
1603 	pAccessibility->iUnhideDockDelay = fSensitivity * 1000;  // so we decreased the old delay by 1.5, since we handle mouse movements better.
1604 
1605 	//\____________________ sous-docks.
1606 	pAccessibility->iLeaveSubDockDelay = cairo_dock_get_integer_key_value (pKeyFile, "Accessibility", "leaving delay", &bFlushConfFileNeeded, 330, "System", NULL);
1607 	pAccessibility->iShowSubDockDelay = cairo_dock_get_integer_key_value (pKeyFile, "Accessibility", "show delay", &bFlushConfFileNeeded, 300, "System", NULL);
1608 	if (!g_key_file_has_key (pKeyFile, "Accessibility", "show_on_click", NULL))
1609 	{
1610 		pAccessibility->bShowSubDockOnClick = cairo_dock_get_boolean_key_value (pKeyFile, "Accessibility", "show on click", &bFlushConfFileNeeded, FALSE, "System", NULL);
1611 		g_key_file_set_integer (pKeyFile, "Accessibility", "show_on_click", pAccessibility->bShowSubDockOnClick ? 1 : 0);
1612 		bFlushConfFileNeeded = TRUE;
1613 	}
1614 	else
1615 		pAccessibility->bShowSubDockOnClick = (cairo_dock_get_integer_key_value (pKeyFile, "Accessibility", "show_on_click", &bFlushConfFileNeeded, 0, NULL, NULL) == 1);
1616 
1617 	//\____________________ lock
1618 	///pAccessibility->bLockAll = cairo_dock_get_boolean_key_value (pKeyFile, "Accessibility", "lock all", &bFlushConfFileNeeded, FALSE, NULL, NULL);
1619 	pAccessibility->bLockIcons = pAccessibility->bLockAll || cairo_dock_get_boolean_key_value (pKeyFile, "Accessibility", "lock icons", &bFlushConfFileNeeded, FALSE, NULL, NULL);
1620 
1621 	// system
1622 	pSystem->bAnimateSubDock = cairo_dock_get_boolean_key_value (pKeyFile, "System", "animate subdocks", &bFlushConfFileNeeded, TRUE, "Sub-Docks", NULL);
1623 
1624 	return bFlushConfFileNeeded;
1625 }
1626 
1627 
1628   ////////////////////
1629  /// RESET CONFIG ///
1630 ////////////////////
1631 
reset_config(CairoDocksParam * pDocksParam)1632 static void reset_config (CairoDocksParam *pDocksParam)
1633 {
1634 	CairoDocksParam *pBackground = pDocksParam;
1635 	CairoDocksParam *pAccessibility = pDocksParam;
1636 
1637 	// background
1638 	g_free (pBackground->cBackgroundImageFile);
1639 
1640 	// accessibility
1641 	g_free (pAccessibility->cRaiseDockShortcut);
1642 	g_free (pAccessibility->cHideEffect);
1643 	g_free (pAccessibility->cZoneImage);
1644 }
1645 
1646 
1647   ////////////
1648  /// LOAD ///
1649 ////////////
1650 
_load_visible_zone(const gchar * cVisibleZoneImageFile,int iVisibleZoneWidth,int iVisibleZoneHeight,double fVisibleZoneAlpha)1651 static void _load_visible_zone (const gchar *cVisibleZoneImageFile, int iVisibleZoneWidth, int iVisibleZoneHeight, double fVisibleZoneAlpha)
1652 {
1653 	cairo_dock_unload_image_buffer (&g_pVisibleZoneBuffer);
1654 
1655 	cairo_dock_load_image_buffer_full (&g_pVisibleZoneBuffer,
1656 		cVisibleZoneImageFile,
1657 		iVisibleZoneWidth,
1658 		iVisibleZoneHeight,
1659 		CAIRO_DOCK_FILL_SPACE,
1660 		fVisibleZoneAlpha);
1661 }
load(void)1662 static void load (void)
1663 {
1664 	_load_visible_zone (myDocksParam.cZoneImage, myDocksParam.iZoneWidth, myDocksParam.iZoneHeight, myDocksParam.fZoneAlpha);
1665 
1666 	g_pHidingBackend = cairo_dock_get_hiding_effect (myDocksParam.cHideEffect);
1667 
1668 	if (g_pKeepingBelowBackend == NULL)  // pas d'option en config pour ca.
1669 		g_pKeepingBelowBackend = cairo_dock_get_hiding_effect ("Fade out");
1670 
1671 	// the first main dock doesn't have a config file, its parameters are the global ones.
1672 	if (g_pMainDock)
1673 	{
1674 		g_pMainDock->iGapX = myDocksParam.iGapX;
1675 		g_pMainDock->iGapY = myDocksParam.iGapY;
1676 		g_pMainDock->fAlign = myDocksParam.fAlign;
1677 		g_pMainDock->iNumScreen = myDocksParam.iNumScreen;
1678 		g_pMainDock->bExtendedMode = myDocksParam.bExtendedMode;
1679 
1680 		_set_dock_orientation (g_pMainDock, myDocksParam.iScreenBorder);
1681 		cairo_dock_move_resize_dock (g_pMainDock);
1682 
1683 		g_pMainDock->fFlatDockWidth = - myIconsParam.iIconGap;  // car on ne le connaissait pas encore au moment de sa creation.
1684 
1685 		// register a key binding
1686 		if (myDocksParam.iVisibility == CAIRO_DOCK_VISI_SHORTKEY)  // register a key binding
1687 		{
1688 			if (s_pPopupBinding == NULL)
1689 			{
1690 				s_pPopupBinding = gldi_shortkey_new (myDocksParam.cRaiseDockShortcut,
1691 					"Cairo-Dock",
1692 					_("Pop up the main dock"),
1693 					GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON,
1694 					g_cConfFile,
1695 					"Accessibility",
1696 					"raise shortcut",
1697 					(CDBindkeyHandler) _raise_from_shortcut,
1698 					NULL);
1699 			}
1700 			else
1701 			{
1702 				gldi_shortkey_rebind (s_pPopupBinding, myDocksParam.cRaiseDockShortcut, NULL);
1703 			}
1704 		}
1705 
1706 		gldi_dock_set_visibility (g_pMainDock, myDocksParam.iVisibility);
1707 	}
1708 }
1709 
1710 
1711   //////////////
1712  /// RELOAD ///
1713 //////////////
1714 
_reload_bg(CairoDock * pDock,G_GNUC_UNUSED gpointer data)1715 static void _reload_bg (CairoDock *pDock, G_GNUC_UNUSED gpointer data)
1716 {
1717 	pDock->backgroundBuffer.iWidth ++;  // force the reload
1718 	cairo_dock_trigger_load_dock_background (pDock);
1719 }
_init_hiding(CairoDock * pDock,G_GNUC_UNUSED gpointer data)1720 static void _init_hiding (CairoDock *pDock, G_GNUC_UNUSED gpointer data)
1721 {
1722 	if (pDock->bIsShowing || pDock->bIsHiding)
1723 	{
1724 		g_pHidingBackend->init (pDock);
1725 	}
1726 }
reload(CairoDocksParam * pPrevDocksParam,CairoDocksParam * pDocksParam)1727 static void reload (CairoDocksParam *pPrevDocksParam, CairoDocksParam *pDocksParam)
1728 {
1729 	CairoDocksParam *pBackground = pDocksParam;
1730 	CairoDocksParam *pPosition = pDocksParam;
1731 	CairoDocksParam *pAccessibility = pDocksParam;
1732 	// CairoDocksParam *pViews = pDocksParam;
1733 	// CairoDocksParam *pSystem = pDocksParam;
1734 	CairoDocksParam *pPrevBackground = pPrevDocksParam;
1735 	CairoDocksParam *pPrevPosition = pPrevDocksParam;
1736 	CairoDocksParam *pPrevAccessibility = pPrevDocksParam;
1737 	// CairoDocksParam *pPrevViews = pPrevDocksParam;
1738 	// CairoDocksParam *pPrevSystem = pPrevDocksParam;
1739 	CairoDock *pDock = g_pMainDock;
1740 
1741 	// background
1742 	gldi_docks_foreach_root ((GFunc)_reload_bg, NULL);
1743 
1744 	// position
1745 	pDock->iNumScreen = pPosition->iNumScreen;
1746 
1747 	if (pPosition->iNumScreen != pPrevPosition->iNumScreen)
1748 	{
1749 		_reposition_root_docks (TRUE);  // on replace tous les docks racines sauf le main dock, puisque c'est fait apres.
1750 	}
1751 
1752 	CairoDockTypeHorizontality bWasHorizontal = pDock->container.bIsHorizontal;
1753 	if (pPosition->iScreenBorder != pPrevPosition->iScreenBorder)
1754 	{
1755 		_set_dock_orientation (pDock, pPosition->iScreenBorder);
1756 		cairo_dock_reload_buffers_in_dock (pDock, TRUE, FALSE);  // icons may have a different width and height, so changing the orientation will affect them.  also, stack-icons may be drawn differently according to the orientation (ex.: box).
1757 	}
1758 	pDock->bExtendedMode = pBackground->bExtendedMode;
1759 	pDock->iGapX = pPosition->iGapX;
1760 	pDock->iGapY = pPosition->iGapY;
1761 	pDock->fAlign = pPosition->fAlign;
1762 
1763 	if (pPosition->iNumScreen != pPrevPosition->iNumScreen
1764 	|| pPosition->iScreenBorder != pPrevPosition->iScreenBorder  // if the orientation or the screen has changed, the available size may have changed too
1765 	|| pPosition->iGapX != pPrevPosition->iGapX
1766 	|| pPosition->iGapY != pPrevPosition->iGapY)
1767 	{
1768 		cairo_dock_update_dock_size (pDock);
1769 		cairo_dock_move_resize_dock (pDock);
1770 		if (bWasHorizontal != pDock->container.bIsHorizontal)
1771 			pDock->container.iWidth --;  // la taille dans le referentiel du dock ne change pas meme si on change d'horizontalite, par contre la taille de la fenetre change. On introduit donc un biais ici pour forcer le configure-event a faire son travail, sinon ca fausse le redraw.
1772 	}
1773 	else if (pPosition->fAlign != pPrevPosition->fAlign  // need to update the input zone
1774 	|| pPrevBackground->iDockLineWidth != pBackground->iDockLineWidth  // frame size has changed
1775 	|| pPrevBackground->iFrameMargin != pBackground->iFrameMargin)  // idem
1776 	{
1777 		cairo_dock_update_dock_size (pDock);
1778 	}
1779 
1780 	///cairo_dock_calculate_dock_icons (pDock);
1781 
1782 	gldi_docks_redraw_all_root ();  // the background is a global parameter
1783 
1784 	// accessibility
1785 	//\_______________ Shortkey.
1786 	if (pAccessibility->iVisibility == CAIRO_DOCK_VISI_SHORTKEY)
1787 	{
1788 		if (s_pPopupBinding == NULL)
1789 		{
1790 			s_pPopupBinding = gldi_shortkey_new (myDocksParam.cRaiseDockShortcut,
1791 				"Cairo-Dock",
1792 				_("Pop up the main dock"),
1793 				GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON,
1794 				g_cCurrentThemePath,
1795 				"Accessibility",
1796 				"raise shortcut",
1797 				(CDBindkeyHandler) _raise_from_shortcut,
1798 				NULL);
1799 		}
1800 		else
1801 		{
1802 			gldi_shortkey_rebind (s_pPopupBinding, myDocksParam.cRaiseDockShortcut, NULL);
1803 		}
1804 	}
1805 	else
1806 	{
1807 		gldi_object_unref (GLDI_OBJECT(s_pPopupBinding));
1808 		s_pPopupBinding = NULL;
1809 	}
1810 
1811 	//\_______________ Hiding effect.
1812 	if (g_strcmp0 (pAccessibility->cHideEffect, pPrevAccessibility->cHideEffect) != 0)
1813 	{
1814 		g_pHidingBackend = cairo_dock_get_hiding_effect (pAccessibility->cHideEffect);
1815 		if (g_pHidingBackend && g_pHidingBackend->init)
1816 		{
1817 			gldi_docks_foreach_root ((GFunc)_init_hiding, NULL);  // si le dock est en cours d'animation, comme le backend est nouveau, il n'a donc pas ete initialise au debut de l'animation => on le fait ici.
1818 		}
1819 	}
1820 
1821 	//\_______________ Callback zone.
1822 	if (g_strcmp0 (pAccessibility->cZoneImage, pPrevAccessibility->cZoneImage) != 0
1823 	|| pAccessibility->iZoneWidth != pPrevAccessibility->iZoneWidth
1824 	|| pAccessibility->iZoneHeight != pPrevAccessibility->iZoneHeight
1825 	|| pAccessibility->fZoneAlpha != pPrevAccessibility->fZoneAlpha)
1826 	{
1827 		_load_visible_zone (pAccessibility->cZoneImage, pAccessibility->iZoneWidth, pAccessibility->iZoneHeight, pAccessibility->fZoneAlpha);
1828 
1829 		gldi_docks_redraw_all_root ();
1830 	}
1831 
1832 	gldi_dock_set_visibility (pDock, pAccessibility->iVisibility);
1833 }
1834 
1835 
1836   //////////////
1837  /// UNLOAD ///
1838 //////////////
1839 
unload(void)1840 static void unload (void)
1841 {
1842 	cairo_dock_unload_image_buffer (&g_pVisibleZoneBuffer);
1843 
1844 	_stop_polling_screen_edge_now ();
1845 	s_bQuickHide = FALSE;
1846 
1847 	gldi_object_unref (GLDI_OBJECT(s_pPopupBinding));
1848 	s_pPopupBinding = NULL;
1849 }
1850 
1851 
1852   ////////////
1853  /// INIT ///
1854 ////////////
1855 
on_style_changed(G_GNUC_UNUSED gpointer data)1856 static gboolean on_style_changed (G_GNUC_UNUSED gpointer data)
1857 {
1858 	cd_debug ("Docks: style change to %d", myDocksParam.bUseDefaultColors);
1859 	if (myDocksParam.bUseDefaultColors)  // reload bg
1860 	{
1861 		cd_debug (" reload dock's bg...");
1862 
1863 		gboolean bNeedUpdateSize = (myDocksParam.iDockLineWidth != myStyleParam.iLineWidth);  // frame size changed
1864 		myDocksParam.iDockRadius = myStyleParam.iCornerRadius;
1865 		myDocksParam.iDockLineWidth = myStyleParam.iLineWidth;
1866 
1867 		if (bNeedUpdateSize)  // update docks size and background
1868 			gldi_docks_foreach_root ((GFunc)cairo_dock_update_dock_size, NULL);
1869 		else  // update docks background for color change
1870 			gldi_docks_foreach_root ((GFunc)_reload_bg, NULL);
1871 	}
1872 	return GLDI_NOTIFICATION_LET_PASS;
1873 }
1874 
init(void)1875 static void init (void)
1876 {
1877 	s_hDocksTable = g_hash_table_new_full (g_str_hash,
1878 		g_str_equal,
1879 		NULL,  // name of the dock (points directly to the dock)
1880 		NULL);  // dock
1881 
1882 	/**gldi_object_register_notification (&myDockObjectMgr,
1883 		NOTIFICATION_RENDER,
1884 		(GldiNotificationFunc) _render_dock_notification,
1885 		GLDI_RUN_FIRST, NULL);*/
1886 	gldi_object_register_notification (&myDockObjectMgr,
1887 		NOTIFICATION_LEAVE_DOCK,
1888 		(GldiNotificationFunc) _on_leave_dock,  // is a notification so that others can prevent a dock from hiding (ex Slide view)
1889 		GLDI_RUN_FIRST, NULL);
1890 	gldi_object_register_notification (&myDockObjectMgr,
1891 		NOTIFICATION_INSERT_ICON,
1892 		(GldiNotificationFunc) on_insert_remove_icon,
1893 		GLDI_RUN_AFTER, NULL);
1894 	gldi_object_register_notification (&myDockObjectMgr,
1895 		NOTIFICATION_REMOVE_ICON,
1896 		(GldiNotificationFunc) on_insert_remove_icon,
1897 		GLDI_RUN_AFTER, NULL);
1898 	gldi_object_register_notification (&myIconObjectMgr,
1899 		NOTIFICATION_UPDATE_ICON,
1900 		(GldiNotificationFunc) on_update_inserting_removing_icon,
1901 		GLDI_RUN_AFTER, NULL);
1902 	gldi_object_register_notification (&myIconObjectMgr,
1903 		NOTIFICATION_STOP_ICON,
1904 		(GldiNotificationFunc) on_stop_inserting_removing_icon,
1905 		GLDI_RUN_AFTER, NULL);
1906 	gldi_object_register_notification (&myDesktopMgr,
1907 		NOTIFICATION_DESKTOP_GEOMETRY_CHANGED,
1908 		(GldiNotificationFunc) _on_screen_geometry_changed,
1909 		GLDI_RUN_FIRST, NULL);
1910 	gldi_object_register_notification (&myDialogObjectMgr,
1911 		NOTIFICATION_NEW,
1912 		(GldiNotificationFunc) _on_new_dialog,
1913 		GLDI_RUN_AFTER, NULL);
1914 	gldi_object_register_notification (&myStyleMgr,
1915 		NOTIFICATION_STYLE_CHANGED,
1916 		(GldiNotificationFunc) on_style_changed,
1917 		GLDI_RUN_AFTER, NULL);
1918 
1919 	gldi_docks_visibility_start ();
1920 }
1921 
1922 
1923   ///////////////
1924  /// MANAGER ///
1925 ///////////////
1926 
init_object(GldiObject * obj,gpointer attr)1927 static void init_object (GldiObject *obj, gpointer attr)
1928 {
1929 	CairoDock *pDock = (CairoDock*)obj;
1930 	CairoDockAttr *dattr = (CairoDockAttr*)attr;
1931 
1932 	// check everything is ok
1933 	g_return_if_fail (dattr != NULL && dattr->cDockName != NULL);
1934 
1935 	if (g_hash_table_lookup (s_hDocksTable, dattr->cDockName) != NULL)
1936 	{
1937 		cd_warning ("a dock with the name '%s' is already registered", dattr->cDockName);
1938 		return;
1939 	}
1940 
1941 	//\__________________ init internals
1942 	gldi_dock_init_internals (pDock);
1943 	if (s_bKeepAbove)
1944 		gtk_window_set_keep_above (GTK_WINDOW (pDock->container.pWidget), s_bKeepAbove);
1945 
1946 	//\__________________ initialize its parameters (it's a root dock by default)
1947 	pDock->cDockName = g_strdup (dattr->cDockName);
1948 	pDock->iAvoidingMouseIconType = -1;
1949 	pDock->fFlatDockWidth = - myIconsParam.iIconGap;
1950 	pDock->fMagnitudeMax = 1.;
1951 	pDock->fPostHideOffset = 1.;
1952 	pDock->iInputState = CAIRO_DOCK_INPUT_AT_REST;  // le dock est cree au repos. La zone d'input sera mis en place lors du configure.
1953 	pDock->iIconSize = myIconsParam.iIconWidth;  // by default
1954 
1955 	gldi_object_register_notification (pDock,
1956 		NOTIFICATION_RENDER,
1957 		(GldiNotificationFunc) _render_dock_notification,
1958 		GLDI_RUN_FIRST, NULL);  /// we connect here, to pass before the manager... try to avoid this hack...
1959 
1960 	//\__________________ register the dock
1961 	if (g_hash_table_size (s_hDocksTable) == 0)  // c'est le 1er.
1962 	{
1963 		pDock->bIsMainDock = TRUE;
1964 		g_pMainDock = pDock;
1965 	}
1966 	g_hash_table_insert (s_hDocksTable, pDock->cDockName, pDock);
1967 
1968 	//\__________________ set the icons.
1969 	GList *pIconList = dattr->pIconList;
1970 
1971 	gldi_automatic_separators_add_in_list (pIconList);
1972 
1973 	pDock->icons = pIconList;  // set icons now, before we set the ratio and the renderer.
1974 	Icon *icon;
1975 	GList *ic;
1976 	for (ic = pIconList; ic != NULL; ic = ic->next)
1977 	{
1978 		icon = ic->data;
1979 		if (icon->cParentDockName == NULL)
1980 			icon->cParentDockName = g_strdup (pDock->cDockName);
1981 		cairo_dock_set_icon_container (icon, pDock);
1982 	}
1983 
1984 	//\__________________
1985 	if (! dattr->bSubDock)
1986 	{
1987 		gtk_window_set_title (GTK_WINDOW (pDock->container.pWidget), "cairo-dock");
1988 
1989 		//\__________________ register it as a main dock
1990 		s_pRootDockList = g_list_prepend (s_pRootDockList, pDock);
1991 
1992 		//\__________________ set additional params from its config file
1993 		_get_root_dock_config (pDock);
1994 	}
1995 	else
1996 	{
1997 		gtk_window_set_title (GTK_WINDOW (pDock->container.pWidget), "cairo-dock-sub");
1998 		pDock->iRefCount = 1;
1999 
2000 		//\__________________ set additional params from its parent dock.
2001 		CairoDock *pParentDock = dattr->pParentDock;
2002 		if (pParentDock == NULL)
2003 			pParentDock = g_pMainDock;
2004 
2005 		pDock->container.bIsHorizontal = pParentDock->container.bIsHorizontal;
2006 		pDock->container.bDirectionUp = pParentDock->container.bDirectionUp;
2007 		pDock->iNumScreen = pParentDock->iNumScreen;
2008 		pDock->iIconSize = pParentDock->iIconSize;
2009 
2010 		pDock->container.fRatio = myBackendsParam.fSubDockSizeRatio;
2011 
2012 		//\__________________ hide the dock
2013 		gtk_widget_hide (pDock->container.pWidget);
2014 	}
2015 
2016 	//\__________________ set a renderer (got from the conf, or the default one).
2017 	if (dattr->cRendererName)
2018 		cairo_dock_set_renderer (pDock, dattr->cRendererName);  /// merge both functions ?...
2019 	else
2020 		cairo_dock_set_default_renderer (pDock);
2021 
2022 	//\__________________ load the icons.
2023 	if (pIconList != NULL)
2024 	{
2025 		cairo_dock_reload_buffers_in_dock (pDock, FALSE, TRUE);  // idle reload; FALSE = not recursively, TRUE = compute icons size
2026 	}
2027 
2028 	cairo_dock_update_dock_size (pDock);
2029 }
2030 
reset_object(GldiObject * obj)2031 static void reset_object (GldiObject *obj)
2032 {
2033 	CairoDock *pDock = (CairoDock*)obj;
2034 
2035 	// stop timers
2036 	if (pDock->iSidUnhideDelayed != 0)
2037 		g_source_remove (pDock->iSidUnhideDelayed);
2038 	if (pDock->iSidHideBack != 0)
2039 		g_source_remove (pDock->iSidHideBack);
2040 	if (pDock->iSidMoveResize != 0)
2041 		g_source_remove (pDock->iSidMoveResize);
2042 	if (pDock->iSidLeaveDemand != 0)
2043 		g_source_remove (pDock->iSidLeaveDemand);
2044 	if (pDock->iSidUpdateWMIcons != 0)
2045 		g_source_remove (pDock->iSidUpdateWMIcons);
2046 	if (pDock->iSidLoadBg != 0)
2047 		g_source_remove (pDock->iSidLoadBg);
2048 	if (pDock->iSidDestroyEmptyDock != 0)
2049 		g_source_remove (pDock->iSidDestroyEmptyDock);
2050 	if (pDock->iSidTestMouseOutside != 0)
2051 		g_source_remove (pDock->iSidTestMouseOutside);
2052 	if (pDock->iSidUpdateDockSize != 0)
2053 		g_source_remove (pDock->iSidUpdateDockSize);
2054 
2055 	// free icons that are still present
2056 	GList *icons = pDock->icons;
2057 	pDock->icons = NULL;  // remove the icons first, to avoid any use of 'icons' in the 'destroy' callbacks.
2058 	GList *ic;
2059 	for (ic = icons; ic != NULL; ic = ic->next)
2060 	{
2061 		Icon *pIcon = ic->data;
2062 		cairo_dock_set_icon_container (pIcon, NULL);  // optimisation, to avoid detaching the icon from the container (it also prevents from auto-destroying the dock when it becomes empty)
2063 		if (pIcon->pSubDock != NULL && s_bResetAll)  // if we're deleting the whole table, we don't want the icon to destroy its sub-dock
2064 			pIcon->pSubDock = NULL;
2065 		gldi_object_unref (GLDI_OBJECT(pIcon));
2066 	}
2067 	///g_list_foreach (icons, (GFunc)gldi_object_unref, NULL);
2068 	g_list_free (icons);
2069 
2070 	// if it's a sub-dock, ensure the main icon looses its sub-dock
2071 	if (pDock->iRefCount > 0)
2072 	{
2073 		Icon *pPointedIcon = cairo_dock_search_icon_pointing_on_dock (pDock, NULL);
2074 		if (pPointedIcon != NULL)
2075 			pPointedIcon->pSubDock = NULL;
2076 	}
2077 
2078 	// unregister it
2079 	if (pDock->cDockName)
2080 	{
2081 		g_hash_table_remove (s_hDocksTable, pDock->cDockName);
2082 		s_pRootDockList = g_list_remove (s_pRootDockList, pDock);
2083 	}
2084 
2085 	// stop the mouse scrutation
2086 	if (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP
2087 	|| pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY
2088 	|| pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE
2089 	|| pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW)
2090 	{
2091 		_stop_polling_screen_edge ();
2092 	}
2093 
2094 	// free data
2095 	if (pDock->pShapeBitmap != NULL)
2096 		cairo_region_destroy (pDock->pShapeBitmap);
2097 
2098 	if (pDock->pHiddenShapeBitmap != NULL)
2099 		cairo_region_destroy (pDock->pHiddenShapeBitmap);
2100 
2101 	if (pDock->pActiveShapeBitmap != NULL)
2102 		cairo_region_destroy (pDock->pActiveShapeBitmap);
2103 
2104 	if (pDock->pRenderer != NULL && pDock->pRenderer->free_data != NULL)
2105 	{
2106 		pDock->pRenderer->free_data (pDock);
2107 	}
2108 
2109 	g_free (pDock->cRendererName);
2110 	g_free (pDock->cBgImagePath);
2111 	cairo_dock_unload_image_buffer (&pDock->backgroundBuffer);
2112 	if (pDock->iFboId != 0)
2113 		glDeleteFramebuffersEXT (1, &pDock->iFboId);
2114 	if (pDock->iRedirectedTexture != 0)
2115 		_cairo_dock_delete_texture (pDock->iRedirectedTexture);
2116 	g_free (pDock->cDockName);
2117 }
2118 
delete_object(GldiObject * obj)2119 static gboolean delete_object (GldiObject *obj)
2120 {
2121 	CairoDock *pDock = (CairoDock*)obj;
2122 	if (pDock->bIsMainDock)  // can't delete the main dock
2123 	{
2124 		return FALSE;
2125 	}
2126 
2127 	// remove the conf file
2128 	_remove_root_dock_config (pDock->cDockName);
2129 
2130 	// delete all the icons
2131 	GList *icons = pDock->icons;
2132 	pDock->icons = NULL;  // remove the icons first, to avoid any use of 'icons' in the 'destroy' callbacks.
2133 	GList *ic;
2134 	for (ic = icons; ic != NULL; ic = ic->next)
2135 	{
2136 		Icon *pIcon = ic->data;
2137 		cairo_dock_set_icon_container (pIcon, NULL);  // optimisation, to avoid detaching the icon from the container.
2138 		gldi_object_delete (GLDI_OBJECT(pIcon));
2139 	}
2140 	///g_list_foreach (icons, (GFunc)gldi_object_delete, NULL);
2141 	g_list_free (icons);
2142 
2143 	return TRUE;
2144 }
2145 
reload_object(GldiObject * obj,gboolean bReloadConf,G_GNUC_UNUSED GKeyFile * pKeyFile)2146 static GKeyFile* reload_object (GldiObject *obj, gboolean bReloadConf, G_GNUC_UNUSED GKeyFile *pKeyFile)
2147 {
2148 	CairoDock *pDock = (CairoDock*)obj;
2149 
2150 	if (bReloadConf)  // maybe we should update the parameters that have the global value ?...
2151 		_get_root_dock_config (pDock);
2152 
2153 	cairo_dock_set_default_renderer (pDock);
2154 
2155 	pDock->backgroundBuffer.iWidth ++;  // pour forcer le chargement du fond.
2156 	cairo_dock_reload_buffers_in_dock (pDock, TRUE, TRUE);
2157 
2158 	_cairo_dock_draw_one_subdock_icon (NULL, pDock, NULL);  // container-icons may be drawn differently according to the orientation (ex.: box). must be done after sub-docks are reloaded.
2159 
2160 	gtk_widget_queue_draw (pDock->container.pWidget);
2161 	return NULL;
2162 }
2163 
gldi_register_docks_manager(void)2164 void gldi_register_docks_manager (void)
2165 {
2166 	// Manager
2167 	memset (&myDocksMgr, 0, sizeof (GldiManager));
2168 	gldi_object_init (GLDI_OBJECT(&myDocksMgr), &myManagerObjectMgr, NULL);
2169 	myDocksMgr.cModuleName   = "Docks";
2170 	// interface
2171 	myDocksMgr.init          = init;
2172 	myDocksMgr.load          = load;
2173 	myDocksMgr.unload        = unload;
2174 	myDocksMgr.reload        = (GldiManagerReloadFunc)reload;
2175 	myDocksMgr.get_config    = (GldiManagerGetConfigFunc)get_config;
2176 	myDocksMgr.reset_config  = (GldiManagerResetConfigFunc)reset_config;
2177 	// Config
2178 	memset (&myDocksParam, 0, sizeof (CairoDocksParam));
2179 	myDocksMgr.pConfig = (GldiManagerConfigPtr)&myDocksParam;
2180 	myDocksMgr.iSizeOfConfig = sizeof (CairoDocksParam);
2181 	// data
2182 	memset (&g_pVisibleZoneBuffer, 0, sizeof (CairoDockImageBuffer));
2183 	myDocksMgr.pData = (GldiManagerDataPtr)NULL;
2184 	myDocksMgr.iSizeOfData = 0;
2185 
2186 	// Object Manager
2187 	memset (&myDockObjectMgr, 0, sizeof (GldiObjectManager));
2188 	myDockObjectMgr.cName         = "Dock";
2189 	myDockObjectMgr.iObjectSize   = sizeof (CairoDock);
2190 	// interface
2191 	myDockObjectMgr.init_object   = init_object;
2192 	myDockObjectMgr.reset_object  = reset_object;
2193 	myDockObjectMgr.delete_object = delete_object;
2194 	myDockObjectMgr.reload_object = reload_object;
2195 	// signals
2196 	gldi_object_install_notifications (&myDockObjectMgr, NB_NOTIFICATIONS_DOCKS);
2197 	// parent object
2198 	gldi_object_set_manager (GLDI_OBJECT (&myDockObjectMgr), &myContainerObjectMgr);
2199 }
2200