gnome-control-center/gnome-settings-daemon/gnome-settings-xrdb.c
Rodrigo Moya 4f4291f6d4 all modules use now the new arch.
2007-06-21  Rodrigo Moya <rodrigo@gnome-db.org>

	* gnome-settings-accessibility-keyboard.c:
	* gnome-settings-keybindings.c:
	* gnome-settings-keyboard.c:
	* gnome-settings-multimedia-keys.c:
	* gnome-settings-xrdb.c:
	* gnome-settings-daemon.c: all modules use now the new arch.

	* gnome-settings-background.c (background_callback): pass the correct
	argument to the idle callback.

svn path=/trunk/; revision=7756
2007-06-21 12:19:06 +00:00

424 lines
11 KiB
C

/* -*- Mode: C; indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; style: linux -*- */
/* gnome-settings-xrdb.c
*
* Copyright © 2003 Ross Burton
*
* Written by Ross Burton <ross@burtonini.com>
*
* 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, 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., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <glib/gi18n.h>
#include <gtk/gtkwindow.h>
#include "gnome-settings-module.h"
typedef struct {
GnomeSettingsModule parent;
} GnomeSettingsModuleXrdb;
typedef struct {
GnomeSettingsModuleClass parent_class;
} GnomeSettingsModuleXrdbClass;
#define SYSTEM_AD_DIR GNOMECC_DATA_DIR "/xrdb"
#define GENERAL_AD SYSTEM_AD_DIR "/General.ad"
#define USER_AD_DIR ".gnome2/xrdb"
#define USER_X_RESOURCES ".Xresources"
#define USER_X_DEFAULTS ".Xdefaults"
#define GTK_THEME_KEY "/desktop/gnome/interface/gtk_theme"
static GnomeSettingsModuleRunlevel gnome_settings_module_xrdb_get_runlevel (GnomeSettingsModule *module);
static gboolean gnome_settings_module_xrdb_initialize (GnomeSettingsModule *module, GConfClient *client);
static gboolean gnome_settings_module_xrdb_start (GnomeSettingsModule *module);
static gboolean gnome_settings_module_xrdb_stop (GnomeSettingsModule *module);
static GtkWidget *widget;
static void
gnome_settings_module_xrdb_class_init (GnomeSettingsModuleXrdbClass *klass)
{
GnomeSettingsModuleClass *module_class;
module_class = GNOME_SETTINGS_MODULE_CLASS (klass);
module_class->get_runlevel = gnome_settings_module_xrdb_get_runlevel;
module_class->initialize = gnome_settings_module_xrdb_initialize;
module_class->start = gnome_settings_module_xrdb_start;
module_class->stop = gnome_settings_module_xrdb_stop;
}
static void
gnome_settings_module_xrdb_init (GnomeSettingsModuleXrdb *module)
{
}
/*
* Theme colour functions
*/
/*
* TODO: replace with the code from Smooth? (which should really be
* public in GTK+)
*/
static GdkColor*
colour_shade (GdkColor *a, gdouble shade, GdkColor *b)
{
guint16 red, green, blue;
red = CLAMP ((a->red) * shade, 0, 0xFFFF);
green = CLAMP ((a->green) * shade, 0, 0xFFFF);
blue = CLAMP ((a->blue) * shade, 0, 0xFFFF);
b->red = red;
b->green = green;
b->blue = blue;
return b;
}
static void
append_colour_define (GString *string, const gchar* name, const GdkColor* colour)
{
g_return_if_fail (string != NULL);
g_return_if_fail (name != NULL);
g_return_if_fail (colour != NULL);
g_string_append_printf (string, "#define %s #%2.2hx%2.2hx%2.2hx\n",
name, colour->red>>8, colour->green>>8, colour->blue>>8);
}
static void
append_theme_colours (GtkStyle *style, GString *string)
{
GdkColor tmp;
g_return_if_fail (style != NULL);
g_return_if_fail (string != NULL);
append_colour_define(string, "BACKGROUND",
&style->bg[GTK_STATE_NORMAL]);
append_colour_define(string, "FOREGROUND",
&style->fg[GTK_STATE_NORMAL]);
append_colour_define(string, "SELECT_BACKGROUND",
&style->bg[GTK_STATE_SELECTED]);
append_colour_define(string, "SELECT_FOREGROUND",
&style->text[GTK_STATE_SELECTED]);
append_colour_define(string, "WINDOW_BACKGROUND",
&style->base[GTK_STATE_NORMAL]);
append_colour_define(string, "WINDOW_FOREGROUND",
&style->text[GTK_STATE_NORMAL]);
append_colour_define(string, "INACTIVE_BACKGROUND",
&style->bg[GTK_STATE_INSENSITIVE]);
append_colour_define(string, "INACTIVE_FOREGROUND",
&style->text[GTK_STATE_INSENSITIVE]);
append_colour_define(string, "ACTIVE_BACKGROUND",
&style->bg[GTK_STATE_SELECTED]);
append_colour_define(string, "ACTIVE_FOREGROUND",
&style->text[GTK_STATE_SELECTED]);
append_colour_define(string, "HIGHLIGHT",
colour_shade (&style->bg[GTK_STATE_NORMAL],
1.2, &tmp));
append_colour_define(string, "LOWLIGHT",
colour_shade (&style->bg[GTK_STATE_NORMAL],
2.0/3.0, &tmp));
return;
}
/*
* Directory scanning functions
*/
/**
* Compare two file names on their base names.
*/
static gint
compare_basenames (gconstpointer a, gconstpointer b)
{
char *base_a, *base_b;
int res;
base_a = g_path_get_basename (a);
base_b = g_path_get_basename (b);
res = strcmp (base_a, base_b);
g_free (base_a);
g_free (base_b);
return res;
}
/**
* Append the contents of a file onto the end of a GString
*/
static void
append_file (const char* file, GString *string, GError **error)
{
gchar *contents;
g_return_if_fail (string != NULL);
g_return_if_fail (file != NULL);
if (g_file_get_contents (file, &contents, NULL, error)) {
g_string_append (string, contents);
g_free (contents);
}
}
/**
* Scan a single directory for .ad files, and return them all in a
* GSList*
*/
static GSList*
scan_ad_directory (const char *path, GError **error)
{
GSList *list = NULL;
GDir *dir;
const gchar *entry;
g_return_val_if_fail (path != NULL, NULL);
dir = g_dir_open (path, 0, error);
if (*error) {
return NULL;
}
while ((entry = g_dir_read_name (dir)) != NULL) {
if (g_str_has_suffix (entry, ".ad")) {
list = g_slist_prepend (list, g_strdup_printf ("%s/%s", path, entry));
}
}
g_dir_close (dir);
/* TODO: sort still? */
return g_slist_sort (list, (GCompareFunc)strcmp);
}
/**
* Scan the user and system paths, and return a list of strings in the
* right order for processing.
*/
static GSList*
scan_for_files (GError **error)
{
const char* home_dir;
GSList *user_list = NULL, *system_list = NULL;
GSList *list = NULL, *p;
system_list = scan_ad_directory (SYSTEM_AD_DIR, error);
if (*error) return NULL;
home_dir = g_get_home_dir ();
if (home_dir) {
char *user_ad = g_build_filename (home_dir, USER_AD_DIR, NULL);
if (g_file_test (user_ad, G_FILE_TEST_IS_DIR)) {
user_list = scan_ad_directory (user_ad, error);
if (*error) {
g_slist_foreach (system_list, (GFunc)g_free, NULL);
g_slist_free (system_list);
g_free (user_ad);
return NULL;
}
}
g_free (user_ad);
} else {
g_warning (_("Cannot determine user's home directory"));
}
/* An alternative approach would be to strdup() the strings
and free the entire contents of these lists, but that is a
little inefficient for my liking - RB */
for (p = system_list; p != NULL; p = g_slist_next (p)) {
if (strcmp (p->data, GENERAL_AD) == 0) {
/* We ignore this, free the data now */
g_free (p->data);
continue;
}
if (g_slist_find_custom (user_list, p->data, compare_basenames)) {
/* Ditto */
g_free (p->data);
continue;
}
list = g_slist_prepend (list, p->data);
}
g_slist_free (system_list);
for (p = user_list; p != NULL; p = g_slist_next (p)) {
list = g_slist_prepend (list, p->data);
}
g_slist_free (user_list);
/* Reverse the order so it is the correct way */
list = g_slist_reverse (list);
/* Add the initial file */
list = g_slist_prepend (list, g_strdup (GENERAL_AD));
return list;
}
/**
* Append an X resources file, such as .Xresources, or .Xdefaults
*/
static void
append_xresource_file (const char * filename, GString *string, GError **error)
{
const char* home_path;
char *xresources;
g_return_if_fail (string != NULL);
home_path = g_get_home_dir ();
if (home_path == NULL) {
g_warning (_("Cannot determine user's home directory"));
return;
}
xresources = g_build_filename (home_path, filename, NULL);
if (g_file_test (xresources, G_FILE_TEST_EXISTS)) {
append_file (xresources, string, error);
if (*error) {
g_warning ("%s", (*error)->message);
g_error_free (*error);
error = NULL;
}
}
g_free (xresources);
}
/*
* Entry point
*/
static void
apply_settings (GtkStyle *style)
{
char *xrdb[] = { "xrdb", "-merge", NULL };
GString *string;
GSList *list = NULL, *p;
GError *error = NULL;
string = g_string_sized_new (256);
append_theme_colours (style, string);
list = scan_for_files (&error);
if (error) {
g_warning (error->message);
g_error_free (error);
error = NULL;
}
for (p = list; p != NULL; p=g_slist_next (p)) {
append_file (p->data, string, &error);
if (error) {
g_warning (error->message);
g_error_free (error);
error = NULL;
}
}
g_slist_foreach (list, (GFunc)g_free, NULL);
g_slist_free (list);
append_xresource_file (USER_X_RESOURCES, string, &error);
append_xresource_file (USER_X_DEFAULTS, string, &error);
if (error) {
g_warning (error->message);
g_error_free (error);
error = NULL;
}
gnome_settings_spawn_with_input (xrdb, string->str);
g_string_free (string, TRUE);
return;
}
static void theme_changed (GtkSettings *settings,
GParamSpec *pspec,
GtkWidget *widget)
{
apply_settings (gtk_widget_get_style (widget));
}
GType
gnome_settings_module_xrdb_get_type (void)
{
static GType module_type = 0;
if (!module_type) {
static const GTypeInfo module_info = {
sizeof (GnomeSettingsModuleXrdbClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gnome_settings_module_xrdb_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GnomeSettingsModuleXrdb),
0, /* n_preallocs */
(GInstanceInitFunc) gnome_settings_module_xrdb_init,
};
module_type = g_type_register_static (GNOME_SETTINGS_TYPE_MODULE,
"GnomeSettingsModuleXrdb",
&module_info, 0);
}
return module_type;
}
static GnomeSettingsModuleRunlevel
gnome_settings_module_xrdb_get_runlevel (GnomeSettingsModule *module)
{
return GNOME_SETTINGS_MODULE_RUNLEVEL_XSETTINGS;
}
static gboolean
gnome_settings_module_xrdb_initialize (GnomeSettingsModule *module, GConfClient *client)
{
return TRUE;
}
static gboolean
gnome_settings_module_xrdb_start (GnomeSettingsModule *module)
{
static gboolean initialized = FALSE;
if (!initialized) {
/* the initialization is done here otherwise
gnome_settings_xsettings_load would generate
false hit as gtk-theme-name is set to Default in
gnome_settings_xsettings_init */
GtkSettings *settings = gtk_settings_get_default ();
widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (settings,
"notify::gtk-theme-name",
G_CALLBACK (theme_changed),
widget);
gtk_widget_ensure_style (widget);
initialized = TRUE;
}
return TRUE;
}
static gboolean
gnome_settings_module_xrdb_stop (GnomeSettingsModule *module)
{
return TRUE;
}