Finished manager part of XSETTINGS. Left to be done is to implement the same for the clients ;)

This commit is contained in:
Sanel Zukan 2007-09-19 14:12:34 +00:00
parent 04a87a7f7c
commit 762ad9883d
3 changed files with 287 additions and 9 deletions

View File

@ -454,6 +454,16 @@ do_it:
edelib::alert(_("Unable to load XSETTINGS manager properly"));
stop_xsettings_manager();
}
if(!xsm) return;
/* testing code
* FIXME: move this to outside client
*/
xsm->set_int("Net/DoubleClickTime", 234);
xsm->set_color("Net/Background/Normal", 34, 45, 23, 0);
xsm->set_string("Net/UserName", "John Foo");
xsm->notify();
}
void EvokeService::stop_xsettings_manager(void) {

View File

@ -11,17 +11,36 @@
*/
#include "Xsm.h"
#include <edelib/Debug.h>
#include <edelib/List.h>
#include <FL/x.h>
#include <stdio.h> // snprintf
#include <X11/Xmd.h> // CARD16, CARD32
#include <stdio.h> // snprintf
#include <stdlib.h> // free
#include <string.h> // strdup, strcmp
#define XSETTINGS_PAD(n, p) ((n + p - 1) & (~(p - 1)))
typedef edelib::list<XsettingsSetting*> XsettingsList;
typedef edelib::list<XsettingsSetting*>::iterator XsettingsListIter;
struct XsmData {
Window window;
Atom manager_atom;
Atom selection_atom;
Atom xsettings_atom;
unsigned long serial;
XsettingsList list;
};
struct XsettingsBuffer {
unsigned char* content;
unsigned char* pos;
int len;
};
struct XsettingsColor {
@ -38,7 +57,7 @@ struct XsettingsSetting {
XsettingsColor v_color;
} data;
unsigned long last_changed_serial;
unsigned long last_change_serial;
};
struct TimeStampInfo {
@ -75,12 +94,121 @@ Time get_server_time(Display* dpy, Window win) {
return xev.xproperty.time;
}
char settings_byte_order(void) {
CARD32 myint = 0x01020304;
return (*(char*)&myint == 1) ? MSBFirst : LSBFirst;
}
bool settings_equal(const XsettingsSetting* s1, const XsettingsSetting* s2) {
EASSERT(s1 != NULL && s2 != NULL);
if(s1->type != s2->type)
return false;
if(strcmp(s1->name, s2->name) != 0)
return false;
switch(s1->type) {
case XS_TYPE_INT:
return s1->data.v_int == s2->data.v_int;
case XS_TYPE_COLOR:
return (s1->data.v_color.red == s2->data.v_color.red) &&
(s1->data.v_color.green == s2->data.v_color.green) &&
(s1->data.v_color.blue == s2->data.v_color.blue) &&
(s1->data.v_color.alpha == s2->data.v_color.alpha);
case XS_TYPE_STRING:
return (strcmp(s1->data.v_string, s2->data.v_string) == 0);
}
return false;
}
int setting_len(const XsettingsSetting* setting) {
int len = 8; // type + pad + name-len + last-change-serial
len += XSETTINGS_PAD(strlen(setting->name), 4);
switch(setting->type) {
case XS_TYPE_INT:
len += 4;
break;
case XS_TYPE_COLOR:
len += 8;
break;
case XS_TYPE_STRING:
len += 4 + XSETTINGS_PAD(strlen(setting->data.v_string), 4);
break;
}
return len;
}
void setting_store(const XsettingsSetting* setting, XsettingsBuffer* buffer) {
int len, str_len;
*(buffer->pos++) = setting->type;
*(buffer->pos++) = 0;
str_len = strlen(setting->name);
*(CARD16*)(buffer->pos) = str_len;
buffer->pos += 2;
len = XSETTINGS_PAD(str_len, 4);
memcpy(buffer->pos, setting->name, str_len);
len -= str_len;
buffer->pos += str_len;
for(; len > 0; len--)
*(buffer->pos++) = 0;
*(CARD32*)(buffer->pos) = setting->last_change_serial;
buffer->pos += 4;
switch(setting->type) {
case XS_TYPE_INT:
*(CARD32*)(buffer->pos) = setting->data.v_int;
buffer->pos += 4;
break;
case XS_TYPE_COLOR:
*(CARD16*)(buffer->pos) = setting->data.v_color.red;
*(CARD16*)(buffer->pos + 2) = setting->data.v_color.green;
*(CARD16*)(buffer->pos + 4) = setting->data.v_color.blue;
*(CARD16*)(buffer->pos + 6) = setting->data.v_color.alpha;
buffer->pos += 8;
break;
case XS_TYPE_STRING:
str_len = strlen(setting->data.v_string);
*(CARD32*)(buffer->pos) = str_len;
buffer->pos += 4;
len = XSETTINGS_PAD(str_len, 4);
memcpy(buffer->pos, setting->data.v_string, str_len);
len -= str_len;
buffer->pos += str_len;
for(; len > 0; len--)
*(buffer->pos++) = 0;
break;
}
}
Xsm::Xsm() : data(NULL) { }
Xsm::~Xsm() {
if(data) {
XDestroyWindow(fl_display, data->window);
XsettingsList& lst = data->list;
if(!lst.empty()) {
XsettingsListIter it = lst.begin(), it_end = lst.end();
for(; it != it_end; ++it)
delete_setting(*it);
lst.clear();
}
delete data;
}
@ -151,3 +279,130 @@ bool Xsm::should_quit(const XEvent* xev) {
return false;
}
void Xsm::set_setting(const XsettingsSetting* setting) {
EASSERT(data != NULL);
XsettingsList& lst = data->list;
XsettingsListIter it = lst.begin(), it_end = lst.end();
/*
* Check if entry already exists. If setting with the same
* name already exists, but with different values, that setting
* will be completely replaced with new one.
*/
for(; it != it_end; ++it) {
if(strcmp((*it)->name, setting->name) == 0) {
if(settings_equal((*it), setting)) {
return;
} else {
delete_setting(*it);
lst.erase(it);
break;
}
}
}
XsettingsSetting* new_setting = new XsettingsSetting;
new_setting->name = strdup(setting->name);
//new_setting->last_change_serial = setting->last_change_serial;
new_setting->type = setting->type;
switch(new_setting->type) {
case XS_TYPE_INT:
new_setting->data.v_int = setting->data.v_int;
break;
case XS_TYPE_COLOR:
new_setting->data.v_color.red = setting->data.v_color.red;
new_setting->data.v_color.green = setting->data.v_color.green;
new_setting->data.v_color.blue = setting->data.v_color.blue;
new_setting->data.v_color.alpha = setting->data.v_color.alpha;
break;
case XS_TYPE_STRING:
new_setting->data.v_string = strdup(setting->data.v_string);
break;
}
new_setting->last_change_serial = data->serial;
lst.push_back(new_setting);
}
void Xsm::delete_setting(XsettingsSetting* setting) {
if(!setting)
return;
if(setting->type == XS_TYPE_STRING)
free(setting->data.v_string);
free(setting->name);
delete setting;
setting = NULL;
}
void Xsm::set_int(const char* name, int val) {
XsettingsSetting setting;
setting.name = (char*)name;
setting.type = XS_TYPE_INT;
setting.data.v_int = val;
set_setting(&setting);
}
void Xsm::set_color(const char* name, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha) {
XsettingsSetting setting;
setting.name = (char*)name;
setting.type = XS_TYPE_COLOR;
setting.data.v_color.red = red;
setting.data.v_color.green = green;
setting.data.v_color.blue = blue;
setting.data.v_color.alpha = alpha;
set_setting(&setting);
}
void Xsm::set_string(const char* name, const char* str) {
XsettingsSetting setting;
setting.name = (char*)name;
setting.type = XS_TYPE_STRING;
setting.data.v_string = (char*)str;
set_setting(&setting);
}
void Xsm::notify(void) {
EASSERT(data != NULL);
int n_settings = 0;
XsettingsBuffer buff;
buff.len = 12; // byte-order + pad + SERIAL + N_SETTINGS
XsettingsList& lst = data->list;
XsettingsListIter it = lst.begin(), it_end = lst.end();
for(; it != it_end; ++it) {
buff.len += setting_len(*it);
n_settings++;
}
buff.content = new unsigned char[buff.len];
buff.pos = buff.content;
*buff.pos = settings_byte_order();
buff.pos += 4;
*(CARD32*)buff.pos = data->serial++;
buff.pos += 4;
*(CARD32*)buff.pos = n_settings;
buff.pos += 4;
for(it = lst.begin(); it != it_end; ++it)
setting_store(*it, &buff);
XChangeProperty(fl_display, data->window, data->xsettings_atom, data->xsettings_atom,
8, PropModeReplace, buff.content, buff.len);
delete [] buff.content;
}

View File

@ -29,18 +29,25 @@
* Author of referent implementation is Owen Taylor.
*/
enum XsettingsType {
XS_TYPE_INT = 0,
XS_TYPE_COLOR,
XS_TYPE_STRING
};
struct XsmData;
struct XsettingsSetting;
struct XsettingsBuffer;
/*
* Enum order must be exact on client side too, since via these values
* client will try to decode settings.
*/
enum XsettingsType {
XS_TYPE_INT = 0,
XS_TYPE_STRING,
XS_TYPE_COLOR
};
class Xsm {
private:
XsmData* data;
void set_setting(const XsettingsSetting* setting);
void delete_setting(XsettingsSetting* setting);
public:
Xsm();
@ -48,6 +55,12 @@ class Xsm {
bool is_running(void);
bool init(void);
bool should_quit(const XEvent* xev);
void set_int(const char* name, int val);
void set_color(const char* name,
unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha);
void set_string(const char* name, const char* str);
void notify(void);
};
#endif