enlightenment/src/bin/e_xsettings.c

747 lines
18 KiB
C
Raw Normal View History

/* TODO
check http://www.pvv.org/~mariusbu/proposal.html
for advances in cross toolkit settings */
#include <e.h>
//#include <X11/Xlib.h>
//#include <X11/Xmd.h> /* For CARD16 */
// define here to avoid needing x includes directly.
#define C16 unsigned short
#define C32 unsigned int
#define RETRY_TIMEOUT 2.0
#define SETTING_TYPE_INT 0
#define SETTING_TYPE_STRING 1
#define SETTING_TYPE_COLOR 2
#define OFFSET_ADD(n) ((n + 4 - 1) & (~(4 - 1)))
typedef struct _Settings_Manager Settings_Manager;
typedef struct _Setting Setting;
struct _Settings_Manager
{
2020-11-29 05:30:24 -08:00
Ecore_X_Window selection;
Ecore_Timer *timer_retry;
unsigned long serial;
Ecore_X_Atom _atom_xsettings_screen;
Eina_Bool enabled E_BITFIELD;
};
struct _Setting
{
unsigned short type;
const char *name;
2020-11-29 05:30:24 -08:00
struct {
const char *value;
2020-11-29 05:30:24 -08:00
} s;
struct {
int value;
2020-11-29 05:30:24 -08:00
} i;
struct {
unsigned short red, green, blue, alpha;
2020-11-29 05:30:24 -08:00
} c;
unsigned long length;
unsigned long last_change;
};
static void _e_xsettings_apply(Settings_Manager *sm);
static Ecore_X_Atom _atom_manager = 0;
static Ecore_X_Atom _atom_xsettings = 0;
static Ecore_X_Atom _atom_gtk_iconthemes = 0;
static Ecore_X_Atom _atom_gtk_rcfiles = 0;
static Settings_Manager *manager = NULL;
static Eina_List *settings = NULL;
static Eina_Bool running = EINA_FALSE;
static Eio_File *eio_op = NULL;
static Eina_Bool setting = EINA_FALSE;
static Eina_Bool reset = EINA_FALSE;
static const char _setting_icon_theme_name[] = "Net/IconThemeName";
static const char _setting_theme_name[] = "Net/ThemeName";
static const char _setting_font_name[] = "Gtk/FontName";
static const char _setting_xft_dpi[] = "Xft/DPI";
static const char _setting_xft_antialias[] = "Xft/Antialias";
static const char _setting_xft_autohint[] = "Xft/Autohint";
static const char _setting_xft_hinting[] = "Xft/Hinting";
static const char _setting_xft_hintstyle[] = "Xft/HintStyle";
static const char _setting_xft_rgba[] = "Xft/RGBA";
static const char *_setting_theme = NULL;
static void _e_xsettings_done_cb(void *data, Eio_File *handler, const Eina_Stat *stat);
static Ecore_X_Atom
_e_xsettings_atom_screen_get(int screen_num)
{
char buf[32];
snprintf(buf, sizeof(buf), "_XSETTINGS_S%d", screen_num);
return ecore_x_atom_get(buf);
}
static Eina_Bool
_e_xsettings_selection_owner_set(void)
{
Ecore_X_Atom atom;
Ecore_X_Window cur_selection;
Eina_Bool ret;
atom = _e_xsettings_atom_screen_get(0);
ecore_x_selection_owner_set(e_comp->cm_selection, atom,
ecore_x_current_time_get());
ecore_x_sync();
cur_selection = ecore_x_selection_owner_get(atom);
ret = (cur_selection == e_comp->cm_selection);
if (!ret)
ERR("XSETTINGS: tried to set selection to %#x, but got %#x",
(unsigned int)e_comp->cm_selection, cur_selection);
return ret;
}
static void
_e_xsettings_deactivate(Settings_Manager *sm)
{
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
Ecore_X_Atom atom;
atom = _e_xsettings_atom_screen_get(0);
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
ecore_x_selection_owner_set(0, atom, ecore_x_current_time_get());
ecore_x_sync();
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
sm->enabled = 0;
}
static Eina_Bool
_e_xsettings_activate(Settings_Manager *sm)
{
Ecore_X_Atom atom;
Ecore_X_Window old_win;
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
if (sm->enabled) return 1;
atom = _e_xsettings_atom_screen_get(0);
old_win = ecore_x_selection_owner_get(atom);
if (old_win != 0) return 0;
if (!_e_xsettings_selection_owner_set())
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
return 0;
ecore_x_client_message32_send(e_comp->root, _atom_manager,
ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
ecore_x_current_time_get(), atom,
e_comp->cm_selection, 0, 0);
if (settings) _e_xsettings_apply(sm);
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
sm->enabled = 1;
return 1;
}
static Eina_Bool
_e_xsettings_activate_retry(void *data)
{
Settings_Manager *sm = data;
Eina_Bool ret;
INF("XSETTINGS: reactivate...");
ret = _e_xsettings_activate(sm);
if (ret)
INF("XSETTINGS: activate success!");
else
ERR("XSETTINGS: activate failure! retrying in %0.1f seconds", RETRY_TIMEOUT);
if (!ret)
return ECORE_CALLBACK_RENEW;
sm->timer_retry = NULL;
return ECORE_CALLBACK_CANCEL;
}
static void
_e_xsettings_retry(Settings_Manager *sm)
{
if (sm->timer_retry) return;
sm->timer_retry = ecore_timer_loop_add
(RETRY_TIMEOUT, _e_xsettings_activate_retry, sm);
}
static void
_e_xsettings_string_set(const char *name, const char *value)
{
Setting *s;
Eina_List *l;
if (!name) return;
if (name == _setting_theme_name)
e_config->xsettings.net_theme_name_detected = value;
name = eina_stringshare_add(name);
EINA_LIST_FOREACH(settings, l, s)
{
if (s->type != SETTING_TYPE_STRING) continue;
if (s->name == name) break;
}
if (!value)
{
if (!s) return;
DBG("remove %s\n", name);
eina_stringshare_del(name);
eina_stringshare_del(s->name);
eina_stringshare_del(s->s.value);
settings = eina_list_remove(settings, s);
E_FREE(s);
return;
}
if (s)
{
DBG("update %s %s\n", name, value);
eina_stringshare_del(name);
eina_stringshare_replace(&s->s.value, value);
}
else
{
DBG("add %s %s\n", name, value);
s = E_NEW(Setting, 1);
s->type = SETTING_TYPE_STRING;
s->name = name;
s->s.value = eina_stringshare_add(value);
settings = eina_list_append(settings, s);
}
/* type + pad + name-len + last-change-serial + str_len */
s->length = 12;
s->length += OFFSET_ADD(strlen(name));
s->length += OFFSET_ADD(strlen(value));
s->last_change = ecore_x_current_time_get();
}
static void
_e_xsettings_int_set(const char *name, int value, Eina_Bool set)
{
Setting *s;
Eina_List *l;
if (!name) return;
name = eina_stringshare_add(name);
EINA_LIST_FOREACH(settings, l, s)
{
if (s->type != SETTING_TYPE_INT) continue;
if (s->name == name) break;
}
if (!set)
{
if (!s) return;
DBG("remove %s\n", name);
eina_stringshare_del(name);
eina_stringshare_del(s->name);
settings = eina_list_remove(settings, s);
E_FREE(s);
return;
}
if (s)
{
DBG("update %s %d\n", name, value);
eina_stringshare_del(name);
s->i.value = value;
}
else
{
DBG("add %s %d\n", name, value);
s = E_NEW(Setting, 1);
s->type = SETTING_TYPE_INT;
s->name = name;
s->i.value = value;
settings = eina_list_append(settings, s);
}
2011-10-05 02:37:59 -07:00
// type + pad + name-len + last-change-serial + value
s->length = 12;
s->length += OFFSET_ADD(strlen(name));
}
static unsigned char *
_e_xsettings_copy(unsigned char *buffer, Setting *s)
{
size_t str_len;
size_t len;
C16 tmp16;
C32 tmp32;
buffer[0] = s->type;
buffer[1] = 0;
buffer += 2;
str_len = strlen(s->name);
tmp16 = str_len;
memcpy(buffer, &tmp16, sizeof(C16));
buffer += 2;
memcpy(buffer, s->name, str_len);
buffer += str_len;
len = OFFSET_ADD(str_len) - str_len;
memset(buffer, 0, len);
buffer += len;
tmp32 = s->last_change;
memcpy(buffer, &tmp32, sizeof(C32));
buffer += 4;
switch (s->type)
{
case SETTING_TYPE_INT:
tmp32 = s->i.value;
memcpy(buffer, &tmp32, sizeof(C32));
buffer += 4;
break;
case SETTING_TYPE_STRING:
str_len = strlen(s->s.value);
tmp32 = str_len;
memcpy(buffer, &tmp32, sizeof(C32));
buffer += 4;
memcpy(buffer, s->s.value, str_len);
buffer += str_len;
len = OFFSET_ADD(str_len) - str_len;
memset(buffer, 0, len);
buffer += len;
break;
case SETTING_TYPE_COLOR:
tmp16 = s->c.red;
memcpy(buffer, &tmp16, sizeof(C16));
buffer += 2;
tmp16 = s->c.green;
memcpy(buffer, &tmp16, sizeof(C16));
buffer += 2;
tmp16 = s->c.blue;
memcpy(buffer, &tmp16, sizeof(C16));
buffer += 2;
tmp16 = s->c.alpha;
memcpy(buffer, &tmp16, sizeof(C16));
buffer += 2;
break;
}
return buffer;
}
static void
_e_xsettings_apply(Settings_Manager *sm)
{
unsigned char *data;
unsigned char *pos;
size_t len = 12;
Setting *s;
Eina_List *l;
C32 tmp32;
EINA_LIST_FOREACH(settings, l, s)
len += s->length;
pos = data = calloc(1, len);
if (!data) return;
#if (defined __BYTE_ORDER && __BYTE_ORDER == __LITTLE_ENDIAN) || (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
*pos = 0; //LSBFirst
#else
*pos = 1; //MSBFirst
#endif
pos += 4;
tmp32 = sm->serial++;
memcpy(pos, &tmp32, sizeof(C32));
pos += 4;
tmp32 = eina_list_count(settings);
memcpy(pos, &tmp32, sizeof(C32));
pos += 4;
EINA_LIST_FOREACH(settings, l, s)
pos = _e_xsettings_copy(pos, s);
ecore_x_window_prop_property_set(e_comp->cm_selection,
_atom_xsettings,
_atom_xsettings,
8, data, len);
free(data);
}
static void
_e_xsettings_update(void)
{
if (e_comp->cm_selection) _e_xsettings_apply(manager);
}
static void
_e_xsettings_gtk_icon_update(void)
{
const Eina_List *l;
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
E_Client *ec;
EINA_LIST_FOREACH(e_comp->clients, l, ec)
if (ec->icccm.state)
ecore_x_client_message8_send(e_client_util_win_get(ec),
_atom_gtk_iconthemes, NULL, 0);
}
static void
_e_xsettings_gtk_rcfiles_update(void)
{
const Eina_List *l;
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
E_Client *ec;
EINA_LIST_FOREACH(e_comp->clients, l, ec)
if (ec->icccm.state)
ecore_x_client_message8_send(e_client_util_win_get(ec),
_atom_gtk_rcfiles, NULL, 0);
}
static void
_e_xsettings_icon_theme_set(void)
{
if (e_config->xsettings.match_e17_icon_theme)
{
_e_xsettings_string_set(_setting_icon_theme_name,
e_config->icon_theme);
return;
}
if (e_config->xsettings.net_icon_theme_name)
{
_e_xsettings_string_set(_setting_icon_theme_name,
e_config->xsettings.net_icon_theme_name);
return;
}
_e_xsettings_string_set(_setting_icon_theme_name, NULL);
}
static void
_e_xsettings_error_cb(void *data, Eio_File *handler EINA_UNUSED, int error EINA_UNUSED)
{
Eina_List *l = data;
if (reset || setting)
{
char buf[PATH_MAX];
if (reset || (!l)) l = efreet_data_dirs_get();
else if (l)
l = l->next;
reset = EINA_FALSE;
if (l)
{
snprintf(buf, sizeof(buf), "%s/themes/%s",
(char *)eina_list_data_get(l), _setting_theme);
eio_op = eio_file_direct_stat(buf, _e_xsettings_done_cb,
_e_xsettings_error_cb, l);
return;
}
}
eio_op = NULL;
setting = EINA_FALSE;
_setting_theme = NULL;
if (e_config->xsettings.net_theme_name)
_e_xsettings_string_set(_setting_theme_name,
e_config->xsettings.net_theme_name);
else
_e_xsettings_string_set(_setting_theme_name, NULL);
_e_xsettings_update();
}
static void
_e_xsettings_done_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, const Eina_Stat *estat EINA_UNUSED)
{
if (reset)
{
/* should not happen */
_e_xsettings_error_cb(NULL, NULL, 0);
return;
}
_e_xsettings_string_set(_setting_theme_name, _setting_theme);
_setting_theme = NULL;
eio_op = NULL;
setting = EINA_FALSE;
_e_xsettings_update();
}
static void
_e_xsettings_theme_set(void)
{
if (e_config->xsettings.match_e17_theme)
{
const char *file;
file = e_theme_edje_file_get(NULL, "e/desktop/background");
if (file)
{
if ((_setting_theme = edje_file_data_get(file, "gtk-theme")))
{
char buf[PATH_MAX];
e_user_homedir_snprintf(buf, sizeof(buf),
".themes/%s", _setting_theme);
eio_op = eio_file_direct_stat(buf, _e_xsettings_done_cb,
_e_xsettings_error_cb, NULL);
setting = EINA_TRUE;
return;
}
}
}
if (e_config->xsettings.net_theme_name)
{
_e_xsettings_string_set(_setting_theme_name,
e_config->xsettings.net_theme_name);
return;
}
_e_xsettings_string_set(_setting_theme_name, NULL);
}
static int
_dbl_to_str(char *buf, size_t buf_size, double val, int decimals)
{
int ival;
size_t l = 0;
if (val < 0)
{
if (buf_size < 2) return -1;
val = -val;
buf[0] = '-';
buf[1] = 0;
l++;
}
ival = val;
snprintf(buf + l, buf_size - l, "%i", ival);
if (decimals <= 0) return 0;
l = strlen(buf);
if (l >= (buf_size - 2)) return -1;
buf[l] = '.';
buf[l + 1] = 0;
l++;
while (decimals > 0)
{
if (l >= (buf_size - 1)) return -1;
val *= 10.0;
ival = val;
val = val - ival;
buf[l] = '0' + (ival % 10);
buf[l + 1] = 0;
l++;
if (l >= (buf_size - 1)) return -1;
decimals--;
}
return 0;
}
static void
_e_xsettings_font_set(void)
{
E_Font_Default *efd;
E_Font_Properties *efp;
efd = e_font_default_get("application");
if (efd && efd->font)
{
efp = e_font_fontconfig_name_parse(efd->font);
if (efp->name)
{
Eina_Strbuf *buf;
Eina_List *l;
int size = efd->size;
char size_buf[32];
const char *p;
/* TODO better way to convert evas font sizes? */
if (!size) size = 10; // default if not set
else if (size < 0) size /= -10; // in 1/10th units
// limit sizes
if (size < 5) size = 5; // don't allow too small
else if (size > 100) size = 100; // don't allow silly sizes
_dbl_to_str(size_buf, sizeof(size_buf), (double)size, 0);
buf = eina_strbuf_new();
eina_strbuf_append(buf, efp->name);
eina_strbuf_append_char(buf, ' ');
EINA_LIST_FOREACH(efp->styles, l, p)
{
eina_strbuf_append(buf, p);
eina_strbuf_append_char(buf, ' ');
}
eina_strbuf_append(buf, size_buf);
_e_xsettings_string_set(_setting_font_name,
eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
e_font_properties_free(efp);
return;
}
e_font_properties_free(efp);
}
_e_xsettings_string_set(_setting_font_name, NULL);
}
static void
_e_xsettings_dpi_set(void)
{
if (e_config->scale.set_xapp_dpi)
_e_xsettings_int_set(_setting_xft_dpi,
(double)e_config->scale.xapp_base_dpi * e_scale * 1024.0,
EINA_TRUE);
_e_xsettings_int_set(_setting_xft_antialias,
1,
EINA_TRUE);
_e_xsettings_int_set(_setting_xft_hinting,
1,
EINA_TRUE);
_e_xsettings_int_set(_setting_xft_autohint,
0,
EINA_TRUE);
_e_xsettings_string_set(_setting_xft_hintstyle,
"hintfull");
_e_xsettings_string_set(_setting_xft_rgba,
"none");
}
static void
_e_xsettings_cursor_path_set(void)
{
struct stat st;
char buf[PATH_MAX], env[PATH_MAX + PATH_MAX + 100], *path;
e_user_homedir_concat_static(buf, ".icons");
if (stat(buf, &st)) return;
path = getenv("XCURSOR_PATH");
if (path)
{
if (strstr(path, buf)) return;
snprintf(env, sizeof(env), "%s:%s", buf, path);
path = env;
}
else
{
snprintf(env, sizeof(env), "%s:%s", buf, "/usr/share/icons");
path = env;
}
e_env_set("XCURSOR_PATH", path);
}
static void
_e_xsettings_start(void)
{
if (running) return;
_e_xsettings_dpi_set();
_e_xsettings_theme_set();
_e_xsettings_icon_theme_set();
_e_xsettings_font_set();
_e_xsettings_cursor_path_set();
manager = E_NEW(Settings_Manager, 1);
if (!_e_xsettings_activate(manager))
_e_xsettings_retry(manager);
running = EINA_TRUE;
}
static void
_e_xsettings_stop(void)
{
Setting *s;
if (!running) return;
if (manager->timer_retry)
ecore_timer_del(manager->timer_retry);
if ((!stopping) && (!x_fatal))
_e_xsettings_deactivate(manager);
E_FREE(manager);
EINA_LIST_FREE(settings, s)
{
if (s->name) eina_stringshare_del(s->name);
if (s->s.value) eina_stringshare_del(s->s.value);
E_FREE(s);
}
running = EINA_FALSE;
}
EINTERN int
e_xsettings_init(void)
{
_atom_manager = ecore_x_atom_get("MANAGER");
_atom_xsettings = ecore_x_atom_get("_XSETTINGS_SETTINGS");
_atom_gtk_iconthemes = ecore_x_atom_get("_GTK_LOAD_ICONTHEMES");
_atom_gtk_rcfiles = ecore_x_atom_get("_GTK_READ_RCFILES");
if (e_config->xsettings.enabled)
{
_e_xsettings_start();
if (!getenv("E_RESTART"))
_e_xsettings_gtk_rcfiles_update();
}
return 1;
}
EINTERN int
e_xsettings_shutdown(void)
{
_e_xsettings_stop();
if (eio_op) eio_file_cancel(eio_op);
eio_op = NULL;
setting = EINA_FALSE;
return 1;
}
static void
_update_sequence(void)
{
_e_xsettings_dpi_set();
_e_xsettings_theme_set();
_e_xsettings_icon_theme_set();
_e_xsettings_font_set();
_e_xsettings_update();
_e_xsettings_gtk_icon_update();
}
E_API void
e_xsettings_config_update(void)
{
if (!_atom_manager) return;
setting = EINA_FALSE;
if (eio_op) eio_file_cancel(eio_op);
if (!e_config->xsettings.enabled)
{
_e_xsettings_stop();
return;
}
if (!running)
{
_e_xsettings_start();
}
else
{
_update_sequence();
reset = EINA_TRUE;
}
}