2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
25
#include <glib/gstdio.h>
26
#include <cairo-dock.h>
28
#include "applet-struct.h"
29
#include "applet-composite-manager.h"
36
static CDWM *_get_wm_by_name (const gchar *cName)
39
for (i = 0; i < NB_WM; i ++)
41
if (strcmp (cName, myData.pWmList[i].cName) == 0)
42
return &myData.pWmList[i];
46
static CDWM *_get_wm_by_index (CDWMIndex n)
49
return &myData.pWmList[n];
54
static void _set_metacity_composite (gboolean bActive)
58
r = system ("gconftool-2 -s '/apps/metacity/general/compositing_manager' --type bool true");
60
r = system ("gconftool-2 -s '/apps/metacity/general/compositing_manager' --type bool false");
62
static void _set_xfwm_composite (gboolean bActive)
66
r = system ("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'");
68
r = system ("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'false'");
70
static void _set_kwin_composite (gboolean bActive)
74
r = system ("if test \"`qdbus org.kde.kwin /KWin compositingActive`\" = \"false\";then qdbus org.kde.kwin /KWin toggleCompositing; fi"); // not active, so activating
76
r = system ("if test \"`qdbus org.kde.kwin /KWin compositingActive`\" = \"true\"; then qdbus org.kde.kwin /KWin toggleCompositing; fi"); // active, so deactivating
78
static void _define_known_wms (void)
80
myData.pWmList[CD_COMPIZ].cName = "Compiz";
81
myData.pWmList[CD_COMPIZ].cCommand = "compiz --replace";
82
myData.pWmList[CD_COMPIZ].activate_composite = NULL;
83
myData.pWmList[CD_COMPIZ].cConfigTool = "ccsm";
85
myData.pWmList[CD_KWIN].cName = "KWin";
86
myData.pWmList[CD_KWIN].cCommand = "kwin --replace";
87
myData.pWmList[CD_KWIN].activate_composite = _set_kwin_composite;
88
myData.pWmList[CD_KWIN].cConfigTool = NULL; /// TODO: find the config tool...
90
myData.pWmList[CD_XFWM].cName = "Xfwm";
91
myData.pWmList[CD_XFWM].cCommand = "xfwm4 --replace";
92
myData.pWmList[CD_XFWM].activate_composite = _set_xfwm_composite;
93
myData.pWmList[CD_XFWM].cConfigTool = "xfwm4-settings"; // there is also xfwm4-tweaks-settings, wish they merge both ...
95
myData.pWmList[CD_METACITY].cName = "Metacity";
96
myData.pWmList[CD_METACITY].cCommand = "metacity --replace";
97
myData.pWmList[CD_METACITY].activate_composite = _set_metacity_composite;
98
myData.pWmList[CD_METACITY].cConfigTool = "gconf-editor /apps/metacity";
100
myData.pWmList[CD_CUSTOM_WMFB].cName = "Fallback";
101
myData.pWmList[CD_CUSTOM_WMFB].cCommand = NULL;
102
myData.pWmList[CD_CUSTOM_WMFB].activate_composite = NULL;
103
myData.pWmList[CD_CUSTOM_WMFB].bIsAvailable = TRUE;
105
myData.pWmList[CD_CUSTOM_WMC].cName = "Composite";
106
myData.pWmList[CD_CUSTOM_WMC].cCommand = NULL;
107
myData.pWmList[CD_CUSTOM_WMC].activate_composite = NULL;
108
myData.pWmList[CD_CUSTOM_WMC].bIsAvailable = TRUE;
111
static void _check_available_wms (gchar *cWhich)
113
if (cWhich == NULL) // no known WM is present, skip the check.
117
wm = _get_wm_by_index (CD_COMPIZ);
118
wm->bIsAvailable = (strstr (cWhich, "compiz") != NULL);
119
wm = _get_wm_by_index (CD_KWIN);
120
wm->bIsAvailable = (strstr (cWhich, "kwin") != NULL);
121
wm = _get_wm_by_index (CD_XFWM);
122
wm->bIsAvailable = (strstr (cWhich, "xfwm4") != NULL);
123
wm = _get_wm_by_index (CD_METACITY);
124
wm->bIsAvailable = (strstr (cWhich, "metacity") != NULL);
127
static CDWMIndex _check_current_wm (gchar *cPs)
129
if (cPs == NULL) // no known WM is present, skip the check.
132
if (strstr (cPs, "compiz") != NULL)
134
if (strstr (cPs, "kwin") != NULL)
136
if (strstr (cPs, "xfwm4") != NULL)
138
if (strstr (cPs, "metacity") != NULL)
145
////////////////////////
146
/// COMPOSITE SIGNAL ///
147
////////////////////////
149
static void _on_composited_changed (GdkScreen *pScreen, gpointer data)
151
myData.bIsComposited = gdk_screen_is_composited (pScreen);
152
cd_draw_current_state ();
154
static void _start_watching_composite_state (void)
156
// get the current state.
157
GdkScreen *pScreen = gdk_screen_get_default ();
158
myData.bIsComposited = gdk_screen_is_composited (pScreen);
161
cd_draw_current_state ();
163
// listen for future changes.
164
g_signal_connect (G_OBJECT (pScreen), "composited-changed", G_CALLBACK(_on_composited_changed), NULL);
172
static CDWM *_get_prefered_wmc (CDWMIndex iCurrentWm)
174
g_print ("%s (%s, %d)\n", __func__, myConfig.cWmCompositor, iCurrentWm);
176
if (myConfig.cWmCompositor != NULL) // a composite WM is defined.
178
wm = _get_wm_by_name (myConfig.cWmCompositor);
179
if (wm == NULL) // not one of the known WM -> define and take the custom one.
181
wm = _get_wm_by_index (CD_CUSTOM_WMC);
182
g_free ((gchar*)wm->cCommand);
183
wm->cCommand = g_strdup (myConfig.cWmCompositor);
186
else if (wm->bIsAvailable)
190
// no WM defined, or the one defined is not available -> check if a suitable one is running.
191
if (iCurrentWm < NB_WM) // one of the know WM is running
193
if (myData.bIsComposited) // and it provides composite => let's take it!
195
wm = _get_wm_by_index (iCurrentWm);
196
if (wm->bIsAvailable) // just to be sure.
201
// no succes so far, take the most suitable one.
202
int index[NB_COMPOSITE_WM] = {CD_COMPIZ, CD_KWIN, CD_XFWM, CD_METACITY}; // in this order by default.
203
switch (g_iDesktopEnv)
205
case CAIRO_DOCK_GNOME:
206
index[1] = CD_METACITY;
209
case CAIRO_DOCK_XFCE:
218
for (i = 0; i < NB_COMPOSITE_WM; i ++)
220
wm = _get_wm_by_index (index[i]);
221
g_print (" %d) %s, %d\n", index[i], wm->cName, wm->bIsAvailable);
222
if (wm->bIsAvailable)
228
static CDWM *_get_prefered_wmfb (CDWMIndex iCurrentWm)
230
g_print ("%s (%s, %d)\n", __func__, myConfig.cWmFallback, iCurrentWm);
232
if (myConfig.cWmFallback != NULL) // a fallback WM is defined.
234
wm = _get_wm_by_name (myConfig.cWmFallback);
235
if (wm == NULL) // not one of the known WM -> define and take the custom one.
237
wm = _get_wm_by_index (CD_CUSTOM_WMFB);
238
g_free ((gchar*)wm->cCommand);
239
wm->cCommand = g_strdup (myConfig.cWmFallback);
242
else if (wm->bIsAvailable)
246
// no WM defined, or the one defined is not available -> check if a suitable one is running.
247
if (iCurrentWm < NB_WM) // one of the know WM is running
249
if (!myData.bIsComposited) // and it is a fallback => let's take it!
251
wm = _get_wm_by_index (iCurrentWm);
252
g_print ("current wm: %d, %d\n", iCurrentWm, wm->bIsAvailable);
253
if (wm->bIsAvailable) // just to be sure.
258
// no succes so far, take the most suitable one.
259
int index[NB_FALLBACK_WM] = {CD_METACITY, CD_XFWM, CD_KWIN}; // in this order by default.
260
switch (g_iDesktopEnv)
262
case CAIRO_DOCK_GNOME:
263
index[0] = CD_METACITY;
266
case CAIRO_DOCK_XFCE:
268
index[1] = CD_METACITY;
272
index[1] = CD_METACITY;
277
for (i = 0; i < NB_FALLBACK_WM; i ++)
279
wm = _get_wm_by_index (index[i]);
280
g_print (" %s (%d)\n", wm->cName, wm->bIsAvailable);
281
if (wm->bIsAvailable)
287
static inline gchar *_get_running_wm (void)
289
return cairo_dock_launch_command_sync ("pgrep -l \"kwin$|compiz$|xfwm4$|metacity$\""); // -l = write the name of the program (not the command next to the PID in 'ps -ef'. we add a '$' after the names to avoid listing things like compiz-decorator or xfwm4-settings
291
static void _define_prefered_wms (gchar *cPs)
293
// get the compositor and fallback WMs
294
CDWMIndex iCurrentWm = _check_current_wm (cPs);
295
myData.wmc = _get_prefered_wmc (iCurrentWm);
296
myData.wmfb = _get_prefered_wmfb (iCurrentWm);
297
g_print ("***** WM: %s / %s\n", myData.wmc?myData.wmc->cName:NULL, myData.wmfb?myData.wmfb->cName:NULL);
299
void cd_define_prefered_wms (void)
301
gchar *ps = _get_running_wm ();
302
_define_prefered_wms (ps);
310
static void _check_wms (CDSharedMemory *pSharedMemory)
312
pSharedMemory->which = cairo_dock_launch_command_sync ("which compiz kwin xfwm4 metacity");
314
pSharedMemory->ps = _get_running_wm ();
316
static void _update_from_data (CDSharedMemory *pSharedMemory)
318
_check_available_wms (pSharedMemory->which);
320
_define_prefered_wms (pSharedMemory->ps); // we do it once we know the current state.
322
cairo_dock_discard_task (myData.pTask);
326
static void _free_shared_memory (CDSharedMemory *pSharedMemory)
328
g_free (pSharedMemory->which);
329
g_free (pSharedMemory->ps);
330
g_free (pSharedMemory);
332
void cd_init_wms (void)
334
_define_known_wms ();
336
_start_watching_composite_state ();
338
CDSharedMemory *pSharedMemory = g_new0 (CDSharedMemory, 1);
339
myData.pTask = cairo_dock_new_task_full (0, // one-shot
340
(CairoDockGetDataAsyncFunc) _check_wms,
341
(CairoDockUpdateSyncFunc) _update_from_data,
342
(GFreeFunc) _free_shared_memory,
344
cairo_dock_launch_task_delayed (myData.pTask, 3000); // 3s delay, since we don't need these info right away.
348
void cd_stop_wms (void)
351
cairo_dock_discard_task (myData.pTask);
354
GdkScreen *pScreen = gdk_screen_get_default ();
355
g_signal_handlers_disconnect_by_func (G_OBJECT(pScreen), _on_composited_changed, NULL);
359
wm = _get_wm_by_index (CD_CUSTOM_WMC);
360
g_free ((gchar*)wm->cCommand);
361
wm = _get_wm_by_index (CD_CUSTOM_WMFB);
362
g_free ((gchar*)wm->cCommand);
370
void cd_draw_current_state (void)
372
g_print ("%s (%d)\n", __func__, myData.bIsComposited);
373
if (myData.bIsComposited)
374
CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cIconCompositeON, "composite-on.png");
376
CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cIconCompositeOFF, "composite-off.png");
380
/////////////////////
381
/// TOGGLE ON/OFF ///
382
/////////////////////
384
static gboolean _activate_composite_delayed (gpointer data)
388
if (myData.wmc->activate_composite != NULL)
389
myData.wmc->activate_composite (TRUE);
393
if (myData.wmfb->activate_composite != NULL)
394
myData.wmfb->activate_composite (FALSE);
399
static gboolean _wm_is_running (CDWM *wm)
401
const gchar *cCommand = wm->cCommand;
402
gchar *cWhich = g_strdup_printf ("pgrep %s$", cCommand); // see above for the '$' character.
403
gchar *str = strchr (cWhich+6, ' '); // remove any parameter to the command, we just want the program name.
404
if (str) // a space is found.
409
gchar *cResult = cairo_dock_launch_command_sync (cWhich);
410
gboolean bIsRunning = (cResult != NULL && *cResult != '\0');
417
static void cd_turn_composite_on (void)
419
if (myData.wmc == NULL) // no compositor.
421
cairo_dock_show_temporary_dialog_with_icon (D_("No compositor is available."), myIcon, myContainer, 6000, "same icon");
425
// if not already launched, launch it.
426
if (! _wm_is_running (myData.wmc)) // not running
428
cairo_dock_launch_command (myData.wmc->cCommand);
429
g_timeout_add_seconds (2, _activate_composite_delayed, GINT_TO_POINTER (1)); // let the WM start for 2s.
431
else // already running, just toggle composite ON.
433
if (myData.wmc->activate_composite != NULL)
434
myData.wmc->activate_composite (TRUE);
436
cairo_dock_show_temporary_dialog_with_icon (D_("No compositor is available."), myIcon, myContainer, 6000, "same icon");
440
static void cd_turn_composite_off (void)
442
if (myData.wmfb == NULL) // no fallback.
444
cairo_dock_show_temporary_dialog_with_icon (D_("No fallback is available."), myIcon, myContainer, 6000, "same icon");
448
// if not already launched, launch it.
449
if (! _wm_is_running (myData.wmfb)) // not running
451
cairo_dock_launch_command (myData.wmfb->cCommand);
452
g_timeout_add_seconds (2, _activate_composite_delayed, 0); // let the WM start for 2s.
454
else // already running, just toggle composite OFF.
456
if (myData.wmfb->activate_composite != NULL)
457
myData.wmfb->activate_composite (FALSE);
459
cairo_dock_show_temporary_dialog_with_icon (D_("No fallback is available."), myIcon, myContainer, 6000, "same icon");
463
void cd_toggle_composite (void)
465
if (myData.bIsComposited)
466
cd_turn_composite_off ();
468
cd_turn_composite_on ();
476
static const gchar *_get_config_tool (void)
478
if (myData.bIsComposited && myData.wmc)
480
return myData.wmc->cConfigTool;
482
else if (!myData.bIsComposited && myData.wmfb)
484
return myData.wmfb->cConfigTool;
488
void cd_open_wm_config (void)
490
const gchar *cConfigTool = _get_config_tool ();
492
if (cConfigTool != NULL)
494
gchar *cmd = g_strdup_printf ("which %s", cConfigTool);
495
gchar *cResult = cairo_dock_launch_command_sync (cmd);
497
if (cResult == NULL || *cResult != '/')
499
gchar *msg = g_strdup_printf (D_("You need to install '%s'"), cConfigTool);
500
cairo_dock_show_temporary_dialog_with_icon (msg, myIcon, myContainer, 6000, "same icon");
505
cairo_dock_launch_command (cConfigTool);
510
cairo_dock_show_temporary_dialog_with_icon (D_("No configuration tool is available."), myIcon, myContainer, 6000, "same icon");
515
static const gchar *_get_command (void)
517
if (myData.bIsComposited && myData.wmc)
519
return myData.wmc->cCommand;
521
else if (!myData.bIsComposited && myData.wmfb)
523
return myData.wmfb->cCommand;
528
void cd_reload_wm (void)
530
const gchar *cCommand = _get_command ();
531
if (cCommand != NULL)
533
cairo_dock_launch_command (cCommand);