2
* Copyright © 2005 Novell, Inc.
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Novell, Inc. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Novell, Inc. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: David Reveman <davidr@novell.com>
33
#include <glib/gprintf.h>
34
#include <gconf/gconf-client.h>
38
#define APP_NAME "/apps/compiz"
39
#define KEY_CHANGE_TIMEOUT 250
41
struct _GConfModifier {
45
{ "<Shift>", ShiftMask },
46
{ "<Control>", ControlMask },
47
{ "<Mod1>", Mod1Mask },
48
{ "<Mod2>", Mod2Mask },
49
{ "<Mod3>", Mod3Mask },
50
{ "<Mod4>", Mod4Mask },
51
{ "<Mod5>", Mod5Mask },
52
{ "<Alt>", CompAltMask },
53
{ "<Meta>", CompMetaMask },
54
{ "<Super>", CompSuperMask },
55
{ "<Hyper>", CompHyperMask },
56
{ "<ModeSwitch>", CompModeSwitchMask },
57
{ "<Release>", CompReleaseMask }
60
#define N_MODIFIERS (sizeof (modifiers) / sizeof (struct _GConfModifier))
62
static int displayPrivateIndex;
64
typedef struct _GConfDisplay {
65
int screenPrivateIndex;
68
CompTimeoutHandle timeoutHandle;
70
InitPluginForDisplayProc initPluginForDisplay;
71
SetDisplayOptionProc setDisplayOption;
72
SetDisplayOptionForPluginProc setDisplayOptionForPlugin;
75
typedef struct _GConfScreen {
76
InitPluginForScreenProc initPluginForScreen;
77
SetScreenOptionProc setScreenOption;
78
SetScreenOptionForPluginProc setScreenOptionForPlugin;
81
#define GET_GCONF_DISPLAY(d) \
82
((GConfDisplay *) (d)->privates[displayPrivateIndex].ptr)
84
#define GCONF_DISPLAY(d) \
85
GConfDisplay *gd = GET_GCONF_DISPLAY (d)
87
#define GET_GCONF_SCREEN(s, gd) \
88
((GConfScreen *) (s)->privates[(gd)->screenPrivateIndex].ptr)
90
#define GCONF_SCREEN(s) \
91
GConfScreen *gs = GET_GCONF_SCREEN (s, GET_GCONF_DISPLAY (s->display))
94
strcmpskipifequal (char **ptr, char *s)
99
ret = strncmp (*ptr, s, len);
106
static GConfValueType
107
gconfTypeFromCompType (CompOptionType type)
110
case CompOptionTypeBool:
111
return GCONF_VALUE_BOOL;
112
case CompOptionTypeInt:
113
return GCONF_VALUE_INT;
114
case CompOptionTypeFloat:
115
return GCONF_VALUE_FLOAT;
116
case CompOptionTypeString:
117
return GCONF_VALUE_STRING;
118
case CompOptionTypeColor:
119
return GCONF_VALUE_STRING;
120
case CompOptionTypeBinding:
121
return GCONF_VALUE_STRING;
122
case CompOptionTypeList:
123
return GCONF_VALUE_LIST;
128
return GCONF_VALUE_INVALID;
132
gconfSetValue (CompDisplay *d,
133
CompOptionValue *value,
138
case CompOptionTypeBool:
139
gconf_value_set_bool (gvalue, value->b);
141
case CompOptionTypeInt:
142
gconf_value_set_int (gvalue, value->i);
144
case CompOptionTypeFloat:
145
gconf_value_set_float (gvalue, value->f);
147
case CompOptionTypeString:
148
gconf_value_set_string (gvalue, value->s);
150
case CompOptionTypeColor: {
153
color = g_strdup_printf ("#%.2x%.2x%.2x",
158
gconf_value_set_string (gvalue, color);
162
case CompOptionTypeBinding: {
165
if (value->bind.type == CompBindingTypeButton)
166
modMask = value->bind.u.button.modifiers;
168
modMask = value->bind.u.key.modifiers;
170
if (modMask & (CompPressMask | CompReleaseMask))
172
gchar *m, *mods = g_strdup ("");
176
for (i = 0; i < N_MODIFIERS; i++)
178
if (modMask & modifiers[i].modifier)
180
m = g_strconcat (mods, modifiers[i].name, NULL);
189
if (value->bind.type == CompBindingTypeButton)
191
binding = g_strdup_printf ("%sButton%d", mods,
192
value->bind.u.button.button);
199
keysym = XKeycodeToKeysym (d->display,
200
value->bind.u.key.keycode,
202
keyname = XKeysymToString (keysym);
205
binding = g_strdup_printf ("%s%s", mods, keyname);
207
binding = g_strdup_printf ("%s0x%x", mods,
208
value->bind.u.key.keycode);
212
gconf_value_set_string (gvalue, binding);
219
gconf_value_set_string (gvalue, "Disabled");
228
gconfSetOption (CompDisplay *d,
240
key = g_strjoin ("/", APP_NAME "/plugins", plugin, screen, "options",
245
key = g_strjoin ("/", APP_NAME "/general", screen, "options", o->name,
250
case CompOptionTypeBool:
251
case CompOptionTypeInt:
252
case CompOptionTypeFloat:
253
case CompOptionTypeString:
254
case CompOptionTypeColor:
255
case CompOptionTypeBinding:
256
gvalue = gconf_value_new (gconfTypeFromCompType (o->type));
257
gconfSetValue (d, &o->value, o->type, gvalue);
258
gconf_client_set (gd->client, key, gvalue, NULL);
259
gconf_value_free (gvalue);
261
case CompOptionTypeList: {
267
gvalue = gconf_value_new (GCONF_VALUE_LIST);
269
type = gconfTypeFromCompType (o->value.list.type);
271
for (i = 0; i < o->value.list.nValue; i++)
273
gv = gconf_value_new (type);
274
gconfSetValue (d, &o->value.list.value[i], o->value.list.type, gv);
275
list = g_slist_append (list, gv);
278
gconf_value_set_list_type (gvalue, type);
279
gconf_value_set_list (gvalue, list);
280
gconf_client_set (gd->client, key, gvalue, NULL);
282
for (i = 0; i < o->value.list.nValue; i++)
284
gv = g_slist_nth_data (list, i);
285
gconf_value_free (gv);
288
gconf_value_free (gvalue);
298
gconfGetValue (CompDisplay *d,
299
CompOptionValue *value,
304
if (type == CompOptionTypeBool &&
305
gvalue->type == GCONF_VALUE_BOOL)
307
value->b = gconf_value_get_bool (gvalue);
310
else if (type == CompOptionTypeInt &&
311
gvalue->type == GCONF_VALUE_INT)
313
value->i = gconf_value_get_int (gvalue);
316
else if (type == CompOptionTypeFloat &&
317
gvalue->type == GCONF_VALUE_FLOAT)
319
value->f = gconf_value_get_float (gvalue);
322
else if (type == CompOptionTypeString &&
323
gvalue->type == GCONF_VALUE_STRING)
325
value->s = (char *) gconf_value_get_string (gvalue);
328
else if (type == CompOptionTypeColor &&
329
gvalue->type == GCONF_VALUE_STRING)
334
color = gconf_value_get_string (gvalue);
336
if (sscanf (color, "#%2x%2x%2x", &c[0], &c[1], &c[2]) == 3)
338
value->c[0] = c[0] << 8 | c[0];
339
value->c[1] = c[1] << 8 | c[1];
340
value->c[2] = c[2] << 8 | c[2];
341
value->c[3] = 0xffff;
346
else if (type == CompOptionTypeBinding &&
347
gvalue->type == GCONF_VALUE_STRING)
349
gchar *binding, *ptr;
353
binding = (gchar *) gconf_value_get_string (gvalue);
354
if (strcasecmp (binding, "disabled") == 0)
356
value->bind.type = CompBindingTypeButton;
357
value->bind.u.button.button = 1;
358
value->bind.u.button.modifiers = 0;
362
for (i = 0; i < N_MODIFIERS; i++)
364
if (strcasestr (binding, modifiers[i].name))
365
mods |= modifiers[i].modifier;
368
/* if not explicetly set to be triggered at release
369
assume it to be triggered at press */
370
if (!(mods & CompReleaseMask))
371
mods |= CompPressMask;
373
ptr = strrchr (binding, '>');
377
while (*binding && !isalnum (*binding))
380
if (strcmpskipifequal (&binding, "Button") == 0)
384
if (sscanf (binding, "%d", &button) == 1)
386
value->bind.type = CompBindingTypeButton;
387
value->bind.u.button.button = button;
388
value->bind.u.button.modifiers = mods;
397
keysym = XStringToKeysym (binding);
398
if (keysym != NoSymbol)
402
keycode = XKeysymToKeycode (d->display, keysym);
405
value->bind.type = CompBindingTypeKey;
406
value->bind.u.key.keycode = keycode;
407
value->bind.u.key.modifiers = mods;
413
if (strncmp (binding, "0x", 2) == 0)
415
value->bind.type = CompBindingTypeKey;
416
value->bind.u.key.keycode = strtol (binding, NULL, 0);
417
value->bind.u.key.modifiers = mods;
429
gconfGetOptionValue (CompDisplay *d,
434
CompOption *o, *option;
436
gchar *pluginPtr = 0;
445
if (strncmp (ptr, APP_NAME, strlen (APP_NAME)))
448
ptr += strlen (APP_NAME);
450
if (strcmpskipifequal (&ptr, "/plugins/") == 0)
453
ptr = strchr (ptr, '/');
457
pluginLen = ptr - pluginPtr;
461
else if (strcmpskipifequal (&ptr, "/general"))
464
if (strcmpskipifequal (&ptr, "/screen") == 0)
468
screenNum = strtol (ptr, &ptr, 0);
470
for (s = d->screens; s; s = s->next)
471
if (s->screenNum == screenNum)
477
else if (strcmpskipifequal (&ptr, "/allscreens"))
480
if (strcmpskipifequal (&ptr, "/options/"))
485
pluginPtr = g_strndup (pluginPtr, pluginLen);
490
p = findActivePlugin (pluginPtr);
495
if (p->vTable->getScreenOptions)
496
option = (*p->vTable->getScreenOptions) (s, &nOption);
500
if (p->vTable->getDisplayOptions)
501
option = (*p->vTable->getDisplayOptions) (d, &nOption);
508
option = compGetScreenOptions (s, &nOption);
510
option = compGetDisplayOptions (d, &nOption);
513
o = compFindOption (option, nOption, ptr, 0);
517
CompOptionValue value;
519
gvalue = gconf_entry_get_value (entry);
522
if (o->type == CompOptionTypeList &&
523
gvalue->type == GCONF_VALUE_LIST)
527
value.list.value = 0;
528
value.list.nValue = 0;
530
type = gconf_value_get_list_type (gvalue);
531
if (type == gconfTypeFromCompType (o->value.list.type))
538
list = gconf_value_get_list (gvalue);
540
length = g_slist_length (list);
545
malloc (sizeof (CompOptionValue) * length);
546
if (value.list.value)
548
value.list.nValue = length;
549
for (i = 0; i < length; i++)
551
if (!gconfGetValue (d, &value.list.value[i],
553
(GConfValue *) list->data))
556
list = g_slist_next (list);
568
status = gconfGetValue (d, &value, o->type, gvalue);
576
status = (*s->setScreenOptionForPlugin) (s,
581
status = (*s->setScreenOption) (s, ptr, &value);
586
status = (*d->setDisplayOptionForPlugin) (d,
591
status = (*d->setDisplayOption) (d, ptr, &value);
595
if (o->type == CompOptionTypeList &&
596
gvalue->type == GCONF_VALUE_LIST)
598
if (value.list.nValue && value.list.value)
599
free (value.list.value);
608
screen = g_strdup_printf ("screen%d", s->screenNum);
610
gconfSetOption (d, o, screen, pluginPtr);
624
gconfInitOption (CompDisplay *d,
636
key = g_strjoin ("/", APP_NAME "/plugins", plugin, screen,
637
"options", o->name, NULL);
641
key = g_strjoin ("/", APP_NAME "/general", screen, "options",
645
entry = gconf_client_get_entry (gd->client, key, NULL, FALSE, NULL);
647
if (!gconfGetOptionValue (d, entry))
648
gconfSetOption (d, o, screen, plugin);
651
gconf_entry_free (entry);
657
gconfInitPlugin (CompDisplay *d,
660
gchar *gconfpath, *key;
664
gconfpath = g_strjoin ("/", APP_NAME "/plugins", p->vTable->name, NULL);
666
key = g_strconcat (gconfpath, "/short_description", NULL);
667
gconf_client_set_string (gd->client, key, p->vTable->shortDesc, NULL);
670
key = g_strconcat (gconfpath, "/long_description", NULL);
671
gconf_client_set_string (gd->client, key, p->vTable->longDesc, NULL);
678
gconfSetDisplayOption (CompDisplay *d,
680
CompOptionValue *value)
686
UNWRAP (gd, d, setDisplayOption);
687
status = (*d->setDisplayOption) (d, name, value);
688
WRAP (gd, d, setDisplayOption, gconfSetDisplayOption);
695
option = compGetDisplayOptions (d, &nOption);
696
gconfSetOption (d, compFindOption (option, nOption, name, 0),
704
gconfSetDisplayOptionForPlugin (CompDisplay *d,
707
CompOptionValue *value)
713
UNWRAP (gd, d, setDisplayOptionForPlugin);
714
status = (*d->setDisplayOptionForPlugin) (d, plugin, name, value);
715
WRAP (gd, d, setDisplayOptionForPlugin, gconfSetDisplayOptionForPlugin);
721
p = findActivePlugin (plugin);
722
if (p && p->vTable->getDisplayOptions)
727
option = (*p->vTable->getDisplayOptions) (d, &nOption);
728
gconfSetOption (d, compFindOption (option, nOption, name, 0),
729
"allscreens", plugin);
737
gconfSetScreenOption (CompScreen *s,
739
CompOptionValue *value)
745
UNWRAP (gs, s, setScreenOption);
746
status = (*s->setScreenOption) (s, name, value);
747
WRAP (gs, s, setScreenOption, gconfSetScreenOption);
755
screen = g_strdup_printf ("screen%d", s->screenNum);
757
option = compGetScreenOptions (s, &nOption);
758
gconfSetOption (s->display, compFindOption (option, nOption, name, 0),
768
gconfSetScreenOptionForPlugin (CompScreen *s,
771
CompOptionValue *value)
777
UNWRAP (gs, s, setScreenOptionForPlugin);
778
status = (*s->setScreenOptionForPlugin) (s, plugin, name, value);
779
WRAP (gs, s, setScreenOptionForPlugin, gconfSetScreenOptionForPlugin);
785
p = findActivePlugin (plugin);
786
if (p && p->vTable->getScreenOptions)
792
screen = g_strdup_printf ("screen%d", s->screenNum);
794
option = (*p->vTable->getScreenOptions) (s, &nOption);
795
gconfSetOption (s->display,
796
compFindOption (option, nOption, name, 0),
807
gconfInitPluginForDisplay (CompPlugin *p,
814
UNWRAP (gd, d, initPluginForDisplay);
815
status = (*d->initPluginForDisplay) (p, d);
816
WRAP (gd, d, initPluginForDisplay, gconfInitPluginForDisplay);
819
gconfInitPlugin (d, p);
821
if (status && p->vTable->getDisplayOptions)
826
option = (*p->vTable->getDisplayOptions) (d, &nOption);
828
gconfInitOption (d, option++, "allscreens", p->vTable->name);
835
gconfInitPluginForScreen (CompPlugin *p,
842
UNWRAP (gs, s, initPluginForScreen);
843
status = (*s->initPluginForScreen) (p, s);
844
WRAP (gs, s, initPluginForScreen, gconfInitPluginForScreen);
846
if (status && p->vTable->getScreenOptions)
852
screen = g_strdup_printf ("screen%d", s->screenNum);
854
option = (*p->vTable->getScreenOptions) (s, &nOption);
856
gconfInitOption (s->display, option++, screen, p->vTable->name);
865
gconfKeyChanged (GConfClient *client,
870
CompDisplay *display = (CompDisplay *) user_data;
872
gconfGetOptionValue (display, entry);
876
gconfTimeout (void *closure)
878
while (g_main_pending ()) g_main_iteration (FALSE);
884
gconfInitDisplay (CompPlugin *p,
891
gd = malloc (sizeof (GConfDisplay));
895
gd->screenPrivateIndex = allocateScreenPrivateIndex (d);
896
if (gd->screenPrivateIndex < 0)
904
gd->client = gconf_client_get_default ();
906
gconf_client_add_dir (gd->client, APP_NAME,
907
GCONF_CLIENT_PRELOAD_NONE, NULL);
909
WRAP (gd, d, initPluginForDisplay, gconfInitPluginForDisplay);
910
WRAP (gd, d, setDisplayOption, gconfSetDisplayOption);
911
WRAP (gd, d, setDisplayOptionForPlugin, gconfSetDisplayOptionForPlugin);
913
d->privates[displayPrivateIndex].ptr = gd;
915
option = compGetDisplayOptions (d, &nOption);
917
gconfInitOption (d, option++, "allscreens", 0);
919
gconf_client_notify_add (gd->client, APP_NAME, gconfKeyChanged, d,
922
gd->timeoutHandle = compAddTimeout (KEY_CHANGE_TIMEOUT, gconfTimeout, 0);
928
gconfFiniDisplay (CompPlugin *p,
933
compRemoveTimeout (gd->timeoutHandle);
935
g_object_unref (gd->client);
937
freeScreenPrivateIndex (d, gd->screenPrivateIndex);
943
gconfInitScreen (CompPlugin *p,
951
GCONF_DISPLAY (s->display);
953
gs = malloc (sizeof (GConfScreen));
957
WRAP (gs, s, initPluginForScreen, gconfInitPluginForScreen);
958
WRAP (gs, s, setScreenOption, gconfSetScreenOption);
959
WRAP (gs, s, setScreenOptionForPlugin, gconfSetScreenOptionForPlugin);
961
s->privates[gd->screenPrivateIndex].ptr = gs;
963
screen = g_strdup_printf ("screen%d", s->screenNum);
965
option = compGetScreenOptions (s, &nOption);
967
gconfInitOption (s->display, option++, screen, 0);
975
gconfFiniScreen (CompPlugin *p,
980
UNWRAP (gs, s, initPluginForScreen);
981
UNWRAP (gs, s, setScreenOption);
982
UNWRAP (gs, s, setScreenOptionForPlugin);
988
gconfInit (CompPlugin *p)
990
displayPrivateIndex = allocateDisplayPrivateIndex ();
991
if (displayPrivateIndex < 0)
998
gconfFini (CompPlugin *p)
1000
if (displayPrivateIndex >= 0)
1001
freeDisplayPrivateIndex (displayPrivateIndex);
1004
CompPluginDep gconfDeps[] = {
1005
{ CompPluginRuleBefore, "decoration" },
1006
{ CompPluginRuleBefore, "wobbly" },
1007
{ CompPluginRuleBefore, "fade" },
1008
{ CompPluginRuleBefore, "cube" },
1009
{ CompPluginRuleBefore, "expose" }
1012
CompPluginVTable gconfVTable = {
1015
"GConf Control Backend",
1024
0, /* GetDisplayOptions */
1025
0, /* SetDisplayOption */
1026
0, /* GetScreenOptions */
1027
0, /* SetScreenOption */
1029
sizeof (gconfDeps) / sizeof (gconfDeps[0])
1033
getCompPluginInfo (void)
1035
return &gconfVTable;