/** * This file is a part of the Cairo-Dock project * * Copyright : (C) see the 'copyright' file. * E-mail : see the 'copyright' file. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "gldi-config.h" #include "cairo-dock-image-buffer.h" #include "cairo-dock-config.h" #include "cairo-dock-icon-factory.h" #include "cairo-dock-icon-facility.h" #include "cairo-dock-separator-manager.h" // gldi_automatic_separators_add_in_list #include "cairo-dock-launcher-manager.h" #include "cairo-dock-applet-manager.h" #include "cairo-dock-stack-icon-manager.h" #include "cairo-dock-class-icon-manager.h" #include "cairo-dock-backends-manager.h" #include "cairo-dock-desktop-manager.h" #include "cairo-dock-log.h" #include "cairo-dock-keyfile-utilities.h" #include "cairo-dock-themes-manager.h" // cairo_dock_add_conf_file #include "cairo-dock-dock-factory.h" #include "cairo-dock-dock-facility.h" #include "cairo-dock-draw.h" #include "cairo-dock-draw-opengl.h" #include "cairo-dock-animations.h" #include "cairo-dock-container.h" #include "cairo-dock-keybinder.h" #include "cairo-dock-indicator-manager.h" // myIndicatorsParam.bUseClassIndic #include "cairo-dock-dialog-manager.h" #include "cairo-dock-style-manager.h" #include "cairo-dock-opengl.h" #include "cairo-dock-dock-visibility.h" #include "cairo-dock-dock-manager.h" // public (manager, config, data) CairoDocksParam myDocksParam; GldiManager myDocksMgr; GldiObjectManager myDockObjectMgr; CairoDockImageBuffer g_pVisibleZoneBuffer; CairoDock *g_pMainDock = NULL; // pointeur sur le dock principal. CairoDockHidingEffect *g_pHidingBackend = NULL; CairoDockHidingEffect *g_pKeepingBelowBackend = NULL; // dependancies extern gchar *g_cConfFile; extern gchar *g_cCurrentThemePath; extern gboolean g_bUseOpenGL; extern CairoDockGLConfig g_openglConfig; // private static GHashTable *s_hDocksTable = NULL; // table des docks existant. static GList *s_pRootDockList = NULL; static guint s_iSidPollScreenEdge = 0; static int s_iNbPolls = 0; static gboolean s_bQuickHide = FALSE; static gboolean s_bKeepAbove = FALSE; static GldiShortkey *s_pPopupBinding = NULL; // option 'pop up on shortkey' static gboolean s_bResetAll = FALSE; #define MOUSE_POLLING_DT 150 // mouse polling delay in ms static gboolean _get_root_dock_config (CairoDock *pDock); static void _start_polling_screen_edge (void); static void _stop_polling_screen_edge (void); static void _synchronize_sub_docks_orientation (CairoDock *pDock, gboolean bUpdateDockSize); static void _set_dock_orientation (CairoDock *pDock, CairoDockPositionType iScreenBorder); static void _remove_root_dock_config (const gchar *cDockName); typedef struct { gboolean bUpToDate; gint x; gint y; gboolean bNoMove; gdouble dx; gdouble dy; } CDMousePolling; ///////////// // MANAGER // ///////////// void cairo_dock_force_docks_above (void) { if (g_pMainDock != NULL) { cd_warning ("this function must be called before any dock is created."); return; } s_bKeepAbove = TRUE; } // UNLOAD // static gboolean _free_one_dock (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data) { g_free (pDock->cDockName); pDock->cDockName = NULL; // to not remove it from the table/list gldi_object_unref (GLDI_OBJECT(pDock)); return TRUE; } void cairo_dock_reset_docks_table (void) { s_bResetAll = TRUE; g_hash_table_foreach_remove (s_hDocksTable, (GHRFunc) _free_one_dock, NULL); g_pMainDock = NULL; g_list_free (s_pRootDockList); s_pRootDockList = NULL; s_bResetAll = FALSE; } static void _make_sub_dock (CairoDock *pDock, CairoDock *pParentDock, const gchar *cRendererName) { //\__________________ set sub-dock flag pDock->iRefCount = 1; gtk_window_set_title (GTK_WINDOW (pDock->container.pWidget), "cairo-dock-sub"); //\__________________ set the orientation relatively to the parent dock pDock->container.bIsHorizontal = pParentDock->container.bIsHorizontal; pDock->container.bDirectionUp = pParentDock->container.bDirectionUp; pDock->iNumScreen = pParentDock->iNumScreen; //\__________________ set a renderer cairo_dock_set_renderer (pDock, cRendererName); //\__________________ update the icons size and the ratio. double fPrevRatio = pDock->container.fRatio; pDock->container.fRatio = MIN (pDock->container.fRatio, myBackendsParam.fSubDockSizeRatio); pDock->iIconSize = pParentDock->iIconSize; Icon *icon; GList *ic; pDock->fFlatDockWidth = - myIconsParam.iIconGap; for (ic = pDock->icons; ic != NULL; ic = ic->next) { icon = ic->data; cairo_dock_icon_set_requested_size (icon, 0, 0); // no request icon->fWidth = icon->fHeight = 0; /// useful ?... cairo_dock_set_icon_size_in_dock (pDock, icon); pDock->fFlatDockWidth += icon->fWidth + myIconsParam.iIconGap; } pDock->iMaxIconHeight *= pDock->container.fRatio / fPrevRatio; //\__________________ remove any input shape if (pDock->pShapeBitmap != NULL) { gldi_shape_destroy (pDock->pShapeBitmap); pDock->pShapeBitmap = NULL; if (pDock->iInputState != CAIRO_DOCK_INPUT_ACTIVE) { cairo_dock_set_input_shape_active (pDock); pDock->iInputState = CAIRO_DOCK_INPUT_ACTIVE; } } //\__________________ hide the dock pDock->bAutoHide = FALSE; gtk_widget_hide (pDock->container.pWidget); } void gldi_dock_make_subdock (CairoDock *pDock, CairoDock *pParentDock, const gchar *cRendererName) { //g_print ("%s (%s)\n", __func__, cRendererName); if (pDock->iRefCount == 0) // il devient un sous-dock. { //\__________________ make it a sub-dock. if (pParentDock == NULL) pParentDock = g_pMainDock; _make_sub_dock (pDock, pParentDock, cRendererName); cairo_dock_update_dock_size (pDock); //\__________________ remove from main-dock land _remove_root_dock_config (pDock->cDockName); // just in case. s_pRootDockList = g_list_remove (s_pRootDockList, pDock); 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). } } static void _find_similar_root_dock (CairoDock *pDock, gpointer *data) { CairoDock *pDock0 = data[0]; if (pDock == pDock0) data[2] = GINT_TO_POINTER (TRUE); if (data[2]) return; if (pDock->container.bIsHorizontal == pDock0->container.bIsHorizontal && pDock->container.bDirectionUp == pDock0->container.bDirectionUp) { int *i = data[1]; *i = *i + 1; } } gchar *gldi_dock_get_readable_name (CairoDock *pDock) { g_return_val_if_fail (pDock != NULL, NULL); gchar *cUserName = NULL; if (pDock->iRefCount == 0) { int i = 0; gpointer data[3] = {pDock, &i, NULL}; GList *d = g_list_last (s_pRootDockList); for (;d != NULL; d = d->prev) // parse the list from the end to get the main dock first (docks are prepended). _find_similar_root_dock (d->data, data); const gchar *cPosition; if (pDock->container.bIsHorizontal) { if (pDock->container.bDirectionUp) cPosition = _("Bottom dock"); else cPosition = _("Top dock"); } else { if (pDock->container.bDirectionUp) cPosition = _("Right dock"); else cPosition = _("Left dock"); } if (i > 0) cUserName = g_strdup_printf ("%s (%d)", cPosition, i+1); else cUserName = g_strdup (cPosition); } return cUserName; } CairoDock *gldi_dock_get (const gchar *cDockName) { if (cDockName == NULL) return NULL; return g_hash_table_lookup (s_hDocksTable, cDockName); } static gboolean _cairo_dock_search_icon_from_subdock (G_GNUC_UNUSED gchar *cDockName, CairoDock *pDock, gpointer *data) { if (pDock == data[0]) return FALSE; Icon **pIconFound = data[1]; CairoDock **pDockFound = data[2]; Icon *icon = cairo_dock_get_icon_with_subdock (pDock->icons, data[0]); if (icon != NULL) { *pIconFound = icon; if (pDockFound != NULL) *pDockFound = pDock; return TRUE; } else return FALSE; } Icon *cairo_dock_search_icon_pointing_on_dock (CairoDock *pDock, CairoDock **pParentDock) // pParentDock peut etre NULL. { 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. return NULL; Icon *pPointingIcon = NULL; gpointer data[3] = {pDock, &pPointingIcon, pParentDock}; g_hash_table_find (s_hDocksTable, (GHRFunc)_cairo_dock_search_icon_from_subdock, data); return pPointingIcon; } gchar *cairo_dock_get_unique_dock_name (const gchar *cPrefix) { const gchar *cNamepattern = (cPrefix != NULL && *cPrefix != '\0' && strcmp (cPrefix, "cairo-dock") != 0 ? cPrefix : "dock"); GString *sNameString = g_string_new (cNamepattern); int i = 2; while (g_hash_table_lookup (s_hDocksTable, sNameString->str) != NULL) { g_string_printf (sNameString, "%s-%d", cNamepattern, i); i ++; } gchar *cUniqueName = sNameString->str; g_string_free (sNameString, FALSE); return cUniqueName; } gboolean cairo_dock_check_unique_subdock_name (Icon *pIcon) { cd_debug ("%s (%s)", __func__, pIcon->cName); gchar *cUniqueName = cairo_dock_get_unique_dock_name (pIcon->cName); if (pIcon->cName == NULL || strcmp (pIcon->cName, cUniqueName) != 0) { g_free (pIcon->cName); pIcon->cName = cUniqueName; cd_debug (" cName <- %s", cUniqueName); return TRUE; } return FALSE; } void gldi_dock_rename (CairoDock *pDock, const gchar *cNewName) { // ensure everything is ok g_return_if_fail (pDock != NULL && cNewName != NULL); g_return_if_fail (g_hash_table_lookup (s_hDocksTable, cNewName) == NULL); // rename in the hash table g_hash_table_remove (s_hDocksTable, pDock->cDockName); g_free (pDock->cDockName); pDock->cDockName = g_strdup (cNewName); g_hash_table_insert (s_hDocksTable, pDock->cDockName, pDock); // rename in each icons GList* ic; Icon *icon; for (ic = pDock->icons; ic != NULL; ic = ic->next) { icon = ic->data; gldi_theme_icon_write_container_name_in_conf_file (icon, cNewName); g_free (icon->cParentDockName); icon->cParentDockName = g_strdup (cNewName); } } void gldi_docks_foreach (GHFunc pFunction, gpointer data) { g_hash_table_foreach (s_hDocksTable, pFunction, data); } void gldi_docks_foreach_root (GFunc pFunction, gpointer data) { g_list_foreach (s_pRootDockList, pFunction, data); } static void _gldi_icons_foreach_in_dock (G_GNUC_UNUSED gchar *cDockName, CairoDock *pDock, gpointer *data) { GldiIconFunc pFunction = data[0]; gpointer pUserData = data[1]; GList *ic = pDock->icons, *next_ic; while (ic != NULL) { next_ic = ic->next; // the function below may remove the current icon pFunction ((Icon*)ic->data, pUserData); ic = next_ic; } } void gldi_icons_foreach_in_docks (GldiIconFunc pFunction, gpointer pUserData) { gpointer data[2] = {pFunction, pUserData}; g_hash_table_foreach (s_hDocksTable, (GHFunc) _gldi_icons_foreach_in_dock, data); } static void _reload_buffer_in_one_dock (/**const gchar *cDockName, */CairoDock *pDock, gpointer data) { cairo_dock_reload_buffers_in_dock (pDock, TRUE, GPOINTER_TO_INT (data)); } static void _cairo_dock_draw_one_subdock_icon (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data) { Icon *icon; GList *ic; for (ic = pDock->icons; ic != NULL; ic = ic->next) { icon = ic->data; if (icon->pSubDock != NULL && (GLDI_OBJECT_IS_STACK_ICON (icon) || CAIRO_DOCK_IS_MULTI_APPLI (icon) || GLDI_OBJECT_IS_APPLET_ICON (icon)) && (icon->iSubdockViewType != 0 || (CAIRO_DOCK_IS_MULTI_APPLI (icon) && !myIndicatorsParam.bUseClassIndic)) /**&& icon->iSidRedrawSubdockContent == 0*/) // icone de sous-dock ou de classe ou d'applets. { cairo_dock_trigger_redraw_subdock_content_on_icon (icon); } } } void cairo_dock_reload_buffers_in_all_docks (gboolean bUpdateIconSize) { 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. // now that all icons in sub-docks are drawn, redraw icons pointing to a sub-dock g_hash_table_foreach (s_hDocksTable, (GHFunc)_cairo_dock_draw_one_subdock_icon, NULL); } static void _cairo_dock_set_one_dock_view_to_default (G_GNUC_UNUSED gchar *cDockName, CairoDock *pDock, gpointer data) { //g_print ("%s (%s)\n", __func__, cDockName); int iDockType = GPOINTER_TO_INT (data); if (iDockType == 0 || (iDockType == 1 && pDock->iRefCount == 0) || (iDockType == 2 && pDock->iRefCount != 0)) { cairo_dock_set_default_renderer (pDock); cairo_dock_update_dock_size (pDock); } } void cairo_dock_set_all_views_to_default (int iDockType) { //g_print ("%s ()\n", __func__); g_hash_table_foreach (s_hDocksTable, (GHFunc) _cairo_dock_set_one_dock_view_to_default, GINT_TO_POINTER (iDockType)); } ////////////////////// // ROOT DOCK CONFIG // ////////////////////// void gldi_rootdock_write_gaps (CairoDock *pDock) { if (pDock->iRefCount > 0) return; cairo_dock_prevent_dock_from_out_of_screen (pDock); if (pDock->bIsMainDock) { cairo_dock_update_conf_file (g_cConfFile, G_TYPE_INT, "Position", "x gap", pDock->iGapX, G_TYPE_INT, "Position", "y gap", pDock->iGapY, G_TYPE_INVALID); } else { const gchar *cDockName = gldi_dock_get_name (pDock); gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, cDockName); if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS)) // shouldn't happen { cairo_dock_add_conf_file (GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_MAIN_DOCK_CONF_FILE, cConfFilePath); } cairo_dock_update_conf_file (cConfFilePath, G_TYPE_INT, "Behavior", "x gap", pDock->iGapX, G_TYPE_INT, "Behavior", "y gap", pDock->iGapY, G_TYPE_INVALID); g_free (cConfFilePath); } } int cairo_dock_convert_icon_size_to_pixels (GldiIconSizeEnum s, double *fMaxScale, double *fReflectSize, int *iIconGap) { int iIconSize; switch (s) { case ICON_DEFAULT: default: iIconSize = myIconsParam.iIconWidth; *fMaxScale = 1 + myIconsParam.fAmplitude; *iIconGap = myIconsParam.iIconGap; *fReflectSize = myIconsParam.fReflectHeightRatio; break; case ICON_TINY: iIconSize = ICON_SIZE_TINY; *fMaxScale = 2; *iIconGap = 4; *fReflectSize = .4; break; case ICON_VERY_SMALL: iIconSize = ICON_SIZE_VERY_SMALL; *fMaxScale = 1.8; *iIconGap = 4; *fReflectSize = .4; break; case ICON_SMALL: iIconSize = ICON_SIZE_SMALL; *fMaxScale = 1.8; *iIconGap = 4; *fReflectSize = .4; break; case ICON_MEDIUM: iIconSize = ICON_SIZE_MEDIUM; *fMaxScale = 1.6; *iIconGap = 3; *fReflectSize = .5; break; case ICON_BIG: iIconSize = ICON_SIZE_BIG; *fMaxScale = 1.5; *iIconGap = 2; *fReflectSize = .6; break; case ICON_HUGE: iIconSize = ICON_SIZE_HUGE; *fMaxScale = 1.3; *iIconGap = 2; *fReflectSize = .6; break; } return iIconSize; } GldiIconSizeEnum cairo_dock_convert_icon_size_to_enum (int iIconSize) { GldiIconSizeEnum s = ICON_DEFAULT; if (iIconSize <= ICON_SIZE_TINY+2) s = ICON_TINY; else if (iIconSize <= ICON_SIZE_VERY_SMALL+2) s = ICON_VERY_SMALL; else if (iIconSize >= ICON_SIZE_HUGE-2) s = ICON_HUGE; else if (iIconSize > ICON_SIZE_MEDIUM) s = ICON_BIG; else { if (myIconsParam.fAmplitude >= 2 || iIconSize <= ICON_SIZE_SMALL) s = ICON_SMALL; else s = ICON_MEDIUM; // moyennes. } return s; } static gboolean _get_root_dock_config (CairoDock *pDock) { g_return_val_if_fail (pDock != NULL, FALSE); if (pDock->iRefCount > 0) return FALSE; 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) { pDock->iGapX = myDocksParam.iGapX; pDock->iGapY = myDocksParam.iGapY; pDock->fAlign = myDocksParam.fAlign; pDock->iNumScreen = myDocksParam.iNumScreen; _set_dock_orientation (pDock, myDocksParam.iScreenBorder); // do it after all position parameters have been set; it sets the sub-docks orientation too. gldi_dock_set_visibility (pDock, myDocksParam.iVisibility); pDock->bGlobalIconSize = TRUE; // default icon size pDock->bGlobalBg = TRUE; // default background // pDock->cRendererName and pDock->iIconSize stay at 0 pDock->bExtendedMode = myDocksParam.bExtendedMode; return TRUE; } //\______________ On verifie la presence du fichier de conf associe. //g_print ("%s (%s)\n", __func__, pDock->cDockName); gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, pDock->cDockName); if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS)) // pas encore de fichier de conf pour ce dock. { pDock->container.bIsHorizontal = g_pMainDock->container.bIsHorizontal; pDock->container.bDirectionUp = g_pMainDock->container.bDirectionUp; pDock->fAlign = g_pMainDock->fAlign; g_free (cConfFilePath); return FALSE; } //\______________ On ouvre le fichier de conf. GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath); if (pKeyFile == NULL) { cd_warning ("wrong conf file (%s) !", cConfFilePath); g_free (cConfFilePath); return FALSE; } //\______________ Position. gboolean bFlushConfFileNeeded = FALSE; pDock->iGapX = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "x gap", &bFlushConfFileNeeded, 0, "Position", NULL); pDock->iGapY = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "y gap", &bFlushConfFileNeeded, 0, "Position", NULL); pDock->fAlign = cairo_dock_get_double_key_value (pKeyFile, "Behavior", "alignment", &bFlushConfFileNeeded, 0.5, "Position", NULL); pDock->iNumScreen = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "num_screen", &bFlushConfFileNeeded, GLDI_DEFAULT_SCREEN, "Position", NULL); CairoDockPositionType iScreenBorder = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "screen border", &bFlushConfFileNeeded, 0, "Position", NULL); _set_dock_orientation (pDock, iScreenBorder); // do it after all position parameters have been set; it sets the sub-docks orientation too. //\______________ Visibility. CairoDockVisibility iVisibility = cairo_dock_get_integer_key_value (pKeyFile, "Behavior", "visibility", &bFlushConfFileNeeded, FALSE, "Position", NULL); gldi_dock_set_visibility (pDock, iVisibility); //\______________ Icons size. int s = cairo_dock_get_integer_key_value (pKeyFile, "Appearance", "icon size", &bFlushConfFileNeeded, ICON_DEFAULT, NULL, NULL); // ICON_DEFAULT <=> same as main dock double fMaxScale, fReflectSize; int iIconGap; pDock->iIconSize = cairo_dock_convert_icon_size_to_pixels (s, &fMaxScale, &fReflectSize, &iIconGap); pDock->bGlobalIconSize = (s == ICON_DEFAULT); //\______________ View. g_free (pDock->cRendererName); pDock->cRendererName = cairo_dock_get_string_key_value (pKeyFile, "Appearance", "main dock view", &bFlushConfFileNeeded, NULL, "Views", NULL); //\______________ Background. int iBgType = cairo_dock_get_integer_key_value (pKeyFile, "Appearance", "fill bg", &bFlushConfFileNeeded, 0, NULL, NULL); pDock->bGlobalBg = (iBgType == 0); if (!pDock->bGlobalBg) { if (iBgType == 1) { gchar *cBgImage = cairo_dock_get_string_key_value (pKeyFile, "Appearance", "background image", &bFlushConfFileNeeded, NULL, NULL, NULL); g_free (pDock->cBgImagePath); if (cBgImage != NULL) { pDock->cBgImagePath = cairo_dock_search_image_s_path (cBgImage); g_free (cBgImage); } else pDock->cBgImagePath = NULL; pDock->bBgImageRepeat = cairo_dock_get_boolean_key_value (pKeyFile, "Appearance", "repeat image", &bFlushConfFileNeeded, FALSE, NULL, NULL); } // on recupere la couleur tout le temps pour avoir un plan B. double couleur[4] = {.7, .7, 1., .7}; cairo_dock_get_double_list_key_value (pKeyFile, "Appearance", "stripes color dark", &bFlushConfFileNeeded, pDock->fBgColorDark, 4, couleur, NULL, NULL); double couleur2[4] = {.7, .9, .7, .4}; cairo_dock_get_double_list_key_value (pKeyFile, "Appearance", "stripes color bright", &bFlushConfFileNeeded, pDock->fBgColorBright, 4, couleur2, NULL, NULL); } pDock->bExtendedMode = cairo_dock_get_boolean_key_value (pKeyFile, "Appearance", "extended", &bFlushConfFileNeeded, FALSE, NULL, NULL); //\______________ On met a jour le fichier de conf. if (! bFlushConfFileNeeded) bFlushConfFileNeeded = cairo_dock_conf_file_needs_update (pKeyFile, GLDI_VERSION); if (bFlushConfFileNeeded) { //g_print ("update %s conf file\n", pDock->cDockName); cairo_dock_upgrade_conf_file (cConfFilePath, pKeyFile, GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_MAIN_DOCK_CONF_FILE); } g_key_file_free (pKeyFile); g_free (cConfFilePath); return TRUE; } static void _remove_root_dock_config (const gchar *cDockName) { if (! cDockName || strcmp (cDockName, "cairo-dock") == 0) return ; gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, cDockName); if (g_file_test (cConfFilePath, G_FILE_TEST_EXISTS)) { cairo_dock_delete_conf_file (cConfFilePath); } g_free (cConfFilePath); } void gldi_dock_add_conf_file_for_name (const gchar *cDockName) { // on cree le fichier de conf a partir du template. cd_debug ("%s (%s)", __func__, cDockName); gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, cDockName); cairo_dock_add_conf_file (GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_MAIN_DOCK_CONF_FILE, cConfFilePath); // on placera le nouveau dock a l'oppose du main dock, meme ecran et meme visibilite. cairo_dock_update_conf_file (cConfFilePath, G_TYPE_INT, "Behavior", "screen border", (g_pMainDock->container.bIsHorizontal ? (g_pMainDock->container.bDirectionUp ? 1 : 0) : (g_pMainDock->container.bDirectionUp ? 3 : 2)), G_TYPE_INT, "Behavior", "visibility", g_pMainDock->iVisibility, G_TYPE_INT, "Behavior", "num_screen", g_pMainDock->iNumScreen, G_TYPE_INVALID); g_free (cConfFilePath); } gchar *gldi_dock_add_conf_file (void) { // on genere un nom unique. 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. // on genere un fichier de conf pour ce nom. gldi_dock_add_conf_file_for_name (cValidDockName); return cValidDockName; } void gldi_docks_redraw_all_root (void) { gldi_docks_foreach_root ((GFunc)cairo_dock_redraw_container, NULL); } static void _reposition_one_root_dock (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, gpointer data) { if (pDock->iRefCount == 0 && ! (data && pDock->bIsMainDock)) { if (!pDock->bIsMainDock) _get_root_dock_config (pDock); // relit toute la conf. cairo_dock_update_dock_size (pDock); // la taille max du dock depend de la taille de l'ecran, donc on recalcule son ratio. cairo_dock_move_resize_dock (pDock); gtk_widget_show (pDock->container.pWidget); gtk_widget_queue_draw (pDock->container.pWidget); _synchronize_sub_docks_orientation (pDock, TRUE); } } static void _reposition_root_docks (gboolean bExceptMainDock) { g_hash_table_foreach (s_hDocksTable, (GHFunc)_reposition_one_root_dock, GINT_TO_POINTER (bExceptMainDock)); } void gldi_subdock_synchronize_orientation (CairoDock *pSubDock, CairoDock *pDock, gboolean bUpdateDockSize) { if (pSubDock->container.bDirectionUp != pDock->container.bDirectionUp) { pSubDock->container.bDirectionUp = pDock->container.bDirectionUp; bUpdateDockSize = TRUE; } if (pSubDock->container.bIsHorizontal != pDock->container.bIsHorizontal) { pSubDock->container.bIsHorizontal = pDock->container.bIsHorizontal; bUpdateDockSize = TRUE; } if (pSubDock->iNumScreen != pDock->iNumScreen) { pSubDock->iNumScreen = pDock->iNumScreen; bUpdateDockSize = TRUE; } if (bUpdateDockSize) { cairo_dock_update_dock_size (pSubDock); } _synchronize_sub_docks_orientation (pSubDock, bUpdateDockSize); } static void _synchronize_sub_docks_orientation (CairoDock *pDock, gboolean bUpdateDockSize) { GList* ic; Icon *icon; for (ic = pDock->icons; ic != NULL; ic = ic->next) { icon = ic->data; if (icon->pSubDock != NULL) { 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). } } } static void _set_dock_orientation (CairoDock *pDock, CairoDockPositionType iScreenBorder) { switch (iScreenBorder) { case CAIRO_DOCK_BOTTOM : pDock->container.bIsHorizontal = CAIRO_DOCK_HORIZONTAL; pDock->container.bDirectionUp = TRUE; break; case CAIRO_DOCK_TOP : pDock->container.bIsHorizontal = CAIRO_DOCK_HORIZONTAL; pDock->container.bDirectionUp = FALSE; break; case CAIRO_DOCK_RIGHT : pDock->container.bIsHorizontal = CAIRO_DOCK_VERTICAL; pDock->container.bDirectionUp = TRUE; break; case CAIRO_DOCK_LEFT : pDock->container.bIsHorizontal = CAIRO_DOCK_VERTICAL; pDock->container.bDirectionUp = FALSE; break; case CAIRO_DOCK_INSIDE_SCREEN : case CAIRO_DOCK_NB_POSITIONS : break; } _synchronize_sub_docks_orientation (pDock, FALSE); } //////////////// // VISIBILITY // //////////////// static void _cairo_dock_quick_hide_one_root_dock (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data) { if (pDock->iRefCount == 0) { pDock->bAutoHide = TRUE; cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pDock)); } } void cairo_dock_quick_hide_all_docks (void) { if (! s_bQuickHide) { s_bQuickHide = TRUE; g_hash_table_foreach (s_hDocksTable, (GHFunc) _cairo_dock_quick_hide_one_root_dock, NULL); _start_polling_screen_edge (); } } static void _cairo_dock_stop_quick_hide_one_root_dock (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data) { if (pDock->iRefCount == 0 && ! pDock->bTemporaryHidden && pDock->bAutoHide && pDock->iVisibility != CAIRO_DOCK_VISI_AUTO_HIDE) { pDock->bAutoHide = FALSE; if (! pDock->container.bInside) // on le fait re-apparaitre. { cairo_dock_start_showing (pDock); // l'input shape sera mise lors du configure. } } } void cairo_dock_stop_quick_hide (void) { if (s_bQuickHide) { s_bQuickHide = FALSE; _stop_polling_screen_edge (); g_hash_table_foreach (s_hDocksTable, (GHFunc) _cairo_dock_stop_quick_hide_one_root_dock, NULL); } } void cairo_dock_allow_entrance (CairoDock *pDock) { pDock->bEntranceDisabled = FALSE; } void cairo_dock_disable_entrance (CairoDock *pDock) { pDock->bEntranceDisabled = TRUE; } gboolean cairo_dock_entrance_is_allowed (CairoDock *pDock) { return (! pDock->bEntranceDisabled); } void cairo_dock_activate_temporary_auto_hide (CairoDock *pDock) { if (pDock->iRefCount == 0 && ! pDock->bTemporaryHidden && pDock->iVisibility != CAIRO_DOCK_VISI_AUTO_HIDE) { pDock->bAutoHide = TRUE; pDock->bTemporaryHidden = TRUE; 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. { cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pDock)); // un cairo_dock_start_hiding ne cacherait pas les sous-docks. } } } void cairo_dock_deactivate_temporary_auto_hide (CairoDock *pDock) { //g_print ("%s ()\n", __func__); if (pDock->iRefCount == 0 && pDock->bTemporaryHidden && ! s_bQuickHide) { pDock->bTemporaryHidden = FALSE; pDock->bAutoHide = FALSE; if (! pDock->container.bInside) // on le fait re-apparaitre. { cairo_dock_start_showing (pDock); } } } static gboolean _cairo_dock_hide_back_dock (CairoDock *pDock) { //g_print ("hide back\n"); if (pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW && ! pDock->container.bInside) cairo_dock_pop_down (pDock); else if (pDock->bAutoHide) cairo_dock_start_hiding (pDock); pDock->iSidHideBack = 0; return FALSE; } static gboolean _cairo_dock_unhide_dock_delayed (CairoDock *pDock) { //g_print ("%s (%d, %d)\n", __func__, pDock->container.bInside, pDock->iInputState); if (pDock->container.bInside && pDock->iInputState != CAIRO_DOCK_INPUT_HIDDEN && !pDock->bIsBelow) // already inside and reachable (caution) => no need to show it again. { pDock->iSidUnhideDelayed = 0; return FALSE; } //g_print ("let's show this dock (%d)\n", pDock->bIsMainDock); if (pDock->bAutoHide) cairo_dock_start_showing (pDock); if (pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW) cairo_dock_pop_up (pDock); if (pDock->iSidHideBack == 0) // on se recachera dans 2s si on n'est pas entre dans le dock entre-temps. pDock->iSidHideBack = g_timeout_add (2000, (GSourceFunc) _cairo_dock_hide_back_dock, (gpointer) pDock); pDock->iSidUnhideDelayed = 0; return FALSE; } static void _cairo_dock_unhide_root_dock_on_mouse_hit (CairoDock *pDock, CDMousePolling *pMouse) { if (! pDock->bAutoHide && pDock->iVisibility != CAIRO_DOCK_VISI_KEEP_BELOW) return; int iScreenWidth = gldi_dock_get_screen_width (pDock); int iScreenHeight = gldi_dock_get_screen_height (pDock); int iScreenX = gldi_dock_get_screen_offset_x (pDock); int iScreenY = gldi_dock_get_screen_offset_y (pDock); //\________________ On recupere la position du pointeur. gint x, y; if (! pMouse->bUpToDate) // pas encore recupere le pointeur. { pMouse->bUpToDate = TRUE; gldi_display_get_pointer (&x, &y); if (x == pMouse->x && y == pMouse->y) // le pointeur n'a pas bouge, on quitte. { pMouse->bNoMove = TRUE; return ; } pMouse->bNoMove = FALSE; pMouse->dx = (x - pMouse->x); pMouse->dy = (y - pMouse->y); double d = sqrt (pMouse->dx * pMouse->dx + pMouse->dy * pMouse->dy); pMouse->dx /= d; pMouse->dy /= d; pMouse->x = x; pMouse->y = y; } else // le pointeur a ete recupere auparavant. { if (pMouse->bNoMove) // position inchangee. return; x = pMouse->x; y = pMouse->y; } if (!pDock->container.bIsHorizontal) { x = pMouse->y; y = pMouse->x; } y -= iScreenY; // relative to the border of the dock's screen. if (pDock->container.bDirectionUp) { y = iScreenHeight - 1 - y; } //\________________ On verifie les conditions. int x1, x2; // coordinates range on the X screen edge. gboolean bShow = FALSE; int Ws = (pDock->container.bIsHorizontal ? gldi_desktop_get_width() : gldi_desktop_get_height()); switch (myDocksParam.iCallbackMethod) { case CAIRO_HIT_SCREEN_BORDER: default: if (y != 0) break; if (x < iScreenX || x > iScreenX + iScreenWidth - 1) // only check the border of the dock's screen. break ; bShow = TRUE; break; case CAIRO_HIT_DOCK_PLACE: if (y != 0) break; x1 = pDock->container.iWindowPositionX + (pDock->container.iWidth - pDock->iActiveWidth) * pDock->fAlign; x2 = x1 + pDock->iActiveWidth; if (x1 < 8) // avoid corners, since this is actually the purpose of this option (corners can be used by the WM to trigger actions). x1 = 8; if (x2 > Ws - 8) x2 = Ws - 8; if (x < x1 || x > x2) break; bShow = TRUE; break; case CAIRO_HIT_SCREEN_CORNER: if (y != 0) break; 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). break ; bShow = TRUE; break; case CAIRO_HIT_ZONE: if (y > myDocksParam.iZoneHeight) break; x1 = pDock->container.iWindowPositionX + (pDock->container.iWidth - myDocksParam.iZoneWidth) * pDock->fAlign; x2 = x1 + myDocksParam.iZoneWidth; if (x < x1 || x > x2) break; bShow = TRUE; break; } if (! bShow) { if (pDock->iSidUnhideDelayed != 0) { g_source_remove (pDock->iSidUnhideDelayed); pDock->iSidUnhideDelayed = 0; } return; } //\________________ On montre ou on programme le montrage du dock. int nx, ny; // normal vector to the screen edge. double cost; // cos (teta), where teta = angle between mouse vector and dock's normal double f = 1.; // delay factor if (pDock->container.bIsHorizontal) { nx = 0; ny = (pDock->container.bDirectionUp ? -1 : 1); } else { ny = 0; nx = (pDock->container.bDirectionUp ? -1 : 1); } cost = nx * pMouse->dx + ny * pMouse->dy; 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. int iDelay = f * myDocksParam.iUnhideDockDelay; //g_print (" dock will be shown in %dms (%.2f, %d)\n", iDelay, f, pDock->bIsMainDock); if (iDelay != 0) // on programme une apparition. { if (pDock->iSidUnhideDelayed == 0) pDock->iSidUnhideDelayed = g_timeout_add (iDelay, (GSourceFunc) _cairo_dock_unhide_dock_delayed, (gpointer) pDock); } else // on montre le dock tout de suite. { _cairo_dock_unhide_dock_delayed (pDock); } } static gboolean _cairo_dock_poll_screen_edge (G_GNUC_UNUSED gpointer data) // thanks to Smidgey for the pop-up patch ! { static CDMousePolling mouse; mouse.bUpToDate = FALSE; // mouse position will be updated by the first hidden dock. g_list_foreach (s_pRootDockList, (GFunc) _cairo_dock_unhide_root_dock_on_mouse_hit, &mouse); return TRUE; } static void _start_polling_screen_edge (void) { s_iNbPolls ++; cd_debug ("%s (%d)", __func__, s_iNbPolls); if (s_iSidPollScreenEdge == 0) s_iSidPollScreenEdge = g_timeout_add (MOUSE_POLLING_DT, (GSourceFunc) _cairo_dock_poll_screen_edge, NULL); } static void _stop_polling_screen_edge_now (void) { if (s_iSidPollScreenEdge != 0) { g_source_remove (s_iSidPollScreenEdge); s_iSidPollScreenEdge = 0; } s_iNbPolls = 0; } static void _stop_polling_screen_edge (void) { cd_debug ("%s (%d)", __func__, s_iNbPolls); s_iNbPolls --; if (s_iNbPolls <= 0) { _stop_polling_screen_edge_now (); // remet tout a 0. } } void gldi_dock_set_visibility (CairoDock *pDock, CairoDockVisibility iVisibility) { //\_______________ jeu de parametres. gboolean bReserveSpace = (iVisibility == CAIRO_DOCK_VISI_RESERVE); gboolean bKeepBelow = (iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW); gboolean bAutoHideOnOverlap = (iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP); gboolean bAutoHideOnAnyOverlap = (iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY); gboolean bAutoHide = (iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE); gboolean bShortKey = (iVisibility == CAIRO_DOCK_VISI_SHORTKEY); gboolean bReserveSpace0 = (pDock->iVisibility == CAIRO_DOCK_VISI_RESERVE); gboolean bKeepBelow0 = (pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW); gboolean bAutoHideOnOverlap0 = (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP); gboolean bAutoHideOnAnyOverlap0 = (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY); gboolean bAutoHide0 = (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE); gboolean bShortKey0 = (pDock->iVisibility == CAIRO_DOCK_VISI_SHORTKEY); pDock->iVisibility = iVisibility; //\_______________ changement dans le Reserve Space. if (bReserveSpace != bReserveSpace0) cairo_dock_reserve_space_for_dock (pDock, bReserveSpace); //\_______________ changement dans le Keep below. if (bKeepBelow != bKeepBelow0) { if (bKeepBelow) cairo_dock_pop_down (pDock); else cairo_dock_pop_up (pDock); } //\_______________ changement dans l'Auto-Hide if (bAutoHideOnOverlap != bAutoHideOnOverlap0 || bAutoHideOnAnyOverlap != bAutoHideOnAnyOverlap0 || bAutoHide != bAutoHide0) { if (bAutoHide) { pDock->bTemporaryHidden = FALSE; pDock->bAutoHide = TRUE; cairo_dock_start_hiding (pDock); } else if (bAutoHideOnAnyOverlap) { pDock->bTemporaryHidden = pDock->bAutoHide; // needed to use the following function gldi_dock_hide_if_any_window_overlap_or_show (pDock); } else { if (! bAutoHideOnOverlap) { pDock->bTemporaryHidden = FALSE; pDock->bAutoHide = FALSE; cairo_dock_start_showing (pDock); } if (bAutoHideOnOverlap) { pDock->bTemporaryHidden = pDock->bAutoHide; // needed to use the following function gldi_dock_hide_show_if_current_window_is_on_our_way (pDock); } } } //\_______________ shortkey if (pDock->bIsMainDock) { if (bShortKey) // option is enabled. { if (s_pPopupBinding && gldi_shortkey_could_grab (s_pPopupBinding)) // a shortkey has been registered and grabbed to show/hide the dock => hide the dock. { gtk_widget_hide (pDock->container.pWidget); } else // bind couldn't be done (no shortkey or couldn't grab it). { // g_print ("bind couldn't be done (no shortkey or couldn't grab it).\n"); pDock->iVisibility = CAIRO_DOCK_VISI_KEEP_ABOVE; } } else if (bShortKey0) // option is now disabled => show the dock. { _reposition_root_docks (FALSE); // FALSE => tous. } } //\_______________ on arrete/demarre la scrutation des bords. gboolean bIsPolling = (bAutoHide0 || bAutoHideOnOverlap0 || bAutoHideOnAnyOverlap0 || bKeepBelow0); gboolean bShouldPoll = (bAutoHide || bAutoHideOnOverlap || bAutoHideOnAnyOverlap || bKeepBelow); if (bIsPolling && ! bShouldPoll) _stop_polling_screen_edge (); else if (!bIsPolling && bShouldPoll) _start_polling_screen_edge (); } ///////////////// /// CALLBACKS /// ///////////////// static gboolean _autohide_after_shortkey (CairoDock *pDock) { if (pDock->iVisibility == CAIRO_DOCK_VISI_SHORTKEY && gldi_container_is_visible (CAIRO_CONTAINER (pDock)) && ! pDock->container.bInside) gtk_widget_hide (pDock->container.pWidget); pDock->iSidHideBack = 0; return FALSE; } static void _show_dock_at_mouse (CairoDock *pDock, G_GNUC_UNUSED gpointer data) { if (pDock->iVisibility != CAIRO_DOCK_VISI_SHORTKEY) return; if (gldi_container_is_visible (CAIRO_CONTAINER (pDock))) // already visible -> hide (toggle) { gtk_widget_hide (pDock->container.pWidget); } else // invisible -> show { // calculate the position where the dock will be shown (under the mouse) gldi_container_update_mouse_position (CAIRO_CONTAINER (pDock)); int W = gldi_dock_get_screen_width (pDock), H = gldi_dock_get_screen_height (pDock); int iScreenOffsetX = gldi_dock_get_screen_offset_x (pDock), iScreenOffsetY = gldi_dock_get_screen_offset_y (pDock); ///pDock->iGapX = pDock->container.iWindowPositionX + iMouseX - g_desktopGeometry.iScreenWidth[pDock->container.bIsHorizontal] * pDock->fAlign; ///pDock->iGapY = (pDock->container.bDirectionUp ? g_desktopGeometry.iScreenHeight[pDock->container.bIsHorizontal] - (pDock->container.iWindowPositionY + iMouseY) : pDock->container.iWindowPositionY + iMouseY); pDock->iGapX = pDock->container.iWindowPositionX + pDock->container.iMouseX - (W - pDock->container.iWidth) * pDock->fAlign - pDock->container.iWidth/2 - iScreenOffsetX; pDock->iGapY = (pDock->container.bDirectionUp ? H - (pDock->container.iWindowPositionY + pDock->container.iMouseY) : pDock->container.iWindowPositionY + pDock->container.iMouseY) - iScreenOffsetY; cd_debug (" => %d;%d", g_pMainDock->iGapX, g_pMainDock->iGapY); int iNewPositionX, iNewPositionY; cairo_dock_get_window_position_at_balance (pDock, pDock->container.iWidth, pDock->container.iHeight, &iNewPositionX, &iNewPositionY); cd_debug (" ==> %d;%d", iNewPositionX, iNewPositionY); if (iNewPositionX < 0) iNewPositionX = 0; else if (iNewPositionX + pDock->container.iWidth > W) iNewPositionX = W - pDock->container.iWidth; if (iNewPositionY < 0) iNewPositionY = 0; else if (iNewPositionY + pDock->container.iHeight > H) iNewPositionY = H - pDock->container.iHeight; // show the dock gtk_window_move (GTK_WINDOW (pDock->container.pWidget), (pDock->container.bIsHorizontal ? iNewPositionX : iNewPositionY), (pDock->container.bIsHorizontal ? iNewPositionY : iNewPositionX)); gtk_widget_show (pDock->container.pWidget); // schedule a hiding in a few seconds if (pDock->iSidHideBack != 0) g_source_remove (pDock->iSidHideBack); pDock->iSidHideBack = g_timeout_add (3000, (GSourceFunc) _autohide_after_shortkey, (gpointer) pDock); } } static void _raise_from_shortcut (G_GNUC_UNUSED const char *cKeyShortcut, G_GNUC_UNUSED gpointer data) { // g_print ("shortkey\n"); gldi_docks_foreach_root ((GFunc)_show_dock_at_mouse, NULL); } static gboolean _on_screen_geometry_changed (G_GNUC_UNUSED gpointer data, gboolean bSizeHasChanged) { if (bSizeHasChanged) _reposition_root_docks (FALSE); // FALSE <=> main dock included return GLDI_NOTIFICATION_LET_PASS; } static gboolean _on_new_dialog (G_GNUC_UNUSED gpointer data, CairoDialog *pDialog) { //\________________ hide sub-dock or label that would overlap it Icon *pIcon = pDialog->pIcon; if (! pIcon) return GLDI_NOTIFICATION_LET_PASS; if (pIcon->pSubDock) // un sous-dock par-dessus le dialogue est tres genant. { cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pIcon->pSubDock)); } GldiContainer *pContainer = cairo_dock_get_icon_container (pIcon); 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. { if (pIcon->iHideLabel == 0) gtk_widget_queue_draw (pContainer->pWidget); pIcon->iHideLabel ++; } return GLDI_NOTIFICATION_LET_PASS; } static gboolean _render_dock_notification (G_GNUC_UNUSED gpointer pUserData, CairoDock *pDock, cairo_t *pCairoContext) { if (pCairoContext) // cairo { if (pDock->fHideOffset != 0 && g_pHidingBackend != NULL && g_pHidingBackend->pre_render) g_pHidingBackend->pre_render (pDock, pDock->fHideOffset, pCairoContext); if (pDock->iFadeCounter != 0 && g_pKeepingBelowBackend != NULL && g_pKeepingBelowBackend->pre_render) g_pKeepingBelowBackend->pre_render (pDock, (double) pDock->iFadeCounter / myBackendsParam.iHideNbSteps, pCairoContext); /// TODO: see if it's ok to not use the optimized rendering any more... /// if not, we can probably get the clip on the cairo context pDock->pRenderer->render (pCairoContext, pDock); if (pDock->fHideOffset != 0 && g_pHidingBackend != NULL && g_pHidingBackend->post_render) g_pHidingBackend->post_render (pDock, pDock->fHideOffset, pCairoContext); if (pDock->iFadeCounter != 0 && g_pKeepingBelowBackend != NULL && g_pKeepingBelowBackend->post_render) g_pKeepingBelowBackend->post_render (pDock, (double) pDock->iFadeCounter / myBackendsParam.iHideNbSteps, pCairoContext); } else // opengl { if (pDock->fHideOffset != 0 && g_pHidingBackend != NULL && g_pHidingBackend->pre_render_opengl) g_pHidingBackend->pre_render_opengl (pDock, pDock->fHideOffset); if (pDock->iFadeCounter != 0 && g_pKeepingBelowBackend != NULL && g_pKeepingBelowBackend->pre_render_opengl) g_pKeepingBelowBackend->pre_render_opengl (pDock, (double) pDock->iFadeCounter / myBackendsParam.iHideNbSteps); pDock->pRenderer->render_opengl (pDock); if (pDock->fHideOffset != 0 && g_pHidingBackend != NULL && g_pHidingBackend->post_render_opengl) g_pHidingBackend->post_render_opengl (pDock, pDock->fHideOffset); if (pDock->iFadeCounter != 0 && g_pKeepingBelowBackend != NULL && g_pKeepingBelowBackend->post_render_opengl) g_pKeepingBelowBackend->post_render_opengl (pDock, (double) pDock->iFadeCounter / myBackendsParam.iHideNbSteps); } return GLDI_NOTIFICATION_LET_PASS; } static gboolean _on_leave_dock (G_GNUC_UNUSED gpointer data, CairoDock *pDock, G_GNUC_UNUSED gboolean *bStartAnimation) { //g_print ("%s (%d, %d)\n", __func__, pDock->iRefCount, pDock->bHasModalWindow); //\_______________ On lance l'animation du dock. if (pDock->iRefCount == 0) { //g_print ("%s (auto-hide:%d)\n", __func__, pDock->bAutoHide); if (pDock->bAutoHide) { ///pDock->fFoldingFactor = (myBackendsParam.bAnimateOnAutoHide ? 0.001 : 0.); cairo_dock_start_hiding (pDock); } } else if (pDock->icons != NULL) { pDock->fFoldingFactor = (myDocksParam.bAnimateSubDock ? 0.001 : 0.); Icon *pIcon = cairo_dock_search_icon_pointing_on_dock (pDock, NULL); //g_print ("'%s' se replie\n", pIcon?pIcon->cName:"none"); gldi_object_notify (pIcon, NOTIFICATION_UNFOLD_SUBDOCK, pIcon); } //g_print ("start shrinking\n"); cairo_dock_start_shrinking (pDock); // on commence a faire diminuer la taille des icones. return GLDI_NOTIFICATION_LET_PASS; } static void _update_removing_inserting_icon_size (Icon *icon) { icon->fInsertRemoveFactor *= .85; if (icon->fInsertRemoveFactor > 0) { if (icon->fInsertRemoveFactor < 0.05) icon->fInsertRemoveFactor = 0.05; } else if (icon->fInsertRemoveFactor < 0) { if (icon->fInsertRemoveFactor > -0.05) icon->fInsertRemoveFactor = -0.05; } } static gboolean on_update_inserting_removing_icon (G_GNUC_UNUSED gpointer pUserData, Icon *pIcon, CairoDock *pDock, gboolean *bContinueAnimation) { if (pIcon->iGlideDirection != 0) { pIcon->fGlideOffset += pIcon->iGlideDirection * .1; if (fabs (pIcon->fGlideOffset) > .99) { pIcon->fGlideOffset = pIcon->iGlideDirection; pIcon->iGlideDirection = 0; } else if (fabs (pIcon->fGlideOffset) < .01) { pIcon->fGlideOffset = 0; pIcon->iGlideDirection = 0; } *bContinueAnimation = TRUE; cairo_dock_redraw_container (CAIRO_CONTAINER (pDock)); } if (pIcon->fInsertRemoveFactor != 0) // the icon is being inserted/removed { _update_removing_inserting_icon_size (pIcon); if (fabs (pIcon->fInsertRemoveFactor) > 0.05) // the animation is not yet finished { cairo_dock_mark_icon_as_inserting_removing (pIcon); *bContinueAnimation = TRUE; } cairo_dock_redraw_container (CAIRO_CONTAINER (pDock)); } return GLDI_NOTIFICATION_LET_PASS; } static gboolean on_insert_remove_icon (G_GNUC_UNUSED gpointer pUserData, Icon *pIcon, G_GNUC_UNUSED CairoDock *pDock) { if (pIcon->fInsertRemoveFactor == 0) // animation not needed. return GLDI_NOTIFICATION_LET_PASS; cairo_dock_mark_icon_as_inserting_removing (pIcon); // On prend en charge le dessin de l'icone pendant sa phase d'insertion/suppression. return GLDI_NOTIFICATION_LET_PASS; } static gboolean on_stop_inserting_removing_icon (G_GNUC_UNUSED gpointer pUserData, Icon *pIcon) { pIcon->fGlideOffset = 0; pIcon->iGlideDirection = 0; return GLDI_NOTIFICATION_LET_PASS; } ////////////////// /// GET CONFIG /// ////////////////// static gboolean get_config (GKeyFile *pKeyFile, CairoDocksParam *pDocksParam) { gboolean bFlushConfFileNeeded = FALSE; CairoDocksParam *pBackground = pDocksParam; CairoDocksParam *pPosition = pDocksParam; CairoDocksParam *pAccessibility = pDocksParam; CairoDocksParam *pSystem = pDocksParam; // frame pBackground->iDockRadius = cairo_dock_get_integer_key_value (pKeyFile, "Background", "corner radius", &bFlushConfFileNeeded, 12, NULL, NULL); pBackground->iDockLineWidth = cairo_dock_get_integer_key_value (pKeyFile, "Background", "line width", &bFlushConfFileNeeded, 2, NULL, NULL); pBackground->iFrameMargin = cairo_dock_get_integer_key_value (pKeyFile, "Background", "frame margin", &bFlushConfFileNeeded, 2, NULL, NULL); double couleur[4] = {0., 0., 0.6, 0.4}; cairo_dock_get_double_list_key_value (pKeyFile, "Background", "line color", &bFlushConfFileNeeded, pBackground->fLineColor, 4, couleur, NULL, NULL); pBackground->bRoundedBottomCorner = cairo_dock_get_boolean_key_value (pKeyFile, "Background", "rounded bottom corner", &bFlushConfFileNeeded, TRUE, NULL, NULL); // background image 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. if (iStyle == -1) // old params < 3.4 { iStyle = g_key_file_get_integer (pKeyFile, "Background", "fill bg", NULL); iStyle ++; g_key_file_set_integer (pKeyFile, "Background", "style", iStyle); } if (iStyle == 0) { pBackground->bUseDefaultColors = TRUE; pBackground->iDockRadius = myStyleParam.iCornerRadius; pBackground->iDockLineWidth = myStyleParam.iLineWidth; } else if (iStyle == 1) { gchar *cBgImage = (iStyle == 1 ? cairo_dock_get_string_key_value (pKeyFile, "Background", "background image", &bFlushConfFileNeeded, NULL, NULL, NULL) : NULL); if (cBgImage != NULL) { pBackground->cBackgroundImageFile = cairo_dock_search_image_s_path (cBgImage); g_free (cBgImage); pBackground->fBackgroundImageAlpha = cairo_dock_get_double_key_value (pKeyFile, "Background", "image alpha", &bFlushConfFileNeeded, 0.5, NULL, NULL); pBackground->bBackgroundImageRepeat = cairo_dock_get_boolean_key_value (pKeyFile, "Background", "repeat image", &bFlushConfFileNeeded, FALSE, NULL, NULL); } } // background gradation if (iStyle != 0 && pBackground->cBackgroundImageFile == NULL) { pBackground->iNbStripes = cairo_dock_get_integer_key_value (pKeyFile, "Background", "number of stripes", &bFlushConfFileNeeded, 10, NULL, NULL); if (pBackground->iNbStripes != 0) { pBackground->fStripesWidth = MAX (.01, MIN (.99, cairo_dock_get_double_key_value (pKeyFile, "Background", "stripes width", &bFlushConfFileNeeded, 0.2, NULL, NULL))) / pBackground->iNbStripes; } double couleur3[4] = {.7, .7, 1., .7}; cairo_dock_get_double_list_key_value (pKeyFile, "Background", "stripes color dark", &bFlushConfFileNeeded, pBackground->fStripesColorDark, 4, couleur3, NULL, NULL); double couleur2[4] = {.7, .9, .7, .4}; cairo_dock_get_double_list_key_value (pKeyFile, "Background", "stripes color bright", &bFlushConfFileNeeded, pBackground->fStripesColorBright, 4, couleur2, NULL, NULL); pBackground->fStripesAngle = cairo_dock_get_double_key_value (pKeyFile, "Background", "stripes angle", &bFlushConfFileNeeded, 90., NULL, NULL); } pAccessibility->bExtendedMode = cairo_dock_get_boolean_key_value (pKeyFile, "Background", "extended", &bFlushConfFileNeeded, FALSE, "Accessibility", NULL); // hidden bg double hcolor[4] = {.8, .8, .8, .5}; cairo_dock_get_double_list_key_value (pKeyFile, "Background", "hidden bg color", &bFlushConfFileNeeded, pBackground->fHiddenBg, 4, hcolor, NULL, NULL); // position pPosition->iGapX = cairo_dock_get_integer_key_value (pKeyFile, "Position", "x gap", &bFlushConfFileNeeded, 0, NULL, NULL); pPosition->iGapY = cairo_dock_get_integer_key_value (pKeyFile, "Position", "y gap", &bFlushConfFileNeeded, 0, NULL, NULL); pPosition->iScreenBorder = cairo_dock_get_integer_key_value (pKeyFile, "Position", "screen border", &bFlushConfFileNeeded, 0, NULL, NULL); if (pPosition->iScreenBorder >= CAIRO_DOCK_NB_POSITIONS) pPosition->iScreenBorder = 0; pPosition->fAlign = cairo_dock_get_double_key_value (pKeyFile, "Position", "alignment", &bFlushConfFileNeeded, 0.5, NULL, NULL); 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. if (g_key_file_has_key (pKeyFile, "Position", "xinerama", NULL)) // "xinerama" and "num screen" old keys { if (g_key_file_get_boolean (pKeyFile," Position", "xinerama", NULL)) // xinerama was used -> set num-screen back { pPosition->iNumScreen = g_key_file_get_integer (pKeyFile, "Position", "num screen", NULL); // "num screen" was the old key g_key_file_set_integer (pKeyFile, "Position", "num_screen", pPosition->iNumScreen); } } //\____________________ Visibilite 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. gchar *cShortkey = cairo_dock_get_string_key_value (pKeyFile, "Accessibility", "raise shortcut", &bFlushConfFileNeeded, NULL, "Position", NULL); pAccessibility->cHideEffect = cairo_dock_get_string_key_value (pKeyFile, "Accessibility", "hide effect", &bFlushConfFileNeeded, NULL, NULL, NULL); if (iVisibility == -1) // option nouvelle 2.1.3 { if (g_key_file_get_boolean (pKeyFile, "Accessibility", "reserve space", NULL)) iVisibility = CAIRO_DOCK_VISI_KEEP_ABOVE; else if (g_key_file_get_boolean (pKeyFile, "Accessibility", "pop-up", NULL)) // on force au nouveau mode. { iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY; pAccessibility->cHideEffect = g_strdup_printf ("Fade out"); // on force a "fade out" pour garder le meme effet. g_key_file_set_string (pKeyFile, "Accessibility", "hide effect", pAccessibility->cHideEffect); } else if (g_key_file_get_boolean (pKeyFile, "Accessibility", "auto-hide", NULL)) iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE; else if (g_key_file_get_boolean (pKeyFile, "Accessibility", "auto quick hide on max", NULL)) iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY; else if (cShortkey) { iVisibility = CAIRO_DOCK_VISI_SHORTKEY; pAccessibility->cRaiseDockShortcut = cShortkey; cShortkey = NULL; } else iVisibility = CAIRO_DOCK_VISI_KEEP_ABOVE; g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility); } else { if (pAccessibility->cHideEffect == NULL) // nouvelle option 2.2.0, cela a change l'ordre du menu. { // avant c'etait : KEEP_ABOVE, RESERVE, KEEP_BELOW, AUTO_HIDE, HIDE_ON_MAXIMIZED, SHORTKEY // mtn c'est : KEEP_ABOVE, RESERVE, KEEP_BELOW, HIDE_ON_OVERLAP, HIDE_ON_OVERLAP_ANY, AUTO_HIDE, VISI_SHORTKEY, if (iVisibility == 2) // on force au nouveau mode. { iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY; pAccessibility->cHideEffect = g_strdup_printf ("Fade out"); // on force a "fade out" pour garder le meme effet. g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility); g_key_file_set_string (pKeyFile, "Accessibility", "hide effect", pAccessibility->cHideEffect); } else if (iVisibility == 3) { iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE; g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility); } else if (iVisibility == 4) { iVisibility = CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY; g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility); } else if (iVisibility == 5) { iVisibility = CAIRO_DOCK_VISI_SHORTKEY; g_key_file_set_integer (pKeyFile, "Accessibility", "visibility", iVisibility); } } if (iVisibility == CAIRO_DOCK_VISI_SHORTKEY) { pAccessibility->cRaiseDockShortcut = cShortkey; cShortkey = NULL; } } pAccessibility->iVisibility = iVisibility; g_free (cShortkey); if (pAccessibility->cHideEffect == NULL) { pAccessibility->cHideEffect = g_strdup_printf ("Move down"); g_key_file_set_string (pKeyFile, "Accessibility", "hide effect", pAccessibility->cHideEffect); } pAccessibility->iCallbackMethod = cairo_dock_get_integer_key_value (pKeyFile, "Accessibility", "callback", &bFlushConfFileNeeded, CAIRO_HIT_DOCK_PLACE, NULL, NULL); if (pAccessibility->iCallbackMethod == CAIRO_HIT_ZONE) { if (! g_key_file_has_key (pKeyFile, "Accessibility", "zone size", NULL)) { pAccessibility->iZoneWidth = 100; pAccessibility->iZoneHeight = 10; int list[2] = {pAccessibility->iZoneWidth, pAccessibility->iZoneHeight}; g_key_file_set_integer_list (pKeyFile, "Accessibility", "zone size", list, 2); } cairo_dock_get_size_key_value_helper (pKeyFile, "Accessibility", "zone ", bFlushConfFileNeeded, pAccessibility->iZoneWidth, pAccessibility->iZoneHeight); if (pAccessibility->iZoneWidth < 20) pAccessibility->iZoneWidth = 20; if (pAccessibility->iZoneHeight < 2) pAccessibility->iZoneHeight = 2; pAccessibility->cZoneImage = cairo_dock_get_string_key_value (pKeyFile, "Accessibility", "callback image", &bFlushConfFileNeeded, 0, "Background", NULL); pAccessibility->fZoneAlpha = 1.; // on laisse l'utilisateur definir la transparence qu'il souhaite directement dans l'image. } //\____________________ Autres parametres. double fSensitivity = cairo_dock_get_double_key_value (pKeyFile, "Accessibility", "edge sensitivity", &bFlushConfFileNeeded, -1, NULL, NULL); // replace "unhide delay" if (fSensitivity < 0) // old param { int iUnhideDockDelay = g_key_file_get_integer (pKeyFile, "Accessibility", "unhide delay", NULL); fSensitivity = iUnhideDockDelay / 1500.; // 0 -> 0 = sensitive, 1500 -> 1 = not sensitive g_key_file_set_double (pKeyFile, "Accessibility", "edge sensitivity", fSensitivity); } pAccessibility->iUnhideDockDelay = fSensitivity * 1000; // so we decreased the old delay by 1.5, since we handle mouse movements better. //\____________________ sous-docks. pAccessibility->iLeaveSubDockDelay = cairo_dock_get_integer_key_value (pKeyFile, "Accessibility", "leaving delay", &bFlushConfFileNeeded, 330, "System", NULL); pAccessibility->iShowSubDockDelay = cairo_dock_get_integer_key_value (pKeyFile, "Accessibility", "show delay", &bFlushConfFileNeeded, 300, "System", NULL); if (!g_key_file_has_key (pKeyFile, "Accessibility", "show_on_click", NULL)) { pAccessibility->bShowSubDockOnClick = cairo_dock_get_boolean_key_value (pKeyFile, "Accessibility", "show on click", &bFlushConfFileNeeded, FALSE, "System", NULL); g_key_file_set_integer (pKeyFile, "Accessibility", "show_on_click", pAccessibility->bShowSubDockOnClick ? 1 : 0); bFlushConfFileNeeded = TRUE; } else pAccessibility->bShowSubDockOnClick = (cairo_dock_get_integer_key_value (pKeyFile, "Accessibility", "show_on_click", &bFlushConfFileNeeded, 0, NULL, NULL) == 1); //\____________________ lock ///pAccessibility->bLockAll = cairo_dock_get_boolean_key_value (pKeyFile, "Accessibility", "lock all", &bFlushConfFileNeeded, FALSE, NULL, NULL); pAccessibility->bLockIcons = pAccessibility->bLockAll || cairo_dock_get_boolean_key_value (pKeyFile, "Accessibility", "lock icons", &bFlushConfFileNeeded, FALSE, NULL, NULL); // system pSystem->bAnimateSubDock = cairo_dock_get_boolean_key_value (pKeyFile, "System", "animate subdocks", &bFlushConfFileNeeded, TRUE, "Sub-Docks", NULL); return bFlushConfFileNeeded; } //////////////////// /// RESET CONFIG /// //////////////////// static void reset_config (CairoDocksParam *pDocksParam) { CairoDocksParam *pBackground = pDocksParam; CairoDocksParam *pAccessibility = pDocksParam; // background g_free (pBackground->cBackgroundImageFile); // accessibility g_free (pAccessibility->cRaiseDockShortcut); g_free (pAccessibility->cHideEffect); g_free (pAccessibility->cZoneImage); } //////////// /// LOAD /// //////////// static void _load_visible_zone (const gchar *cVisibleZoneImageFile, int iVisibleZoneWidth, int iVisibleZoneHeight, double fVisibleZoneAlpha) { cairo_dock_unload_image_buffer (&g_pVisibleZoneBuffer); cairo_dock_load_image_buffer_full (&g_pVisibleZoneBuffer, cVisibleZoneImageFile, iVisibleZoneWidth, iVisibleZoneHeight, CAIRO_DOCK_FILL_SPACE, fVisibleZoneAlpha); } static void load (void) { _load_visible_zone (myDocksParam.cZoneImage, myDocksParam.iZoneWidth, myDocksParam.iZoneHeight, myDocksParam.fZoneAlpha); g_pHidingBackend = cairo_dock_get_hiding_effect (myDocksParam.cHideEffect); if (g_pKeepingBelowBackend == NULL) // pas d'option en config pour ca. g_pKeepingBelowBackend = cairo_dock_get_hiding_effect ("Fade out"); // the first main dock doesn't have a config file, its parameters are the global ones. if (g_pMainDock) { g_pMainDock->iGapX = myDocksParam.iGapX; g_pMainDock->iGapY = myDocksParam.iGapY; g_pMainDock->fAlign = myDocksParam.fAlign; g_pMainDock->iNumScreen = myDocksParam.iNumScreen; g_pMainDock->bExtendedMode = myDocksParam.bExtendedMode; _set_dock_orientation (g_pMainDock, myDocksParam.iScreenBorder); cairo_dock_move_resize_dock (g_pMainDock); g_pMainDock->fFlatDockWidth = - myIconsParam.iIconGap; // car on ne le connaissait pas encore au moment de sa creation. // register a key binding if (myDocksParam.iVisibility == CAIRO_DOCK_VISI_SHORTKEY) // register a key binding { if (s_pPopupBinding == NULL) { s_pPopupBinding = gldi_shortkey_new (myDocksParam.cRaiseDockShortcut, "Cairo-Dock", _("Pop up the main dock"), GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON, g_cConfFile, "Accessibility", "raise shortcut", (CDBindkeyHandler) _raise_from_shortcut, NULL); } else { gldi_shortkey_rebind (s_pPopupBinding, myDocksParam.cRaiseDockShortcut, NULL); } } gldi_dock_set_visibility (g_pMainDock, myDocksParam.iVisibility); } } ////////////// /// RELOAD /// ////////////// static void _reload_bg (CairoDock *pDock, G_GNUC_UNUSED gpointer data) { pDock->backgroundBuffer.iWidth ++; // force the reload cairo_dock_trigger_load_dock_background (pDock); } static void _init_hiding (CairoDock *pDock, G_GNUC_UNUSED gpointer data) { if (pDock->bIsShowing || pDock->bIsHiding) { g_pHidingBackend->init (pDock); } } static void reload (CairoDocksParam *pPrevDocksParam, CairoDocksParam *pDocksParam) { CairoDocksParam *pBackground = pDocksParam; CairoDocksParam *pPosition = pDocksParam; CairoDocksParam *pAccessibility = pDocksParam; // CairoDocksParam *pViews = pDocksParam; // CairoDocksParam *pSystem = pDocksParam; CairoDocksParam *pPrevBackground = pPrevDocksParam; CairoDocksParam *pPrevPosition = pPrevDocksParam; CairoDocksParam *pPrevAccessibility = pPrevDocksParam; // CairoDocksParam *pPrevViews = pPrevDocksParam; // CairoDocksParam *pPrevSystem = pPrevDocksParam; CairoDock *pDock = g_pMainDock; // background gldi_docks_foreach_root ((GFunc)_reload_bg, NULL); // position pDock->iNumScreen = pPosition->iNumScreen; if (pPosition->iNumScreen != pPrevPosition->iNumScreen) { _reposition_root_docks (TRUE); // on replace tous les docks racines sauf le main dock, puisque c'est fait apres. } CairoDockTypeHorizontality bWasHorizontal = pDock->container.bIsHorizontal; if (pPosition->iScreenBorder != pPrevPosition->iScreenBorder) { _set_dock_orientation (pDock, pPosition->iScreenBorder); 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). } pDock->bExtendedMode = pBackground->bExtendedMode; pDock->iGapX = pPosition->iGapX; pDock->iGapY = pPosition->iGapY; pDock->fAlign = pPosition->fAlign; if (pPosition->iNumScreen != pPrevPosition->iNumScreen || pPosition->iScreenBorder != pPrevPosition->iScreenBorder // if the orientation or the screen has changed, the available size may have changed too || pPosition->iGapX != pPrevPosition->iGapX || pPosition->iGapY != pPrevPosition->iGapY) { cairo_dock_update_dock_size (pDock); cairo_dock_move_resize_dock (pDock); if (bWasHorizontal != pDock->container.bIsHorizontal) 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. } else if (pPosition->fAlign != pPrevPosition->fAlign // need to update the input zone || pPrevBackground->iDockLineWidth != pBackground->iDockLineWidth // frame size has changed || pPrevBackground->iFrameMargin != pBackground->iFrameMargin) // idem { cairo_dock_update_dock_size (pDock); } ///cairo_dock_calculate_dock_icons (pDock); gldi_docks_redraw_all_root (); // the background is a global parameter // accessibility //\_______________ Shortkey. if (pAccessibility->iVisibility == CAIRO_DOCK_VISI_SHORTKEY) { if (s_pPopupBinding == NULL) { s_pPopupBinding = gldi_shortkey_new (myDocksParam.cRaiseDockShortcut, "Cairo-Dock", _("Pop up the main dock"), GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON, g_cCurrentThemePath, "Accessibility", "raise shortcut", (CDBindkeyHandler) _raise_from_shortcut, NULL); } else { gldi_shortkey_rebind (s_pPopupBinding, myDocksParam.cRaiseDockShortcut, NULL); } } else { gldi_object_unref (GLDI_OBJECT(s_pPopupBinding)); s_pPopupBinding = NULL; } //\_______________ Hiding effect. if (g_strcmp0 (pAccessibility->cHideEffect, pPrevAccessibility->cHideEffect) != 0) { g_pHidingBackend = cairo_dock_get_hiding_effect (pAccessibility->cHideEffect); if (g_pHidingBackend && g_pHidingBackend->init) { 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. } } //\_______________ Callback zone. if (g_strcmp0 (pAccessibility->cZoneImage, pPrevAccessibility->cZoneImage) != 0 || pAccessibility->iZoneWidth != pPrevAccessibility->iZoneWidth || pAccessibility->iZoneHeight != pPrevAccessibility->iZoneHeight || pAccessibility->fZoneAlpha != pPrevAccessibility->fZoneAlpha) { _load_visible_zone (pAccessibility->cZoneImage, pAccessibility->iZoneWidth, pAccessibility->iZoneHeight, pAccessibility->fZoneAlpha); gldi_docks_redraw_all_root (); } gldi_dock_set_visibility (pDock, pAccessibility->iVisibility); } ////////////// /// UNLOAD /// ////////////// static void unload (void) { cairo_dock_unload_image_buffer (&g_pVisibleZoneBuffer); _stop_polling_screen_edge_now (); s_bQuickHide = FALSE; gldi_object_unref (GLDI_OBJECT(s_pPopupBinding)); s_pPopupBinding = NULL; } //////////// /// INIT /// //////////// static gboolean on_style_changed (G_GNUC_UNUSED gpointer data) { g_print ("%s (Docks, %d)\n", __func__, myDocksParam.bUseDefaultColors); if (myDocksParam.bUseDefaultColors) // reload bg { g_print (" reload dock's bg...\n"); myDocksParam.iDockRadius = myStyleParam.iCornerRadius; myDocksParam.iDockLineWidth = myStyleParam.iLineWidth; gldi_docks_foreach_root ((GFunc)_reload_bg, NULL); } return GLDI_NOTIFICATION_LET_PASS; } static void init (void) { s_hDocksTable = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, // name of the dock (points directly to the dock) NULL); // dock /**gldi_object_register_notification (&myDockObjectMgr, NOTIFICATION_RENDER, (GldiNotificationFunc) _render_dock_notification, GLDI_RUN_FIRST, NULL);*/ gldi_object_register_notification (&myDockObjectMgr, NOTIFICATION_LEAVE_DOCK, (GldiNotificationFunc) _on_leave_dock, // is a notification so that others can prevent a dock from hiding (ex Slide view) GLDI_RUN_FIRST, NULL); gldi_object_register_notification (&myDockObjectMgr, NOTIFICATION_INSERT_ICON, (GldiNotificationFunc) on_insert_remove_icon, GLDI_RUN_AFTER, NULL); gldi_object_register_notification (&myDockObjectMgr, NOTIFICATION_REMOVE_ICON, (GldiNotificationFunc) on_insert_remove_icon, GLDI_RUN_AFTER, NULL); gldi_object_register_notification (&myIconObjectMgr, NOTIFICATION_UPDATE_ICON, (GldiNotificationFunc) on_update_inserting_removing_icon, GLDI_RUN_AFTER, NULL); gldi_object_register_notification (&myIconObjectMgr, NOTIFICATION_STOP_ICON, (GldiNotificationFunc) on_stop_inserting_removing_icon, GLDI_RUN_AFTER, NULL); gldi_object_register_notification (&myDesktopMgr, NOTIFICATION_DESKTOP_GEOMETRY_CHANGED, (GldiNotificationFunc) _on_screen_geometry_changed, GLDI_RUN_FIRST, NULL); gldi_object_register_notification (&myDialogObjectMgr, NOTIFICATION_NEW, (GldiNotificationFunc) _on_new_dialog, GLDI_RUN_AFTER, NULL); gldi_object_register_notification (&myStyleMgr, NOTIFICATION_STYLE_CHANGED, (GldiNotificationFunc) on_style_changed, GLDI_RUN_AFTER, NULL); gldi_docks_visibility_start (); } /////////////// /// MANAGER /// /////////////// static void init_object (GldiObject *obj, gpointer attr) { CairoDock *pDock = (CairoDock*)obj; CairoDockAttr *dattr = (CairoDockAttr*)attr; // check everything is ok g_return_if_fail (dattr != NULL && dattr->cDockName != NULL); if (g_hash_table_lookup (s_hDocksTable, dattr->cDockName) != NULL) { cd_warning ("a dock with the name '%s' is already registered", dattr->cDockName); return; } //\__________________ init internals gldi_dock_init_internals (pDock); if (s_bKeepAbove) gtk_window_set_keep_above (GTK_WINDOW (pDock->container.pWidget), s_bKeepAbove); //\__________________ initialize its parameters (it's a root dock by default) pDock->cDockName = g_strdup (dattr->cDockName); pDock->iAvoidingMouseIconType = -1; pDock->fFlatDockWidth = - myIconsParam.iIconGap; pDock->fMagnitudeMax = 1.; pDock->fPostHideOffset = 1.; pDock->iInputState = CAIRO_DOCK_INPUT_AT_REST; // le dock est cree au repos. La zone d'input sera mis en place lors du configure. pDock->iIconSize = myIconsParam.iIconWidth; // by default gldi_object_register_notification (pDock, NOTIFICATION_RENDER, (GldiNotificationFunc) _render_dock_notification, GLDI_RUN_FIRST, NULL); /// we connect here, to pass before the manager... try to avoid this hack... //\__________________ register the dock if (g_hash_table_size (s_hDocksTable) == 0) // c'est le 1er. { pDock->bIsMainDock = TRUE; g_pMainDock = pDock; } g_hash_table_insert (s_hDocksTable, pDock->cDockName, pDock); //\__________________ set the icons. GList *pIconList = dattr->pIconList; gldi_automatic_separators_add_in_list (pIconList); pDock->icons = pIconList; // set icons now, before we set the ratio and the renderer. Icon *icon; GList *ic; for (ic = pIconList; ic != NULL; ic = ic->next) { icon = ic->data; if (icon->cParentDockName == NULL) icon->cParentDockName = g_strdup (pDock->cDockName); cairo_dock_set_icon_container (icon, pDock); } //\__________________ if (! dattr->bSubDock) { gtk_window_set_title (GTK_WINDOW (pDock->container.pWidget), "cairo-dock"); //\__________________ register it as a main dock s_pRootDockList = g_list_prepend (s_pRootDockList, pDock); //\__________________ set additional params from its config file _get_root_dock_config (pDock); } else { gtk_window_set_title (GTK_WINDOW (pDock->container.pWidget), "cairo-dock-sub"); pDock->iRefCount = 1; //\__________________ set additional params from its parent dock. CairoDock *pParentDock = dattr->pParentDock; if (pParentDock == NULL) pParentDock = g_pMainDock; pDock->container.bIsHorizontal = pParentDock->container.bIsHorizontal; pDock->container.bDirectionUp = pParentDock->container.bDirectionUp; pDock->iNumScreen = pParentDock->iNumScreen; pDock->iIconSize = pParentDock->iIconSize; pDock->container.fRatio = myBackendsParam.fSubDockSizeRatio; //\__________________ hide the dock gtk_widget_hide (pDock->container.pWidget); } //\__________________ set a renderer (got from the conf, or the default one). if (dattr->cRendererName) cairo_dock_set_renderer (pDock, dattr->cRendererName); /// merge both functions ?... else cairo_dock_set_default_renderer (pDock); //\__________________ load the icons. if (pIconList != NULL) { cairo_dock_reload_buffers_in_dock (pDock, FALSE, TRUE); // idle reload; FALSE = not recursively, TRUE = compute icons size } cairo_dock_update_dock_size (pDock); } static void reset_object (GldiObject *obj) { CairoDock *pDock = (CairoDock*)obj; // stop timers if (pDock->iSidUnhideDelayed != 0) g_source_remove (pDock->iSidUnhideDelayed); if (pDock->iSidHideBack != 0) g_source_remove (pDock->iSidHideBack); if (pDock->iSidMoveResize != 0) g_source_remove (pDock->iSidMoveResize); if (pDock->iSidLeaveDemand != 0) g_source_remove (pDock->iSidLeaveDemand); if (pDock->iSidUpdateWMIcons != 0) g_source_remove (pDock->iSidUpdateWMIcons); if (pDock->iSidLoadBg != 0) g_source_remove (pDock->iSidLoadBg); if (pDock->iSidDestroyEmptyDock != 0) g_source_remove (pDock->iSidDestroyEmptyDock); if (pDock->iSidTestMouseOutside != 0) g_source_remove (pDock->iSidTestMouseOutside); if (pDock->iSidUpdateDockSize != 0) g_source_remove (pDock->iSidUpdateDockSize); // free icons that are still present GList *icons = pDock->icons; pDock->icons = NULL; // remove the icons first, to avoid any use of 'icons' in the 'destroy' callbacks. GList *ic; for (ic = icons; ic != NULL; ic = ic->next) { Icon *pIcon = ic->data; 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) if (pIcon->pSubDock != NULL && s_bResetAll) // if we're deleting the whole table, we don't want the icon to destroy its sub-dock pIcon->pSubDock = NULL; gldi_object_unref (GLDI_OBJECT(pIcon)); } ///g_list_foreach (icons, (GFunc)gldi_object_unref, NULL); g_list_free (icons); // if it's a sub-dock, ensure the main icon looses its sub-dock if (pDock->iRefCount > 0) { Icon *pPointedIcon = cairo_dock_search_icon_pointing_on_dock (pDock, NULL); if (pPointedIcon != NULL) pPointedIcon->pSubDock = NULL; } // unregister it if (pDock->cDockName) { g_hash_table_remove (s_hDocksTable, pDock->cDockName); s_pRootDockList = g_list_remove (s_pRootDockList, pDock); } // stop the mouse scrutation if (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP || pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY || pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE || pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW) { _stop_polling_screen_edge (); } // free data if (pDock->pShapeBitmap != NULL) gldi_shape_destroy (pDock->pShapeBitmap); if (pDock->pHiddenShapeBitmap != NULL) gldi_shape_destroy (pDock->pHiddenShapeBitmap); if (pDock->pActiveShapeBitmap != NULL) gldi_shape_destroy (pDock->pActiveShapeBitmap); if (pDock->pRenderer != NULL && pDock->pRenderer->free_data != NULL) { pDock->pRenderer->free_data (pDock); } g_free (pDock->cRendererName); g_free (pDock->cBgImagePath); cairo_dock_unload_image_buffer (&pDock->backgroundBuffer); if (pDock->iFboId != 0) glDeleteFramebuffersEXT (1, &pDock->iFboId); if (pDock->iRedirectedTexture != 0) _cairo_dock_delete_texture (pDock->iRedirectedTexture); g_free (pDock->cDockName); } static gboolean delete_object (GldiObject *obj) { CairoDock *pDock = (CairoDock*)obj; if (pDock->bIsMainDock) // can't delete the main dock { return FALSE; } // remove the conf file _remove_root_dock_config (pDock->cDockName); // delete all the icons GList *icons = pDock->icons; pDock->icons = NULL; // remove the icons first, to avoid any use of 'icons' in the 'destroy' callbacks. GList *ic; for (ic = icons; ic != NULL; ic = ic->next) { Icon *pIcon = ic->data; cairo_dock_set_icon_container (pIcon, NULL); // optimisation, to avoid detaching the icon from the container. gldi_object_delete (GLDI_OBJECT(pIcon)); } ///g_list_foreach (icons, (GFunc)gldi_object_delete, NULL); g_list_free (icons); return TRUE; } static GKeyFile* reload_object (GldiObject *obj, gboolean bReloadConf, G_GNUC_UNUSED GKeyFile *pKeyFile) { CairoDock *pDock = (CairoDock*)obj; if (bReloadConf) // maybe we should update the parameters that have the global value ?... _get_root_dock_config (pDock); cairo_dock_set_default_renderer (pDock); pDock->backgroundBuffer.iWidth ++; // pour forcer le chargement du fond. cairo_dock_reload_buffers_in_dock (pDock, TRUE, TRUE); _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. gtk_widget_queue_draw (pDock->container.pWidget); return NULL; } void gldi_register_docks_manager (void) { // Manager memset (&myDocksMgr, 0, sizeof (GldiManager)); gldi_object_init (GLDI_OBJECT(&myDocksMgr), &myManagerObjectMgr, NULL); myDocksMgr.cModuleName = "Docks"; // interface myDocksMgr.init = init; myDocksMgr.load = load; myDocksMgr.unload = unload; myDocksMgr.reload = (GldiManagerReloadFunc)reload; myDocksMgr.get_config = (GldiManagerGetConfigFunc)get_config; myDocksMgr.reset_config = (GldiManagerResetConfigFunc)reset_config; // Config memset (&myDocksParam, 0, sizeof (CairoDocksParam)); myDocksMgr.pConfig = (GldiManagerConfigPtr)&myDocksParam; myDocksMgr.iSizeOfConfig = sizeof (CairoDocksParam); // data memset (&g_pVisibleZoneBuffer, 0, sizeof (CairoDockImageBuffer)); myDocksMgr.pData = (GldiManagerDataPtr)NULL; myDocksMgr.iSizeOfData = 0; // Object Manager memset (&myDockObjectMgr, 0, sizeof (GldiObjectManager)); myDockObjectMgr.cName = "Dock"; myDockObjectMgr.iObjectSize = sizeof (CairoDock); // interface myDockObjectMgr.init_object = init_object; myDockObjectMgr.reset_object = reset_object; myDockObjectMgr.delete_object = delete_object; myDockObjectMgr.reload_object = reload_object; // signals gldi_object_install_notifications (&myDockObjectMgr, NB_NOTIFICATIONS_DOCKS); // parent object gldi_object_set_manager (GLDI_OBJECT (&myDockObjectMgr), &myContainerObjectMgr); }