mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
Added support for xrdb
This commit is contained in:
parent
3a0c4b31ce
commit
c0ee6c1750
158
evoke/Xsm.cpp
158
evoke/Xsm.cpp
@ -14,19 +14,172 @@
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/TiXml.h>
|
||||
#include <edelib/File.h>
|
||||
#include <edelib/Color.h>
|
||||
#include <edelib/String.h>
|
||||
#include <edelib/Util.h>
|
||||
#include <edelib/Directory.h>
|
||||
#include <edelib/XSettingsCommon.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <FL/x.h>
|
||||
|
||||
#include <X11/Xresource.h>
|
||||
|
||||
#define USER_XRESOURCE ".Xdefaults"
|
||||
#define USER_XRESOURCE_TMP ".Xdefaults-tmp"
|
||||
#define USER_XRESOURCE_SAVED ".Xdefaults-ede-saved"
|
||||
|
||||
struct ResourceMap {
|
||||
char* name;
|
||||
char* xresource_key;
|
||||
char* xresource_klass;
|
||||
};
|
||||
|
||||
/*
|
||||
* Make sure xresource_klass with '*' is listed last since it have
|
||||
* highest priority and will override all previous classes (X Resource class, not C++ one :P)
|
||||
* with the same xresource_key.
|
||||
*/
|
||||
ResourceMap resource_map [] = {
|
||||
{ "Fltk/Background2", "background", "*Text" },
|
||||
{ "Fltk/Background", "background", "*" },
|
||||
{ "Fltk/Foreground", "foreground", "*" }
|
||||
};
|
||||
|
||||
#define RESOURCE_MAP_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
int ignore_xerrors(Display* display, XErrorEvent* xev) {
|
||||
return True;
|
||||
}
|
||||
|
||||
Xsm::Xsm() { }
|
||||
Xsm::Xsm() {
|
||||
}
|
||||
|
||||
Xsm::~Xsm() {
|
||||
EDEBUG("Xsm::~Xsm()\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a short explaination how evoke's XSETTINGS part is combined
|
||||
* with X Resource database (xrdb). First of all, why mess with this? Almost
|
||||
* all pure X apps (xterm, xedit, rxvt) reads color (and more) from xrdb, not to say
|
||||
* that FLTK apps do that too, at least those not linked with edelib::Window. On other
|
||||
* hand since edelib::Window already have builtin XSETTINGS and FLTK backend, you will
|
||||
* that colors for edelib::Window will be specified twice, but this is not a big deal
|
||||
* since painting is done only once.
|
||||
*
|
||||
* Here, in the code, we look for XSETTINGS names listed in resource_map[] and they should
|
||||
* be colors only; when they are found, their equivalents will be created in xrdb as class/key
|
||||
* (see X Resource manual about these).
|
||||
*
|
||||
* Values picked up from XSETTINGS color items will be converted to html since because clients
|
||||
* who reads xrdb expects html colors (or X11 ones, like red/green/blue names, but let we not
|
||||
* complicate). After conversion, everything is stored in ~/.Xdefaults file. If this file
|
||||
* already exists (someone else made it), it will be first merged, picking old values and backed up.
|
||||
*
|
||||
* After evoke quits, file is restored, if existed before or deleted if not. This is also a
|
||||
* workaround for missing functions to delete key/value pairs from xrdb (what was they thinking for??).
|
||||
*/
|
||||
void Xsm::xresource_replace(void) {
|
||||
// with inheritance we got manager_data
|
||||
if(!manager_data->settings)
|
||||
return;
|
||||
|
||||
edelib::String home = edelib::dir_home();
|
||||
|
||||
// try to open ~/.Xdefaults; if failed, X Resource will not complain
|
||||
edelib::String db_file = edelib::build_filename("/", home.c_str(), USER_XRESOURCE);
|
||||
|
||||
// initialize XResource
|
||||
XrmInitialize();
|
||||
// load XResource database
|
||||
XrmDatabase db = XrmGetFileDatabase(db_file.c_str());
|
||||
|
||||
edelib::XSettingsSetting* s;
|
||||
int status;
|
||||
char* type, *value;
|
||||
XrmValue xrmv;
|
||||
char color_val[8];
|
||||
|
||||
edelib::String tmp;
|
||||
|
||||
/*
|
||||
* XSETTINGS does not contains duplicate entries so there is no need to
|
||||
* check for them. We only scan ResourceMap table for XSETTINGS name and
|
||||
* its X Resource equivalent.
|
||||
*/
|
||||
for(unsigned int i = 0; i < RESOURCE_MAP_SIZE(resource_map); i++) {
|
||||
s = edelib::xsettings_list_find(manager_data->settings, resource_map[i].name);
|
||||
if(!s)
|
||||
continue;
|
||||
|
||||
// assure that XSETTINGS key is color type
|
||||
if(s->type != edelib::XSETTINGS_TYPE_COLOR) {
|
||||
EWARNING(ESTRLOC ": Expected color type in %s, but it is not, skipping...\n", s->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if resource is present
|
||||
status = XrmGetResource(db, resource_map[i].xresource_key, resource_map[i].xresource_klass, &type, &xrmv);
|
||||
|
||||
if(status && strcmp(type, "String") == 0) {
|
||||
EDEBUG(ESTRLOC ": %s.%s found in database\n",
|
||||
resource_map[i].xresource_klass, resource_map[i].xresource_key);
|
||||
|
||||
value = xrmv.addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now convert color from XSETTINGS to html value. First convert to fltk color.
|
||||
* TODO: Strange, didn't implemented something like color_rgb_to_html in edelib ?
|
||||
*/
|
||||
int fltk_color = edelib::color_rgb_to_fltk(s->data.v_color.red, s->data.v_color.green, s->data.v_color.blue);
|
||||
edelib::color_fltk_to_html(fltk_color, color_val);
|
||||
|
||||
// and save it
|
||||
tmp.clear();
|
||||
tmp.printf("%s.%s: %s", resource_map[i].xresource_klass, resource_map[i].xresource_key, color_val);
|
||||
XrmPutLineResource(&db, tmp.c_str());
|
||||
}
|
||||
|
||||
edelib::String tmp_db_file = edelib::build_filename("/", home.c_str(), USER_XRESOURCE_TMP);
|
||||
|
||||
/*
|
||||
* Try to merge existing ~/.Xdefaults (if present) with our changes. If there is existing
|
||||
* key/values, they will be replaced with our. If XrmCombineFileDatabase() fails, this means
|
||||
* there is no ~/.Xdefaults, so we don't need to backup it; opposite, backup it before we do
|
||||
* final rename.
|
||||
*/
|
||||
status = XrmCombineFileDatabase(db_file.c_str(), &db, 0);
|
||||
XrmPutFileDatabase(db, tmp_db_file.c_str());
|
||||
//XrmSetDatabase(fl_display, db);
|
||||
XrmDestroyDatabase(db);
|
||||
if(status) {
|
||||
edelib::String db_backup = edelib::build_filename("/", home.c_str(), USER_XRESOURCE_SAVED);
|
||||
edelib::file_rename(db_file.c_str(), db_backup.c_str());
|
||||
}
|
||||
|
||||
edelib::file_rename(tmp_db_file.c_str(), db_file.c_str());
|
||||
}
|
||||
|
||||
void Xsm::xresource_undo(void) {
|
||||
edelib::String home, db_file_backup, db_file;
|
||||
|
||||
home = edelib::dir_home();
|
||||
db_file_backup = edelib::build_filename("/", home.c_str(), USER_XRESOURCE_SAVED);
|
||||
db_file = edelib::build_filename("/", home.c_str(), USER_XRESOURCE);
|
||||
|
||||
/*
|
||||
* If we have backup, restore it; otherwise delete ~/.Xdefaults.
|
||||
* TODO: what if user something write in it? Changes will be lost...
|
||||
*/
|
||||
if(edelib::file_exists(db_file_backup.c_str()))
|
||||
edelib::file_rename(db_file_backup.c_str(), db_file.c_str());
|
||||
else
|
||||
edelib::file_remove(db_file.c_str());
|
||||
}
|
||||
|
||||
bool Xsm::load_serialized(const char* file) {
|
||||
TiXmlDocument doc(file);
|
||||
if(!doc.LoadFile())
|
||||
@ -96,6 +249,7 @@ bool Xsm::load_serialized(const char* file) {
|
||||
}
|
||||
}
|
||||
|
||||
xresource_replace();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -169,5 +323,7 @@ bool Xsm::save_serialized(const char* file) {
|
||||
setting_file.close();
|
||||
edelib::xsettings_list_free(settings);
|
||||
|
||||
xresource_undo();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
/*
|
||||
* XSETTINGS manager with serialization capability.
|
||||
* Also it will write/undo to xrdb (X Resource database).
|
||||
*/
|
||||
class Xsm : public edelib::XSettingsManager {
|
||||
public:
|
||||
@ -24,6 +25,11 @@ class Xsm : public edelib::XSettingsManager {
|
||||
~Xsm();
|
||||
bool load_serialized(const char* file);
|
||||
bool save_serialized(const char* file);
|
||||
|
||||
// replace XResource values from one from XSETTINGS
|
||||
void xresource_replace(void);
|
||||
// undo old XResource values
|
||||
void xresource_undo(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user