You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
compizconfig-backend-tdeconfig/settings-backend/kconfig_backend.cpp

1973 lines
45 KiB

/*
* KDE libccs backend
*
* Copyright (c) 2006 Dennis Kasprzyk <onestone@opencompositing.org>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <qdir.h>
#include <kconfig.h>
#include <ksimpleconfig.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kinstance.h>
#include <kshortcut.h>
#include <kipc.h>
#include <kapplication.h>
#include <dcopclient.h>
#include <kdirwatch.h>
#include <stdlib.h>
#include <X11/X.h>
#include <X11/Xlib.h>
extern "C"
{
#include <ccs.h>
#include <ccs-backend.h>
}
#define CORE_NAME "core"
#define CompAltMask (1 << 16)
#define CompMetaMask (1 << 17)
#define CompSuperMask (1 << 18)
#define CompHyperMask (1 << 19)
#define CompModeSwitchMask (1 << 20)
#define CompNumLockMask (1 << 21)
#define CompScrollLockMask (1 << 22)
static KInstance *instance = NULL;
typedef struct _ConfigFiles
{
KSimpleConfig *main;
QString profile;
KConfig *kwin;
KConfig *global;
Bool modified;
unsigned int watch;
unsigned int kwinWatch;
unsigned int globalWatch;
}
ConfigFiles;
static ConfigFiles *cFiles = NULL;
typedef enum
{
OptionInt,
OptionBool,
OptionKey,
OptionSpecial
}
SpecialOptionType;
struct _SpecialOption
{
QString settingName;
QString pluginName;
QString kdeName;
bool global;
SpecialOptionType type;
}
const specialOptions[] =
{
{"close_window_key", CORE_NAME, "Window Close", true, OptionKey},
{"lower_window_key", CORE_NAME, "Window Lower", true, OptionKey},
{"toggle_window_maximized_key", CORE_NAME, "Window Maximize", true, OptionKey},
{"minimize_window_key", CORE_NAME, "Window Minimize", true, OptionKey},
{"toggle_window_maximized_horizontally_key", CORE_NAME, "Window Maximize Horizontal", true, OptionKey},
{"toggle_window_maximized_vertically_key", CORE_NAME, "Window Maximize Vertical", true, OptionKey},
{"show_desktop_key", CORE_NAME, "Toggle Showing Desktop", true, OptionKey},
{"window_menu_key", CORE_NAME, "Window Operations Menu", true, OptionKey},
{"toggle_window_shaded_key", CORE_NAME, "Window Shade", true, OptionKey},
{"raise_window_key", CORE_NAME, "Window Raise", true, OptionKey},
{"toggle_window_fullscreen_key", CORE_NAME, "Window Fullscreen", true, OptionKey},
{"run_command11_key", "commands", "Kill Window", true, OptionKey},
{"initiate_key", "move", "Window Move", true, OptionKey},
{"initiate_key", "resize", "Window Resize", true, OptionKey},
{"rotate_right_key", "rotate", "Switch to Next Desktop", true, OptionKey},
{"rotate_left_key", "rotate", "Switch to Previous Desktop", true, OptionKey},
{"rotate_to_1_key", "rotate", "Switch to Desktop 1", true, OptionKey},
{"rotate_to_2_key", "rotate", "Switch to Desktop 2", true, OptionKey},
{"rotate_to_3_key", "rotate", "Switch to Desktop 3", true, OptionKey},
{"rotate_to_4_key", "rotate", "Switch to Desktop 4", true, OptionKey},
{"rotate_to_5_key", "rotate", "Switch to Desktop 5", true, OptionKey},
{"rotate_to_6_key", "rotate", "Switch to Desktop 6", true, OptionKey},
{"rotate_to_7_key", "rotate", "Switch to Desktop 7", true, OptionKey},
{"rotate_to_8_key", "rotate", "Switch to Desktop 8", true, OptionKey},
{"rotate_to_9_key", "rotate", "Switch to Desktop 9", true, OptionKey},
{"rotate_to_10_key", "rotate", "Switch to Desktop 10", true, OptionKey},
{"rotate_to_11_key", "rotate", "Switch to Desktop 11", true, OptionKey},
{"rotate_to_12_key", "rotate", "Switch to Desktop 12", true, OptionKey},
{"rotate_right_window_key", "rotate", "Window to Next Desktop", true, OptionKey},
{"rotate_left_window_key", "rotate", "Window to Previous Desktop", true, OptionKey},
{"rotate_to_1_window_key", "rotate", "Window to Desktop 1", true, OptionKey},
{"rotate_to_2_window_key", "rotate", "Window to Desktop 2", true, OptionKey},
{"rotate_to_3_window_key", "rotate", "Window to Desktop 3", true, OptionKey},
{"rotate_to_4_window_key", "rotate", "Window to Desktop 4", true, OptionKey},
{"rotate_to_5_window_key", "rotate", "Window to Desktop 5", true, OptionKey},
{"rotate_to_6_window_key", "rotate", "Window to Desktop 6", true, OptionKey},
{"rotate_to_7_window_key", "rotate", "Window to Desktop 7", true, OptionKey},
{"rotate_to_8_window_key", "rotate", "Window to Desktop 8", true, OptionKey},
{"rotate_to_9_window_key", "rotate", "Window to Desktop 9", true, OptionKey},
{"rotate_to_10_window_key", "rotate", "Window to Desktop 10", true, OptionKey},
{"rotate_to_11_window_key", "rotate", "Window to Desktop 11", true, OptionKey},
{"rotate_to_12_window_key", "rotate", "Window to Desktop 12", true, OptionKey},
{"next_key", "wall", "Switch to Next Desktop", true, OptionKey},
{"prev_key", "wall", "Switch to Previous Desktop", true, OptionKey},
{"right_window_key", "wall", "Window One Desktop to the Right", true, OptionKey},
{"left_window_key", "wall", "Window One Desktop to the Left", true, OptionKey},
{"up_window_key", "wall", "Window One Desktop Up", true, OptionKey},
{"down_window_key", "wall", "Window One Desktop Down", true, OptionKey},
{"up_key", "wall", "Switch One Desktop Up", true, OptionKey},
{"down_key", "wall", "Switch One Desktop Down", true, OptionKey},
{"left_key", "wall", "Switch One Desktop to the Left", true, OptionKey},
{"right_key", "wall", "Switch One Desktop to the Right", true, OptionKey},
{"switch_to_1_key", "vpswitch", "Switch to Desktop 1", true, OptionKey},
{"switch_to_2_key", "vpswitch", "Switch to Desktop 2", true, OptionKey},
{"switch_to_3_key", "vpswitch", "Switch to Desktop 3", true, OptionKey},
{"switch_to_4_key", "vpswitch", "Switch to Desktop 4", true, OptionKey},
{"switch_to_5_key", "vpswitch", "Switch to Desktop 5", true, OptionKey},
{"switch_to_6_key", "vpswitch", "Switch to Desktop 6", true, OptionKey},
{"switch_to_7_key", "vpswitch", "Switch to Desktop 7", true, OptionKey},
{"switch_to_8_key", "vpswitch", "Switch to Desktop 8", true, OptionKey},
{"switch_to_9_key", "vpswitch", "Switch to Desktop 9", true, OptionKey},
{"switch_to_10_key", "vpswitch", "Switch to Desktop 10", true, OptionKey},
{"switch_to_11_key", "vpswitch", "Switch to Desktop 11", true, OptionKey},
{"switch_to_12_key", "vpswitch", "Switch to Desktop 12", true, OptionKey},
{"autoraise", CORE_NAME, "AutoRaise", false, OptionBool},
{"raise_on_click", CORE_NAME, "ClickRaise", false, OptionBool},
{"snapoff_maximized", "move", "MoveResizeMaximizedWindows", false, OptionBool},
{"always_show", "resizeinfo", "GeometryTip", false, OptionBool},
{"allow_wraparound", "wall", "RollOverDesktops", false, OptionBool},
{"autoraise_delay", CORE_NAME, "AutoRaiseInterval", false, OptionInt},
{"flip_time", "rotate", "ElectricBorderDelay", false, OptionInt},
{"unmaximize_window_key", CORE_NAME, NULL, true, OptionSpecial},
{"maximize_window_key", CORE_NAME, NULL, true, OptionSpecial},
{"maximize_window_horizontally_key", CORE_NAME, NULL, true, OptionSpecial},
{"maximize_window_vertically_key", CORE_NAME, NULL, true, OptionSpecial},
{"command11", "commands", NULL, true, OptionSpecial},
{"click_to_focus", CORE_NAME, NULL, false, OptionSpecial},
{"mode", "resize", NULL, true, OptionSpecial},
{"number_of_desktops", CORE_NAME, "Number", false, OptionSpecial},
{"snap_type", "snap", NULL, false, OptionSpecial},
{"edges_categories", "snap", NULL, false, OptionSpecial},
{"resistance_distance", "snap", NULL, false, OptionSpecial},
{"attraction_distance", "snap", NULL, false, OptionSpecial},
{"next_key", "switcher", "Walk Through Windows", true, OptionSpecial},
{"prev_key", "switcher", "Walk Through Windows (Reverse)", true, OptionSpecial},
{"next_all_key", "switcher", "Walk Through Windows", true, OptionSpecial},
{"prev_all_key", "switcher", "Walk Through Windows (Reverse)", true, OptionSpecial},
{"next_no_popup_key", "switcher", "Walk Through Windows", true, OptionSpecial},
{"prev_no_popup_key", "switcher", "Walk Through Windows (Reverse)", true, OptionSpecial},
{"edge_flip_pointer", "rotate", "ElectricBorders", false, OptionSpecial},
{"edge_flip_window", "rotate", "ElectricBorders", false, OptionSpecial},
{"edgeflip_pointer", "wall", "ElectricBorders", false, OptionSpecial},
{"edgeflip_move", "wall", "ElectricBorders", false, OptionSpecial},
{"mode", "place", "Placement", false, OptionSpecial}
};
#define N_SOPTIONS (sizeof (specialOptions) / sizeof (struct _SpecialOption))
static void
createFile (QString name)
{
if (!QFile::exists(name))
{
QFile file (name);
file.open (IO_WriteOnly | IO_Append);
file.close ();
}
}
static void
reload (unsigned int,
void *closure)
{
CCSContext *context = (CCSContext *) closure;
ccsDisableFileWatch (cFiles->watch);
ccsDisableFileWatch (cFiles->kwinWatch);
ccsDisableFileWatch (cFiles->globalWatch);
cFiles->main->reparseConfiguration();
cFiles->kwin->reparseConfiguration();
cFiles->global->reparseConfiguration();
ccsReadSettings (context);
ccsEnableFileWatch (cFiles->watch);
ccsEnableFileWatch (cFiles->kwinWatch);
ccsEnableFileWatch (cFiles->globalWatch);
}
static bool
isIntegratedOption (CCSSetting *setting)
{
for (unsigned int i = 0; i < N_SOPTIONS; i++)
{
if (setting->name == specialOptions[i].settingName &&
QString (setting->parent->name) == specialOptions[i].pluginName)
return true;
}
return false;
}
static void
KdeIntToCCS (CCSSetting *setting,
int num)
{
KConfig *cfg = (specialOptions[num].global) ? cFiles->global : cFiles->kwin;
int val = cfg->readNumEntry (specialOptions[num].kdeName);
ccsSetInt (setting, val);
}
static void
KdeBoolToCCS (CCSSetting *setting,
int num)
{
KConfig *cfg = (specialOptions[num].global) ? cFiles->global : cFiles->kwin;
Bool val = (cfg->readBoolEntry (specialOptions[num].kdeName))? TRUE : FALSE;
ccsSetBool (setting, val);
}
static void
KdeKeyToCCS (CCSSetting *setting,
int num)
{
KConfig *cfg = (specialOptions[num].global) ? cFiles->global : cFiles->kwin;
KKey key (cfg->readEntry (specialOptions[num].kdeName) );
int kdeKeysym = key.sym();
int kdeKeymod = 0;
if (key.modFlags() & KKey::SHIFT)
kdeKeymod |= ShiftMask;
if (key.modFlags() & KKey::CTRL)
kdeKeymod |= ControlMask;
if (key.modFlags() & KKey::ALT)
kdeKeymod |= CompAltMask;
if (key.modFlags() & KKey::WIN)
kdeKeymod |= CompSuperMask;
CCSSettingKeyValue keySet;
if (!key.isNull())
{
keySet.keysym = kdeKeysym;
keySet.keyModMask = kdeKeymod;
ccsSetKey (setting, keySet);
}
}
static void
readIntegratedOption (CCSSetting *setting)
{
int option = 0;
for (unsigned int i = 0; i < N_SOPTIONS; i++)
{
if (setting->name == specialOptions[i].settingName &&
QString (setting->parent->name) == specialOptions[i].pluginName)
{
option = i;
break;
}
}
switch (specialOptions[option].type)
{
case OptionInt:
KdeIntToCCS (setting, option);
break;
case OptionBool:
KdeBoolToCCS (setting, option);
break;
case OptionKey:
KdeKeyToCCS (setting, option);
break;
case OptionSpecial:
if (specialOptions[option].settingName == "command11")
{
ccsSetString (setting, "xkill");
}
else if (specialOptions[option].settingName == "unmaximize_window_key"
|| specialOptions[option].settingName == "maximize_window_key"
|| specialOptions[option].settingName == "maximize_window_horizontally_key"
|| specialOptions[option].settingName == "maximize_window_vertically_key")
{
CCSSettingKeyValue keyVal;
if (!ccsGetKey (setting, &keyVal) )
break;
keyVal.keysym = 0;
keyVal.keyModMask = 0;
ccsSetKey (setting, keyVal);
}
else if (specialOptions[option].settingName == "click_to_focus")
{
Bool val = (cFiles->kwin->readEntry ("FocusPolicy") ==
"ClickToFocus") ? TRUE : FALSE;
ccsSetBool (setting, val);
}
else if (specialOptions[option].settingName == "number_of_desktops")
{
cFiles->kwin->setGroup ("Desktops");
KdeIntToCCS (setting, option);
cFiles->kwin->setGroup ("Windows");
}
else if (specialOptions[option].settingName == "mode" &&
specialOptions[option].pluginName == "resize")
{
QString mode = cFiles->kwin->readEntry ("ResizeMode");
int imode = -1;
int result = 0;
if (cFiles->main->hasKey (specialOptions[option].settingName +
" (Integrated)") )
imode = cFiles->main->readNumEntry (
specialOptions[option].settingName + " (Integrated)");
if (mode == "Opaque")
{
result = 0;
if (imode == 3)
result = 3;
}
else if (mode == "Transparent")
{
result = 1;
if (imode == 2)
result = 2;
}
ccsSetInt (setting, result);
}
else if (specialOptions[option].settingName == "snap_type")
{
static int intList[2] = {0, 1};
CCSSettingValueList list = ccsGetValueListFromIntArray (intList, 2,
setting);
ccsSetList (setting, list);
ccsSettingValueListFree (list, TRUE);
}
else if (specialOptions[option].settingName == "resistance_distance" ||
specialOptions[option].settingName == "attraction_distance")
{
int val1 = cFiles->kwin->readNumEntry ("WindowSnapZone");
int val2 = cFiles->kwin->readNumEntry ("BorderSnapZone");
int result = KMAX (val1, val2);
if (result == 0)
result = cFiles->main->readNumEntry ("snap_distance (Integrated)");
if (result > 0)
ccsSetInt (setting, result);
}
else if (specialOptions[option].settingName == "edges_categories")
{
int val1 = cFiles->kwin->readNumEntry ("WindowSnapZone");
int val2 = cFiles->kwin->readNumEntry ("BorderSnapZone");
int intList[2] = {0, 0};
int num = 0;
if (val2 > 0)
num++;
if (val1 > 0)
{
intList[num] = 1;
num++;
}
CCSSettingValueList list = ccsGetValueListFromIntArray (intList,
num,
setting);
ccsSetList (setting, list);
ccsSettingValueListFree (list, TRUE);
}
else if (specialOptions[option].settingName == "next_key" ||
specialOptions[option].settingName == "prev_key")
{
bool val1;
bool val2 = (cFiles->kwin->readEntry ("AltTabStyle") == "KDE");
cFiles->kwin->setGroup ("TabBox");
val1 = cFiles->kwin->readBoolEntry ("TraverseAll");
cFiles->kwin->setGroup ("Windows");
if (val2 && !val1)
KdeKeyToCCS (setting, option);
else
{
CCSSettingKeyValue keyVal;
if (ccsGetKey (setting, &keyVal) )
{
keyVal.keysym = 0;
keyVal.keyModMask = 0;
ccsSetKey (setting, keyVal);
}
}
}
else if (specialOptions[option].settingName == "next_all_key" ||
specialOptions[option].settingName == "prev_all_key")
{
bool val1;
bool val2 = (cFiles->kwin->readEntry ("AltTabStyle") == "KDE");
cFiles->kwin->setGroup ("TabBox");
val1 = cFiles->kwin->readBoolEntry ("TraverseAll");
cFiles->kwin->setGroup ("Windows");
if (val2 && val1)
KdeKeyToCCS (setting, option);
else
{
CCSSettingKeyValue keyVal;
if (ccsGetKey (setting, &keyVal) )
{
keyVal.keysym = 0;
keyVal.keyModMask = 0;
ccsSetKey (setting, keyVal);
}
}
}
else if (specialOptions[option].settingName == "next_no_popup_key" ||
specialOptions[option].settingName == "prev_no_popup_key")
{
bool val2 = (cFiles->kwin->readEntry ("AltTabStyle") == "KDE");
if (!val2)
KdeKeyToCCS (setting, option);
else
{
CCSSettingKeyValue keyVal;
if (ccsGetKey (setting, &keyVal) )
{
keyVal.keysym = 0;
keyVal.keyModMask = 0;
ccsSetKey (setting, keyVal);
}
}
}
else if (specialOptions[option].settingName == "edge_flip_window" ||
specialOptions[option].settingName == "edgeflip_move")
{
int val = cFiles->kwin->readNumEntry ("ElectricBorders");
if (val > 0)
ccsSetBool (setting, TRUE);
else
ccsSetBool (setting, FALSE);
}
else if (specialOptions[option].settingName == "edge_flip_pointer" ||
specialOptions[option].settingName == "edgeflip_pointer")
{
int val = cFiles->kwin->readNumEntry ("ElectricBorders");
if (val > 1)
ccsSetBool (setting, TRUE);
else
ccsSetBool (setting, FALSE);
}
else if (specialOptions[option].settingName == "mode" &&
specialOptions[option].pluginName == "place")
{
QString mode = cFiles->kwin->readEntry ("Placement");
int result = 0;
if (mode == "Smart")
result = 2;
else if (mode == "Maximizing")
result = 3;
else if (mode == "Cascade")
result = 0;
else if (mode == "Random")
result = 4;
else if (mode == "Centered")
result = 1;
ccsSetInt (setting, result);
}
break;
default:
break;
}
}
static Bool
getSettingIsIntegrated (CCSSetting *setting)
{
return ccsGetIntegrationEnabled (setting->parent->context)
&& isIntegratedOption (setting);
}
static Bool
getSettingIsReadOnly (CCSSetting *setting)
{
if (!ccsGetIntegrationEnabled (setting->parent->context)
|| !isIntegratedOption (setting) )
return FALSE;
int option = 0;
for (unsigned int i = 0; i < N_SOPTIONS; i++)
{
if (setting->name == specialOptions[i].settingName &&
QString (setting->parent->name) == specialOptions[i].pluginName)
{
option = i;
break;
}
}
switch (specialOptions[option].type)
{
case OptionSpecial:
if (specialOptions[option].settingName == "command11")
{
return TRUE;
}
else if (specialOptions[option].settingName == "map_on_shutdown")
{
return TRUE;
}
else if (specialOptions[option].settingName == "unmaximize_window_key"
|| specialOptions[option].settingName == "maximize_window_key"
|| specialOptions[option].settingName == "maximize_window_horizontally_key"
|| specialOptions[option].settingName == "maximize_window_vertically_key")
{
return TRUE;
}
else if (specialOptions[option].settingName == "snap_type" ||
specialOptions[option].settingName == "attraction_distance")
{
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
static CCSStringList
getExistingProfiles (CCSContext *)
{
if (!instance)
instance = new KInstance ("ccs-backend-kconfig");
QDir dir (KGlobal::dirs()->saveLocation ("config", QString::null, false),
"compizrc.*");
QStringList files = dir.entryList();
CCSStringList ret = NULL;
QStringList::iterator it;
for (it = files.begin(); it != files.end(); it++)
{
QString str = (*it);
if (str.length() > 9)
{
QString profile = str.right (str.length() - 9);
if (!profile.isEmpty() )
ret = ccsStringListAppend (ret, strdup (profile.ascii() ) );
}
}
return ret;
}
static void
readSetting (CCSContext *c,
CCSSetting *setting)
{
KSimpleConfig *cfg = cFiles->main;
QString key (setting->name);
QString group (setting->parent->name);
if (setting->isScreen)
{
group += "_screen";
group += QString::number (setting->screenNum);
}
else
group += "_display";
cfg->setGroup (group);
if (ccsGetIntegrationEnabled (c) && isIntegratedOption (setting) )
{
readIntegratedOption (setting);
return;
}
if (!cfg->hasKey (key) )
{
ccsResetToDefault (setting);
return;
}
switch (setting->type)
{
case TypeString:
ccsSetString (setting, cfg->readEntry (key, "").ascii() );
break;
case TypeMatch:
ccsSetMatch (setting, cfg->readEntry (key, "").ascii() );
break;
case TypeFloat:
ccsSetFloat (setting, cfg->readDoubleNumEntry (key) );
break;
case TypeInt:
ccsSetInt (setting, cfg->readNumEntry (key) );
break;
case TypeBool:
{
Bool val = (cfg->readBoolEntry (key) ) ? TRUE : FALSE;
ccsSetBool (setting, val);
}
break;
case TypeColor:
{
QString str = cfg->readEntry (key);
CCSSettingColorValue color;
int c[4];
if (sscanf (str.ascii (), "#%2x%2x%2x%2x",
&c[0], &c[1], &c[2], &c[3]) == 4)
{
color.color.red = c[0] << 8 | c[0];
color.color.green = c[1] << 8 | c[1];
color.color.blue = c[2] << 8 | c[2];
color.color.alpha = c[3] << 8 | c[3];
}
ccsSetColor (setting, color);
}
break;
case TypeList:
{
switch (setting->info.forList.listType)
{
case TypeBool:
{
QValueList<int> list = cfg->readIntListEntry (key);
Bool *array = new Bool[list.count() ];
int i = 0;
QValueList<int>::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
array[i] = ( (*it) ) ? TRUE : FALSE;
i++;
}
CCSSettingValueList l =
ccsGetValueListFromBoolArray (array, i, setting);
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
delete array;
}
break;
case TypeInt:
{
QValueList<int> list = cfg->readIntListEntry (key);
int *array = new int[list.count() ];
int i = 0;
QValueList<int>::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
array[i] = (*it);
i++;
}
CCSSettingValueList l =
ccsGetValueListFromIntArray (array, i, setting);
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
delete array;
}
break;
case TypeString:
{
QStringList list = cfg->readListEntry (key);
if (!list.count() )
break;
char **array = new char *[list.count() ];
int i = 0;
QStringList::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
array[i] = strdup ( (*it).ascii() );
i++;
}
CCSSettingValueList l =
ccsGetValueListFromStringArray (array, i, setting);
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
for (int j = 0; j < i; j++)
free (array[j]);
delete [] array;
}
break;
case TypeMatch:
{
QStringList list = cfg->readListEntry (key);
if (!list.count() )
break;
char **array = new char *[list.count() ];
int i = 0;
QStringList::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
array[i] = strdup ( (*it).ascii() );
i++;
}
CCSSettingValueList l =
ccsGetValueListFromStringArray (array, i, setting);
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
for (int j = 0; j < i; j++)
free (array[j]);
delete [] array;
}
break;
case TypeFloat:
{
QStringList list = cfg->readListEntry (key);
float *array = new float[list.count() ];
int i = 0;
QStringList::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
array[i] = (*it).toDouble();
i++;
}
CCSSettingValueList l =
ccsGetValueListFromFloatArray (array, i, setting);
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
delete array;
}
break;
case TypeColor:
{
QStringList list = cfg->readListEntry (key);
CCSSettingColorValue *array =
new CCSSettingColorValue[list.count() ];
int i = 0;
QStringList::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
int c[4];
if (sscanf ((*it).ascii (), "#%2x%2x%2x%2x",
&c[0], &c[1], &c[2], &c[3]) == 4)
{
array[i].color.red = c[0] << 8 | c[0];
array[i].color.green = c[1] << 8 | c[1];
array[i].color.blue = c[2] << 8 | c[2];
array[i].color.alpha = c[3] << 8 | c[3];
}
i++;
}
CCSSettingValueList l =
ccsGetValueListFromColorArray (array, i, setting);
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
delete array;
}
break;
case TypeKey:
{
QStringList list = cfg->readListEntry (key);
CCSSettingValue *val = NULL;
CCSSettingValueList l = NULL;
QStringList::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
val = (CCSSettingValue*) malloc (sizeof (CCSSettingValue));
if (!val)
break;
if (ccsStringToKeyBinding ((*it).ascii (),
&val->value.asKey))
l = ccsSettingValueListAppend (l, val);
else
free (val);
}
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
}
break;
case TypeButton:
{
QStringList list = cfg->readListEntry (key);
CCSSettingValue *val = NULL;
CCSSettingValueList l = NULL;
QStringList::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
val = (CCSSettingValue*) malloc (sizeof (CCSSettingValue));
if (!val)
break;
if (ccsStringToButtonBinding ((*it).ascii (),
&val->value.asButton))
l = ccsSettingValueListAppend (l, val);
else
free (val);
}
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
}
break;
case TypeEdge:
{
QStringList list = cfg->readListEntry (key);
CCSSettingValue *val = NULL;
CCSSettingValueList l = NULL;
QStringList::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
val = (CCSSettingValue*) malloc (sizeof (CCSSettingValue));
if (!val)
break;
val->value.asEdge = ccsStringToEdges ((*it).ascii ());
l = ccsSettingValueListAppend (l, val);
}
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
}
break;
case TypeBell:
{
QValueList<int> list = cfg->readIntListEntry (key);
CCSSettingValue *val = NULL;
CCSSettingValueList l = NULL;
QValueList<int>::iterator it;
for (it = list.begin(); it != list.end(); it++)
{
val = (CCSSettingValue*) malloc (sizeof (CCSSettingValue));
val->value.asBell = ((*it)) ? TRUE : FALSE;
l = ccsSettingValueListAppend (l, val);
}
ccsSetList (setting, l);
ccsSettingValueListFree (l, TRUE);
}
break;
default:
break;
}
}
break;
case TypeKey:
{
QString str = cfg->readEntry (key);
CCSSettingKeyValue value;
ccsStringToKeyBinding (str.ascii(), &value);
ccsSetKey (setting, value);
}
break;
case TypeButton:
{
QString str = cfg->readEntry (key);
CCSSettingButtonValue value;
ccsStringToButtonBinding (str.ascii(), &value);
ccsSetButton (setting, value);
}
break;
case TypeEdge:
{
QString str = cfg->readEntry (key);
unsigned int value;
value = ccsStringToEdges (str.ascii());
ccsSetEdge (setting, value);
}
break;
case TypeBell:
{
Bool val = (cfg->readBoolEntry (key)) ? TRUE : FALSE;
ccsSetBell (setting, val);
}
break;
default:
kdDebug () << "Not supported setting type : " << setting->type << endl;
break;
}
}
static void
CCSIntToKde (CCSSetting *setting,
int num)
{
KConfig *cfg = (specialOptions[num].global) ? cFiles->global : cFiles->kwin;
int val;
if (!ccsGetInt (setting, &val) )
return;
if (cfg->readNumEntry (specialOptions[num].kdeName) != val)
{
cFiles->modified = true;
cfg->writeEntry (specialOptions[num].kdeName, val);
}
}
static void
CCSBoolToKde (CCSSetting *setting,
int num)
{
KConfig *cfg = (specialOptions[num].global) ? cFiles->global : cFiles->kwin;
Bool val;
if (!ccsGetBool (setting, &val) )
return;
if (cfg->readBoolEntry (specialOptions[num].kdeName) != bool (val) )
{
cFiles->modified = true;
cfg->writeEntry (specialOptions[num].kdeName, bool (val) );
}
}
static void
CCSKeyToKde (CCSSetting *setting,
int num)
{
KConfig *cfg = (specialOptions[num].global) ? cFiles->global : cFiles->kwin;
CCSSettingKeyValue keyVal;
if (!ccsGetKey (setting, &keyVal) )
return;
int kde_keymod = 0;
if (keyVal.keyModMask & ShiftMask)
kde_keymod |= KKey::SHIFT;
if (keyVal.keyModMask & ControlMask)
kde_keymod |= KKey::CTRL;
if (keyVal.keyModMask & CompAltMask)
kde_keymod |= KKey::ALT;
if (keyVal.keyModMask & CompSuperMask)
kde_keymod |= KKey::WIN;
KKey key (keyVal.keysym, kde_keymod);
KKey akey (cfg->readEntry (specialOptions[num].kdeName) );
if (akey != key)
{
cFiles->modified = true;
cfg->writeEntry (specialOptions[num].kdeName, key.toString() );
}
}
static void
writeIntegratedOption (CCSSetting *setting)
{
int option = 0;
for (unsigned int i = 0; i < N_SOPTIONS; i++)
{
if (setting->name == specialOptions[i].settingName &&
QString (setting->parent->name) == specialOptions[i].pluginName)
{
option = i;
break;
}
}
switch (specialOptions[option].type)
{
case OptionInt:
CCSIntToKde (setting, option);
break;
case OptionBool:
CCSBoolToKde (setting, option);
break;
case OptionKey:
CCSKeyToKde (setting, option);
break;
case OptionSpecial:
if (specialOptions[option].settingName == "command11"
|| specialOptions[option].settingName == "unmaximize_window_key"
|| specialOptions[option].settingName == "maximize_window_key"
|| specialOptions[option].settingName == "maximize_window_horizontally_key"
|| specialOptions[option].settingName == "maximize_window_vertically_key")
break;
if (specialOptions[option].settingName == "click_to_focus")
{
QString mode = cFiles->kwin->readEntry ("FocusPolicy");
QString val = "ClickToFocus";
Bool bVal;
if (!ccsGetBool (setting, &bVal) )
break;
if (!bVal)
{
val = "FocusFollowsMouse";
}
if (mode != val)
{
cFiles->modified = true;
cFiles->kwin->writeEntry ("FocusPolicy", val);
}
}
if (specialOptions[option].settingName == "number_of_desktops")
{
cFiles->kwin->setGroup ("Desktops");
CCSIntToKde (setting, option);
cFiles->kwin->setGroup ("Windows");
}
if (specialOptions[option].settingName == "mode" &&
specialOptions[option].pluginName == "resize")
{
QString mode = cFiles->kwin->readEntry("ResizeMode");
QString val = "Opaque";
int iVal;
if (ccsGetInt(setting, &iVal) && (iVal == 1 || iVal == 2))
{
val = "Transparent";
}
if (mode != val)
{
cFiles->modified = true;
cFiles->kwin->writeEntry("ResizeMode",val);
}
cFiles->main->writeEntry(specialOptions[option].settingName + " (Integrated)",iVal);
}
if (specialOptions[option].settingName == "resistance_distance" ||
specialOptions[option].settingName == "edges_categories")
{
int *values, numValues;
CCSSettingValueList sList;
bool edge = false;
bool window = false;
int iVal = 0;
CCSSetting *edges = ccsFindSetting(setting->parent,
"edges_categories",
setting->isScreen,
setting->screenNum);
CCSSetting *dist = ccsFindSetting(setting->parent,
"resistance_distance",
setting->isScreen,
setting->screenNum);
if (!edges || !dist || !ccsGetList (edges, &sList) ||
!ccsGetInt(dist, &iVal))
break;
values = ccsGetIntArrayFromValueList (sList, &numValues);
for (int i = 0; i < numValues; i++)
{
if (values[i] == 0)
edge = true;
if (values[i] == 1)
window = true;
}
if (values)
free (values);
if (edge)
cFiles->kwin->writeEntry ("BorderSnapZone", iVal);
else
cFiles->kwin->writeEntry ("BorderSnapZone", 0);
if (window)
cFiles->kwin->writeEntry ("WindowSnapZone", iVal);
else
cFiles->kwin->writeEntry ("WindowSnapZone", 0);
if (window | edge)
cFiles->modified = true;
cFiles->main->writeEntry ("snap_distance (Integrated)",iVal);
}
else if (specialOptions[option].settingName == "next_key" ||
specialOptions[option].settingName == "prev_key")
{
CCSSettingKeyValue keyVal;
if (!ccsGetKey (setting, &keyVal))
break;
if (keyVal.keysym == 0 && keyVal.keyModMask == 0)
break;
CCSKeyToKde (setting, option);
cFiles->kwin->setGroup ("TabBox");
cFiles->kwin->writeEntry ("TraverseAll", false);
cFiles->kwin->setGroup ("Windows");
cFiles->kwin->writeEntry ("AltTabStyle", "KDE");
cFiles->modified = true;
}
else if (specialOptions[option].settingName == "next_all_key" ||
specialOptions[option].settingName == "prev_all_key")
{
CCSSettingKeyValue keyVal;
if (!ccsGetKey (setting, &keyVal))
break;
if (keyVal.keysym == 0 && keyVal.keyModMask == 0)
break;
CCSKeyToKde (setting, option);
cFiles->kwin->setGroup ("TabBox");
cFiles->kwin->writeEntry ("TraverseAll", true);
cFiles->kwin->setGroup ("Windows");
cFiles->kwin->writeEntry ("AltTabStyle", "KDE");
cFiles->modified = true;
}
else if (specialOptions[option].settingName == "next_no_popup_key" ||
specialOptions[option].settingName == "prev_no_popup_key")
{
CCSSettingKeyValue keyVal;
if (!ccsGetKey (setting, &keyVal))
break;
if (keyVal.keysym == 0 && keyVal.keyModMask == 0)
break;
CCSKeyToKde (setting, option);
cFiles->kwin->writeEntry ("AltTabStyle", "CDE");
cFiles->modified = true;
}
else if (specialOptions[option].settingName == "edge_flip_window" ||
specialOptions[option].settingName == "edgeflip_move")
{
int oVal = cFiles->kwin->readNumEntry ("ElectricBorders");
Bool val;
if (!ccsGetBool (setting, &val))
break;
if (val)
cFiles->kwin->writeEntry ("ElectricBorders", KMAX (1, oVal));
else
cFiles->kwin->writeEntry ("ElectricBorders", 0);
cFiles->modified = true;
}
else if (specialOptions[option].settingName == "edge_flip_pointer" ||
specialOptions[option].settingName == "edgeflip_pointer")
{
int oVal = 0;
Bool val, val2;
if (!ccsGetBool (setting, &val))
break;
CCSSetting *valSet = ccsFindSetting(setting->parent,
"edge_flip_window",
setting->isScreen,
setting->screenNum);
if (!valSet)
valSet = ccsFindSetting(setting->parent, "edgeflip_move",
setting->isScreen, setting->screenNum);
if (valSet && ccsGetBool (valSet, &val2))
{
if (val2)
oVal = 1;
}
else
oVal = 0;
if (val)
cFiles->kwin->writeEntry ("ElectricBorders", 2);
else
cFiles->kwin->writeEntry ("ElectricBorders", oVal);
cFiles->modified = true;
}
else if (specialOptions[option].settingName == "mode" &&
specialOptions[option].pluginName == "place")
{
int val;
if (!ccsGetInt (setting, &val))
break;
switch (val)
{
case 0:
cFiles->kwin->writeEntry ("Placement", "Cascade");
break;
case 1:
cFiles->kwin->writeEntry ("Placement", "Centered");
break;
case 2:
cFiles->kwin->writeEntry ("Placement", "Smart");
break;
case 3:
cFiles->kwin->writeEntry ("Placement", "Maximizing");
break;
case 4:
cFiles->kwin->writeEntry ("Placement", "Random");
break;
default:
break;
}
cFiles->modified = true;
}
break;
default:
break;
}
}
static void
writeSetting (CCSContext *c,
CCSSetting *setting)
{
KSimpleConfig *cfg = cFiles->main;
QString key (setting->name);
QString group (setting->parent->name);
if (setting->isScreen)
{
group += "_screen";
group += QString::number (setting->screenNum);
}
else
group += "_display";
cfg->setGroup (group);
if (ccsGetIntegrationEnabled (c) && isIntegratedOption (setting) )
{
writeIntegratedOption (setting);
return;
}
switch (setting->type)
{
case TypeString:
{
char * val;
if (ccsGetString (setting, &val) )
cfg->writeEntry (key, val);
}
break;
case TypeMatch:
{
char * val;
if (ccsGetMatch (setting, &val) )
cfg->writeEntry (key, val);
}
break;
case TypeFloat:
{
float val;
if (ccsGetFloat (setting, &val) )
cfg->writeEntry (key, val);
}
break;
case TypeInt:
{
int val;
if (ccsGetInt (setting, &val) )
cfg->writeEntry (key, val);
}
break;
case TypeBool:
{
Bool val;
if (ccsGetBool (setting, &val) )
cfg->writeEntry (key, bool (val) );
}
break;
case TypeColor:
{
CCSSettingColorValue color;
char tmp[256];
if (!ccsGetColor (setting, &color) )
break;
snprintf (tmp, 256, "#%.2x%.2x%.2x%.2x",
color.color.red / 256,
color.color.green/ 256,
color.color.blue / 256,
color.color.alpha / 256);
cfg->writeEntry (key, QString (tmp));
}
break;
case TypeList:
{
switch (setting->info.forList.listType)
{
case TypeBool:
{
QValueList<int> list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
list.append (l->data->value.asBool);
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
case TypeInt:
{
QValueList<int> list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
list.append (l->data->value.asInt);
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
case TypeString:
{
QStringList list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
list.append (l->data->value.asString);
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
case TypeMatch:
{
QStringList list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
list.append (l->data->value.asMatch);
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
case TypeFloat:
{
QStringList list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
list.append (QString::number (l->data->value.asFloat) );
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
case TypeColor:
{
QStringList list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
char tmp[256];
snprintf (tmp, 256, "#%.2x%.2x%.2x%.2x",
l->data->value.asColor.array.array[0] / 256,
l->data->value.asColor.array.array[1] / 256,
l->data->value.asColor.array.array[2] / 256,
l->data->value.asColor.array.array[3] / 256);
list.append (QString (tmp));
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
case TypeKey:
{
QStringList list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
QString str;
char *val;
val = ccsKeyBindingToString (&l->data->value.asKey);
str = val;
free (val);
list.append (str);
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
case TypeButton:
{
QStringList list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
QString str;
char *val;
val = ccsButtonBindingToString (
&l->data->value.asButton);
str = val;
free (val);
list.append (str);
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
case TypeEdge:
{
QStringList list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
QString str;
char *val;
val = ccsEdgesToString (l->data->value.asEdge);
str = val;
free (val);
list.append (str);
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
case TypeBell:
{
QValueList<int> list;
CCSSettingValueList l;
if (!ccsGetList (setting, &l) )
break;
while (l)
{
list.append (l->data->value.asBell);
l = l->next;
}
cfg->writeEntry (key, list);
}
break;
default:
break;
}
}
break;
case TypeKey:
{
CCSSettingKeyValue keyVal;
if (!ccsGetKey (setting, &keyVal))
break;
char *val = ccsKeyBindingToString (&keyVal);
cfg->writeEntry (key, val);
free (val);
}
break;
case TypeButton:
{
CCSSettingButtonValue buttonVal;
if (!ccsGetButton (setting, &buttonVal))
break;
char *val = ccsButtonBindingToString (&buttonVal);
cfg->writeEntry (key, val);
free (val);
}
break;
case TypeEdge:
{
unsigned int edges;
if (!ccsGetEdge (setting, &edges) )
break;
char *val = ccsEdgesToString (edges);
cfg->writeEntry (key, val);
free (val);
}
break;
case TypeBell:
{
Bool bell;
if (!ccsGetBell (setting, &bell))
break;
cfg->writeEntry (key, (bell)?true:false);
}
break;
default:
kdDebug () << "Not supported setting type : " << setting->type << endl;
break;
}
}
static Bool
readInit (CCSContext *c)
{
if (!instance)
instance = new KInstance ("ccs-backend-kconfig");
if (cFiles->profile != ccsGetProfile (c) )
{
QString configName ("compizrc");
if (ccsGetProfile (c) && strlen (ccsGetProfile (c) ) )
{
configName += ".";
configName += ccsGetProfile (c);
cFiles->profile = ccsGetProfile (c);
}
delete cFiles->main;
QString wFile = KGlobal::dirs()->saveLocation ("config",
QString::null, false) + configName;
createFile (wFile);
cFiles->main = new KSimpleConfig (configName);
ccsRemoveFileWatch (cFiles->watch);
cFiles->watch = ccsAddFileWatch (wFile.ascii(), TRUE,
reload, (void *) c);
}
return TRUE;
}
static void
readDone (CCSContext *)
{}
static Bool
writeInit (CCSContext *c)
{
if (!instance)
instance = new KInstance ("ccs-backend-kconfig");
if (cFiles->profile != ccsGetProfile (c) )
{
QString configName ("compizrc");
if (ccsGetProfile (c) && strlen (ccsGetProfile (c) ) )
{
configName += ".";
configName += ccsGetProfile (c);
cFiles->profile = ccsGetProfile (c);
}
delete cFiles->main;
QString wFile = KGlobal::dirs()->saveLocation ("config",
QString::null, false) + configName;
createFile (wFile);
cFiles->main = new KSimpleConfig (configName);
ccsRemoveFileWatch (cFiles->watch);
cFiles->watch = ccsAddFileWatch (wFile.ascii(), TRUE,
reload, (void *) c);
}
ccsDisableFileWatch (cFiles->watch);
ccsDisableFileWatch (cFiles->kwinWatch);
ccsDisableFileWatch (cFiles->globalWatch);
return TRUE;
}
static void
writeDone (CCSContext *)
{
cFiles->main->sync();
if (cFiles->modified)
{
cFiles->kwin->sync();
cFiles->global->sync();
DCOPClient *client = kapp->dcopClient();
if (!client->isAttached())
client->attach();
client->send("kwin", "KWinInterface", "reconfigure()", "");
cFiles->modified = false;
}
ccsEnableFileWatch (cFiles->watch);
ccsEnableFileWatch (cFiles->kwinWatch);
ccsEnableFileWatch (cFiles->globalWatch);
}
static Bool
init (CCSContext *c)
{
if (!instance)
instance = new KInstance ("ccs-backend-kconfig");
cFiles = new ConfigFiles;
QString configName ("compizrc");
if (ccsGetProfile (c) && strlen (ccsGetProfile (c) ) )
{
configName += ".";
configName += ccsGetProfile (c);
cFiles->profile = ccsGetProfile (c);
}
QString wFile = KGlobal::dirs()->saveLocation ("config",
QString::null, false) + configName;
createFile (wFile);
cFiles->main = new KSimpleConfig (configName);
cFiles->kwin = new KConfig ("kwinrc");
cFiles->global = new KConfig ("kdeglobals");
cFiles->kwin->setGroup ("Windows");
cFiles->global->setGroup ("Global Shortcuts");
cFiles->watch = ccsAddFileWatch (wFile.ascii(), TRUE, reload, (void *) c);
wFile = KGlobal::dirs()->saveLocation ("config",
QString::null, false) + "kwinrc";
cFiles->kwinWatch = ccsAddFileWatch (wFile.ascii(), TRUE, reload,
(void *) c);
wFile = KGlobal::dirs()->saveLocation ("config",
QString::null, false) + "kdeglobals";
cFiles->globalWatch = ccsAddFileWatch (wFile.ascii(), TRUE, reload,
(void *) c);
return TRUE;
}
static Bool
fini (CCSContext *)
{
if (cFiles)
{
ccsRemoveFileWatch (cFiles->watch);
ccsRemoveFileWatch (cFiles->kwinWatch);
ccsRemoveFileWatch (cFiles->globalWatch);
if (cFiles->main)
delete cFiles->main;
if (cFiles->kwin)
delete cFiles->kwin;
if (cFiles->global)
delete cFiles->global;
delete cFiles;
}
cFiles = NULL;
return TRUE;
}
static Bool
deleteProfile (CCSContext *,
char *profile)
{
QString file (KGlobal::dirs()->saveLocation ("config",
QString::null, false) );
file += "compizrc";
if (profile && strlen (profile) )
{
file += ".";
file += profile;
}
if (QFile::exists (file) )
return QFile::remove (file);
return FALSE;
}
static CCSBackendVTable kconfigVTable =
{
"kconfig",
"KDE Configuration Backend",
"KDE Configuration Backend for libccs",
true,
true,
0,
init,
fini,
readInit,
readSetting,
readDone,
writeInit,
writeSetting,
writeDone,
getSettingIsIntegrated,
getSettingIsReadOnly,
getExistingProfiles,
deleteProfile
};
extern "C"
{
CCSBackendVTable *
getBackendInfo (void)
{
return &kconfigVTable;
}
}