145
117
gboolean g_bForceCairo = FALSE;
146
118
gboolean g_bLocked;
120
static gboolean s_bSucessfulLaunch = FALSE;
148
121
static gchar *s_cLaunchCommand = NULL;
149
122
static gchar *s_cLastVersion = NULL;
150
gboolean g_bEnterHelpOnce = FALSE;
151
static gboolean s_bShowTips = TRUE;
152
static int s_iLastTipGroup = -1;
153
static int s_iLastTipKey = -1;
154
123
static gchar *s_cDefaulBackend = NULL;
155
static gboolean s_bTestComposite = TRUE;
156
124
static gint s_iGuiMode = 0; // 0 = simple mode, 1 = advanced mode
157
125
static gint s_iLastYear = 0;
158
126
static void (*s_activate_composite) (gboolean) = NULL;
160
static void _on_tips_category_changed (GtkComboBox *pWidget, gpointer *data);
162
static void _set_metacity_composite (gboolean bActive)
166
r = system ("gconftool-2 -s '/apps/metacity/general/compositing_manager' --type bool true");
168
r = system ("gconftool-2 -s '/apps/metacity/general/compositing_manager' --type bool false");
171
static void _set_xfwm_composite (gboolean bActive)
175
r = system ("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'");
177
r = system ("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'false'");
180
static void _set_kwin_composite (gboolean bActive)
184
r = system ("[ \"$(qdbus org.kde.kwin /KWin compositingActive)\" == \"false\" ] && qdbus org.kde.kwin /KWin toggleCompositing"); // not active, so activating
186
r = system ("[ \"$(qdbus org.kde.kwin /KWin compositingActive)\" == \"true\" ] && qdbus org.kde.kwin /KWin toggleCompositing"); // active, so deactivating
189
static inline void _cancel_wm_composite (void)
191
s_activate_composite (FALSE);
193
static void _accept_wm_composite (int iClickedButton, GtkWidget *pInteractiveWidget, gpointer data, CairoDialog *pDialog)
195
cd_debug ("%s (%d)", __func__, iClickedButton);
196
if (iClickedButton == 1 || iClickedButton == -2) // clic explicite sur "cancel", ou Echap ou auto-delete.
198
_cancel_wm_composite ();
200
gboolean *bAccepted = data;
201
*bAccepted = TRUE; // l'utilisateur a valide son choix.
203
static void _on_free_wm_dialog (gpointer data)
205
gboolean *bAccepted = data;
206
cd_debug ("%s (%d)", __func__, *bAccepted);
207
if (! *bAccepted) // le dialogue s'est detruit sans que l'utilisateur n'ait valide la question => on annule tout.
209
_cancel_wm_composite ();
214
static void _toggle_remember_choice (GtkCheckButton *pButton, GtkWidget *pDialog)
216
g_object_set_data (G_OBJECT (pDialog), "remember", GINT_TO_POINTER (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pButton))));
218
128
static gboolean _cairo_dock_successful_launch (gpointer data)
130
// successful launch, remove the maintenance mode from the command line.
220
131
if (g_str_has_suffix (s_cLaunchCommand, " -m"))
221
132
s_cLaunchCommand[strlen (s_cLaunchCommand)-3] = '\0'; // on enleve le mode maintenance.
223
//\___________________ On teste le composite maintenant (au demarrage, le composite manager peut ne pas etre lance).
224
if (s_bTestComposite)
226
GdkScreen *pScreen = gdk_screen_get_default ();
227
if (! myContainersParam.bUseFakeTransparency && ! gdk_screen_is_composited (pScreen))
229
cd_warning ("no composite manager found");
230
// find the current WM.
231
gchar *cPsef = cairo_dock_launch_command_sync ("pgrep metacity"); // 'ps' ne marche pas, il faut le lancer dans un script :-/
232
if (cPsef != NULL && *cPsef != '\0')
234
s_activate_composite = _set_metacity_composite;
238
cPsef = cairo_dock_launch_command_sync ("pgrep xfwm");
239
if (cPsef != NULL && *cPsef != '\0')
241
s_activate_composite = _set_xfwm_composite;
245
cPsef = cairo_dock_launch_command_sync ("pgrep kwin");
246
if (cPsef != NULL && *cPsef != '\0')
248
s_activate_composite = _set_kwin_composite;
253
// if the WM can handle the composite, ask the user if he wants to activate it.
254
if (s_activate_composite != NULL) // the WM can activate the composite.
256
Icon *pIcon = cairo_dock_get_dialogless_icon ();
257
GtkWidget *pAskBox = gtk_hbox_new (FALSE, 3);
258
GtkWidget *label = gtk_label_new (_("Don't ask me any more"));
259
cairo_dock_set_dialog_widget_text_color (label);
260
GtkWidget *pCheckBox = gtk_check_button_new ();
261
gtk_box_pack_end (GTK_BOX (pAskBox), pCheckBox, FALSE, FALSE, 0);
262
gtk_box_pack_end (GTK_BOX (pAskBox), label, FALSE, FALSE, 0);
263
g_signal_connect (G_OBJECT (pCheckBox), "toggled", G_CALLBACK(_toggle_remember_choice), pAskBox);
264
int iClickedButton = cairo_dock_show_dialog_and_wait (_("To remove the black rectangle around the dock, you need to activate a composite manager.\nDo you want to activate it now?"), pIcon, CAIRO_CONTAINER (g_pMainDock), 0., NULL, pAskBox);
266
gboolean bRememberChoice = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pCheckBox));
267
gtk_widget_destroy (pAskBox); // le widget survit a un dialogue bloquant.
270
s_bTestComposite = FALSE;
272
if (iClickedButton == 0 || iClickedButton == -1) // ok or Enter.
274
s_activate_composite (TRUE);
275
pIcon = cairo_dock_get_dialogless_icon ();
276
cairo_dock_show_dialog_full (_("Do you want to keep this setting?\nIn 15 seconds, the previous setting will be restored."), pIcon, CAIRO_CONTAINER (g_pMainDock), 15e3, NULL, NULL, (CairoDockActionOnAnswerFunc) _accept_wm_composite, g_new0 (gboolean, 1), (GFreeFunc)_on_free_wm_dialog);
279
else // sinon il a droit a un "message a caractere informatif".
281
cairo_dock_show_general_message (_("To remove the black rectangle around the dock, you will need to activate a composite manager.\nFor instance, this can be done by activating desktop effects, launching Compiz, or activating the composition in Metacity.\nIf your machine can't support composition, Cairo-Dock can emulate it. This option is in the 'System' module of the configuration, at the bottom of the page."), 0);
285
else // a priori peu utile de le retester, surtout que le composite risque de ne pas etre actif tout de suite au demarrage.
287
s_bTestComposite = FALSE;
290
if (! s_bTestComposite)
292
gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
293
cairo_dock_update_conf_file (cConfFilePath,
294
G_TYPE_BOOLEAN, "Launch", "test composite", s_bTestComposite,
296
g_free (cConfFilePath);
133
s_bSucessfulLaunch = TRUE;
135
// new year greetings.
300
136
time_t t = time (NULL);
302
138
localtime_r (&t, &st);
304
if (st.tm_mday <= 15 && st.tm_mon == 0 && s_iLastYear < st.tm_year + 1900) // 2 premieres semaines de janvier.
140
if (!data && st.tm_mday <= 15 && st.tm_mon == 0 && s_iLastYear < st.tm_year + 1900) // first 2 weeks of january + not first launch
306
142
s_iLastYear = st.tm_year + 1900;
307
143
gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
365
201
return FALSE; // TRUE <=> ne pas detruire la fenetre.
368
static void _entered_help_once (CairoDockModuleInstance *pInstance, GKeyFile *pKeyFile)
370
if (!g_bEnterHelpOnce)
372
g_bEnterHelpOnce = TRUE;
373
gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
374
cairo_dock_update_conf_file (cConfFilePath,
375
G_TYPE_BOOLEAN, "Help", "entered once", g_bEnterHelpOnce,
377
g_free (cConfFilePath);
380
static void _register_help_module (void)
382
//\________________ ceci est un vilain hack ...mais je trouvais ca lourd de compiler un truc qui n'a aucun code, et puis comme ca on a l'aide meme sans les plug-ins.
383
CairoDockModule *pHelpModule = g_new0 (CairoDockModule, 1);
384
CairoDockVisitCard *pVisitCard = g_new0 (CairoDockVisitCard, 1);
385
pVisitCard->cModuleName = "Help";
386
pVisitCard->cTitle = _("Help");
387
pVisitCard->iMajorVersionNeeded = 2;
388
pVisitCard->iMinorVersionNeeded = 0;
389
pVisitCard->iMicroVersionNeeded = 0;
390
pVisitCard->cPreviewFilePath = NULL;
391
pVisitCard->cGettextDomain = NULL;
392
pVisitCard->cDockVersionOnCompilation = CAIRO_DOCK_VERSION;
393
pVisitCard->cUserDataDir = "help";
394
pVisitCard->cShareDataDir = CAIRO_DOCK_SHARE_DATA_DIR;
395
pVisitCard->cConfFileName = "help.conf";
396
pVisitCard->cModuleVersion = "0.1.2";
397
pVisitCard->iCategory = CAIRO_DOCK_CATEGORY_BEHAVIOR;
398
pVisitCard->cIconFilePath = CAIRO_DOCK_SHARE_DATA_DIR"/icon-help.svg";
399
pVisitCard->iSizeOfConfig = 0;
400
pVisitCard->iSizeOfData = 0;
401
pVisitCard->cDescription = N_("A useful FAQ which also contains a lot of hints.\nRoll your mouse over a sentence to make helpful popups appear.");
402
pVisitCard->cAuthor = "Fabounet";
404
CairoDockModuleInterface *pInterface = g_new0 (CairoDockModuleInterface, 1);
405
pInterface->load_custom_widget = _entered_help_once;
407
pHelpModule->pVisitCard = pVisitCard;
408
pHelpModule->pInterface = pInterface;
409
cairo_dock_register_module (pHelpModule); // il sera vu par le modules-manager comme un module auto-loaded.
417
gchar **pKeyList; // keys of the current group
419
gint iNumTipGroup; // current group being displayed.
420
gint iNumTipKey; // current key being displayed.
422
GtkWidget *pCategoryCombo;
425
static void _cairo_dock_get_next_tip (CDTipsData *pTips)
427
pTips->iNumTipKey ++; // skip the current expander to go to the current label, which will be skipped in the first iteration.
428
const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
432
pTips->iNumTipKey ++;
433
if (pTips->iNumTipKey >= pTips->iNbKeys) // no more key, go to next group.
435
pTips->iNumTipGroup ++;
436
if (pTips->iNumTipGroup >= pTips->iNbGroups) // no more group, restart from first group.
437
pTips->iNumTipGroup = 0;
438
pTips->iNumTipKey = 0;
440
// since the group has changed, get the keys again.
441
g_strfreev (pTips->pKeyList);
442
cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
443
pTips->pKeyList = g_key_file_get_keys (pTips->pKeyFile, cGroupName, &pTips->iNbKeys, NULL);
445
// and update the category in the comb
446
g_signal_handlers_block_matched (pTips->pCategoryCombo,
451
_on_tips_category_changed,
453
gtk_combo_box_set_active (GTK_COMBO_BOX (pTips->pCategoryCombo), pTips->iNumTipGroup);
454
g_signal_handlers_unblock_matched (pTips->pCategoryCombo,
459
_on_tips_category_changed,
463
// check if the key is an expander widget.
464
const gchar *cKeyName = pTips->pKeyList[pTips->iNumTipKey];
465
gchar *cKeyComment = g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName, NULL);
466
bOk = (cKeyComment && *cKeyComment == CAIRO_DOCK_WIDGET_EXPANDER); // whether it's an expander.
467
g_free (cKeyComment);
471
static void _cairo_dock_get_previous_tip (CDTipsData *pTips)
473
pTips->iNumTipKey --;
475
const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
479
pTips->iNumTipKey --;
480
if (pTips->iNumTipKey < 0) // no more key, go to previous group.
482
pTips->iNumTipGroup --;
483
if (pTips->iNumTipGroup < 0) // no more group, restart from the last group.
484
pTips->iNumTipGroup = pTips->iNbGroups - 1;
486
// since the group has changed, get the keys again.
487
g_strfreev (pTips->pKeyList);
488
cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
489
pTips->pKeyList = g_key_file_get_keys (pTips->pKeyFile, cGroupName, &pTips->iNbKeys, NULL);
491
pTips->iNumTipKey = pTips->iNbKeys - 2;
493
// and update the category in the comb
494
g_signal_handlers_block_matched (pTips->pCategoryCombo,
499
_on_tips_category_changed,
501
gtk_combo_box_set_active (GTK_COMBO_BOX (pTips->pCategoryCombo), pTips->iNumTipGroup);
502
g_signal_handlers_unblock_matched (pTips->pCategoryCombo,
507
_on_tips_category_changed,
511
// check if the key is an expander widget.
512
const gchar *cKeyName = pTips->pKeyList[pTips->iNumTipKey];
513
gchar *cKeyComment = g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName, NULL);
514
bOk = (cKeyComment && *cKeyComment == CAIRO_DOCK_WIDGET_EXPANDER); // whether it's an expander.
518
static gchar *_build_tip_text (CDTipsData *pTips)
520
const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
521
const gchar *cKeyName1 = pTips->pKeyList[pTips->iNumTipKey];
522
const gchar *cKeyName2 = pTips->pKeyList[pTips->iNumTipKey+1];
525
guint iNbElements = 0;
527
const gchar *cHint1 = NULL; // points on the comment.
528
gchar **pAuthorizedValuesList1 = NULL;
529
gchar *cKeyComment1 = g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName1, NULL);
530
const gchar *cText1 = cairo_dock_parse_key_comment (cKeyComment1, &iElementType, &iNbElements, &pAuthorizedValuesList1, &bAligned, &cHint1); // points on the comment.
532
const gchar *cHint2 = NULL;
533
gchar **pAuthorizedValuesList2 = NULL;
534
gchar *cKeyComment2 = g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName2, NULL);
535
const gchar *cText2 = cairo_dock_parse_key_comment (cKeyComment2, &iElementType, &iNbElements, &pAuthorizedValuesList2, &bAligned, &cHint2);
537
gchar *cText = g_strdup_printf ("<b>%s</b>\n\n<i>%s</i>\n\n%s",
538
_("Tips and Tricks"),
539
gettext (pAuthorizedValuesList1?pAuthorizedValuesList1[0]:""),
542
g_strfreev (pAuthorizedValuesList1);
543
g_strfreev (pAuthorizedValuesList2);
544
g_free (cKeyComment1);
545
g_free (cKeyComment2);
548
static void _update_tip_text (CDTipsData *pTips, CairoDialog *pDialog)
550
gchar *cText = _build_tip_text (pTips);
552
myDialogsParam.dialogTextDescription.bUseMarkup = TRUE;
553
cairo_dock_set_dialog_message (pDialog, cText);
554
myDialogsParam.dialogTextDescription.bUseMarkup = FALSE;
558
static void _tips_dialog_action (int iClickedButton, GtkWidget *pInteractiveWidget, CDTipsData *pTips, CairoDialog *pDialog)
560
cd_debug ("%s (%d)", __func__, iClickedButton);
561
if (iClickedButton == 2 || iClickedButton == -1) // click on "next", or Enter.
564
_cairo_dock_get_next_tip (pTips);
566
_update_tip_text (pTips, pDialog);
568
cairo_dock_dialog_reference (pDialog); // keep the dialog alive.
570
else if (iClickedButton == 1) // click on "previous"
572
// show the previous tip
573
_cairo_dock_get_previous_tip (pTips);
575
_update_tip_text (pTips, pDialog);
577
cairo_dock_dialog_reference (pDialog); // keep the dialog alive.
579
else // click on "close" or Escape
582
gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
583
cairo_dock_update_conf_file (cConfFilePath,
584
G_TYPE_BOOLEAN, "Help", "skip tips", pTips->bSkipTips,
585
G_TYPE_INT, "Help", "last tip group", pTips->iNumTipGroup,
586
G_TYPE_INT, "Help", "last tip key", pTips->iNumTipKey,
588
g_free (cConfFilePath);
591
static void _on_free_tips_dialog (CDTipsData *pTips)
593
g_key_file_free (pTips->pKeyFile);
594
g_strfreev (pTips->pGroupList);
595
g_strfreev (pTips->pKeyList);
599
static void _on_tips_on_startup_toggled (GtkCheckButton *pButton, CDTipsData *pTips)
601
pTips->bSkipTips = ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pButton));
603
static void _on_tips_category_changed (GtkComboBox *pWidget, gpointer *data)
605
CDTipsData *pTips = data[0];
606
CairoDialog *pDialog = data[1];
608
int iNumItem = gtk_combo_box_get_active (pWidget);
609
g_return_if_fail (iNumItem < pTips->iNbGroups);
611
pTips->iNumTipGroup = iNumItem;
613
// since the group has changed, get the keys again.
614
g_strfreev (pTips->pKeyList);
615
const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
616
pTips->pKeyList = g_key_file_get_keys (pTips->pKeyFile, cGroupName, &pTips->iNbKeys, NULL);
617
pTips->iNumTipKey = 0;
619
_update_tip_text (pTips, pDialog);
621
void cairo_dock_show_tips (int iLastGroup, int iLastKey)
623
// open the tips file
624
const gchar *cConfFilePath = CAIRO_DOCK_SHARE_DATA_DIR"/help.conf";
625
GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
626
g_return_if_fail (pKeyFile != NULL);
629
gchar **pGroupList = g_key_file_get_groups (pKeyFile, &iNbGroups);
630
iNbGroups -= 2; // skip the last 2 groups (Troubleshooting and Contribute)
631
g_return_if_fail (pGroupList != NULL && iNbGroups > 0);
633
// get the last displayed tip.
634
guint iNumTipGroup, iNumTipKey;
635
if (iLastGroup < 0 || iLastKey < 0) // first time we display a tip.
637
iNumTipGroup = iNumTipKey = 0;
641
iNumTipGroup = iLastGroup;
642
iNumTipKey = iLastKey;
643
if (iNumTipGroup >= iNbGroups) // be sure to stay inside the limits.
645
iNumTipGroup = iNbGroups - 1;
649
const gchar *cGroupName = pGroupList[iNumTipGroup];
652
gchar **pKeyList = g_key_file_get_keys (pKeyFile, cGroupName, &iNbKeys, NULL);
653
g_return_if_fail (pKeyList != NULL && iNbKeys > 0);
654
if (iNumTipKey >= iNbKeys) // be sure to stay inside the limits.
657
CDTipsData *pTips = g_new0 (CDTipsData, 1);
658
pTips->pKeyFile = pKeyFile;
659
pTips->pGroupList = pGroupList;
660
pTips->iNbGroups = iNbGroups;
661
pTips->pKeyList = pKeyList;
662
pTips->iNbKeys = iNbKeys;
663
pTips->iNumTipGroup = iNumTipGroup;
664
pTips->iNumTipKey = iNumTipKey;
666
// update to the next tip.
667
if (iLastGroup >= 0 && iLastKey >= 0) // a previous tip exist => take the next one;
668
_cairo_dock_get_next_tip (pTips);
670
// build a list of the available groups.
671
GtkWidget *pInteractiveWidget = gtk_vbox_new (FALSE, 3);
672
GtkWidget *pComboBox = gtk_combo_box_new_text ();
674
for (i = 0; i < iNbGroups; i ++)
676
gtk_combo_box_append_text (GTK_COMBO_BOX (pComboBox), gettext (pGroupList[i]));
678
gtk_combo_box_set_active (GTK_COMBO_BOX (pComboBox), pTips->iNumTipGroup);
679
pTips->pCategoryCombo = pComboBox;
680
static gpointer data_combo[2];
681
data_combo[0] = pTips; // the 2nd data is the dialog, we'll set it after we make it.
682
g_signal_connect (G_OBJECT (pComboBox), "changed", G_CALLBACK(_on_tips_category_changed), data_combo);
683
GtkWidget *pJumpBox = gtk_hbox_new (FALSE, 3);
684
GtkWidget *label = gtk_label_new (_("Category"));
685
cairo_dock_set_dialog_widget_text_color (label);
686
gtk_box_pack_end (GTK_BOX (pJumpBox), pComboBox, FALSE, FALSE, 0);
687
gtk_box_pack_end (GTK_BOX (pJumpBox), label, FALSE, FALSE, 0);
688
gtk_box_pack_start (GTK_BOX (pInteractiveWidget), pJumpBox, FALSE, FALSE, 0);
690
// build a check-button to display or not on startup.
691
GtkWidget *pAskBox = gtk_hbox_new (FALSE, 3);
692
label = gtk_label_new (_("Show tips on startup"));
693
cairo_dock_set_dialog_widget_text_color (label);
694
GtkWidget *pCheckBox = gtk_check_button_new ();
695
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pCheckBox), TRUE);
696
g_signal_connect (G_OBJECT (pCheckBox), "toggled", G_CALLBACK(_on_tips_on_startup_toggled), pTips);
697
gtk_box_pack_end (GTK_BOX (pAskBox), pCheckBox, FALSE, FALSE, 0);
698
gtk_box_pack_end (GTK_BOX (pAskBox), label, FALSE, FALSE, 0);
699
gtk_box_pack_start (GTK_BOX (pInteractiveWidget), pAskBox, FALSE, FALSE, 0);
702
gchar *cText = _build_tip_text (pTips);
703
CairoDialogAttribute attr;
704
memset (&attr, 0, sizeof (CairoDialogAttribute));
706
attr.cImageFilePath = NULL;
707
attr.pInteractiveWidget = pInteractiveWidget;
708
attr.pActionFunc = (CairoDockActionOnAnswerFunc)_tips_dialog_action;
709
attr.pUserData = pTips;
710
attr.pFreeDataFunc = (GFreeFunc)_on_free_tips_dialog;
711
const gchar *cButtons[] = {"cancel", GTK_STOCK_GO_FORWARD"-rtl", GTK_STOCK_GO_FORWARD"-ltr", NULL};
712
attr.cButtonsImage = cButtons;
714
Icon *pIcon = cairo_dock_get_dialogless_icon ();
715
myDialogsParam.dialogTextDescription.bUseMarkup = TRUE;
716
CairoDialog *pTipsDialog = cairo_dock_build_dialog (&attr, pIcon, CAIRO_CONTAINER (g_pMainDock));
717
myDialogsParam.dialogTextDescription.bUseMarkup = FALSE;
719
data_combo[1] = pTipsDialog;
724
204
static void _cairo_dock_get_global_config (const gchar *cCairoDockDataDir)
726
206
gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", cCairoDockDataDir);