442 lines
10 KiB
C
442 lines
10 KiB
C
|
/* Metacity preferences */
|
||
|
|
||
|
/*
|
||
|
* Copyright (C) 2001 Havoc Pennington
|
||
|
*
|
||
|
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||
|
* 02111-1307, USA.
|
||
|
*/
|
||
|
|
||
|
#include <config.h>
|
||
|
#include "prefs.h"
|
||
|
#include "util.h"
|
||
|
#include <gconf/gconf-client.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
/* If you add a key, it needs updating in init() and in the gconf
|
||
|
* notify listener and of course in the .schemas file
|
||
|
*/
|
||
|
#define KEY_FOCUS_MODE "/apps/metacity/general/focus_mode"
|
||
|
#define KEY_USE_DESKTOP_FONT "/apps/metacity/general/titlebar_uses_desktop_font"
|
||
|
#define KEY_TITLEBAR_FONT "/apps/metacity/general/titlebar_font"
|
||
|
#define KEY_TITLEBAR_FONT_SIZE "/apps/metacity/general/titlebar_font_size"
|
||
|
|
||
|
static GConfClient *client = NULL;
|
||
|
static GList *listeners = NULL;
|
||
|
static GList *changes = NULL;
|
||
|
static guint changed_idle;
|
||
|
static gboolean use_desktop_font = TRUE;
|
||
|
static PangoFontDescription *titlebar_font = NULL;
|
||
|
static int titlebar_font_size = 0;
|
||
|
static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
|
||
|
|
||
|
static gboolean update_use_desktop_font (gboolean value);
|
||
|
static gboolean update_titlebar_font (const char *value);
|
||
|
static gboolean update_titlebar_font_size (int value);
|
||
|
static gboolean update_focus_mode (const char *value);
|
||
|
|
||
|
static void queue_changed (MetaPreference pref);
|
||
|
static void change_notify (GConfClient *client,
|
||
|
guint cnxn_id,
|
||
|
GConfEntry *entry,
|
||
|
gpointer user_data);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
MetaPrefsChangedFunc func;
|
||
|
gpointer data;
|
||
|
} MetaPrefsListener;
|
||
|
|
||
|
void
|
||
|
meta_prefs_add_listener (MetaPrefsChangedFunc func,
|
||
|
gpointer data)
|
||
|
{
|
||
|
MetaPrefsListener *l;
|
||
|
|
||
|
l = g_new (MetaPrefsListener, 1);
|
||
|
l->func = func;
|
||
|
l->data = data;
|
||
|
|
||
|
listeners = g_list_prepend (listeners, l);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
meta_prefs_remove_listener (MetaPrefsChangedFunc func,
|
||
|
gpointer data)
|
||
|
{
|
||
|
GList *tmp;
|
||
|
|
||
|
tmp = listeners;
|
||
|
while (tmp != NULL)
|
||
|
{
|
||
|
MetaPrefsListener *l = tmp->data;
|
||
|
|
||
|
if (l->func == func &&
|
||
|
l->data == data)
|
||
|
{
|
||
|
g_free (l);
|
||
|
listeners = g_list_delete_link (listeners, tmp);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
tmp = tmp->next;
|
||
|
}
|
||
|
|
||
|
meta_bug ("Did not find listener to remove\n");
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
emit_changed (MetaPreference pref)
|
||
|
{
|
||
|
GList *tmp;
|
||
|
GList *copy;
|
||
|
|
||
|
meta_verbose ("Notifying listeners that pref %s changed\n",
|
||
|
meta_preference_to_string (pref));
|
||
|
|
||
|
copy = g_list_copy (listeners);
|
||
|
|
||
|
tmp = copy;
|
||
|
while (tmp != NULL)
|
||
|
{
|
||
|
MetaPrefsListener *l = tmp->data;
|
||
|
|
||
|
(* l->func) (pref, l->data);
|
||
|
|
||
|
tmp = tmp->next;
|
||
|
}
|
||
|
|
||
|
g_list_free (copy);
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
changed_idle_handler (gpointer data)
|
||
|
{
|
||
|
GList *tmp;
|
||
|
GList *copy;
|
||
|
|
||
|
changed_idle = 0;
|
||
|
|
||
|
copy = g_list_copy (changes); /* reentrancy paranoia */
|
||
|
|
||
|
g_list_free (changes);
|
||
|
changes = NULL;
|
||
|
|
||
|
tmp = copy;
|
||
|
while (tmp != NULL)
|
||
|
{
|
||
|
MetaPreference pref = GPOINTER_TO_INT (tmp->data);
|
||
|
|
||
|
emit_changed (pref);
|
||
|
|
||
|
tmp = tmp->next;
|
||
|
}
|
||
|
|
||
|
g_list_free (copy);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
queue_changed (MetaPreference pref)
|
||
|
{
|
||
|
meta_verbose ("Queueing change of pref %s\n",
|
||
|
meta_preference_to_string (pref));
|
||
|
|
||
|
if (g_list_find (changes, GINT_TO_POINTER (pref)) == NULL)
|
||
|
changes = g_list_prepend (changes, GINT_TO_POINTER (pref));
|
||
|
else
|
||
|
meta_verbose ("Change of pref %s was already pending\n",
|
||
|
meta_preference_to_string (pref));
|
||
|
|
||
|
if (changed_idle == 0)
|
||
|
changed_idle = g_idle_add (changed_idle_handler, NULL);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
cleanup_error (GError **error)
|
||
|
{
|
||
|
if (*error)
|
||
|
{
|
||
|
meta_warning ("%s", (*error)->message);
|
||
|
|
||
|
g_error_free (*error);
|
||
|
*error = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
meta_prefs_init (void)
|
||
|
{
|
||
|
GError *err = NULL;
|
||
|
char *str_val;
|
||
|
int int_val;
|
||
|
gboolean bool_val;
|
||
|
|
||
|
if (client != NULL)
|
||
|
return;
|
||
|
|
||
|
/* returns a reference which we hold forever */
|
||
|
client = gconf_client_get_default ();
|
||
|
|
||
|
gconf_client_add_dir (client, "/apps/metacity",
|
||
|
GCONF_CLIENT_PRELOAD_RECURSIVE,
|
||
|
&err);
|
||
|
cleanup_error (&err);
|
||
|
|
||
|
str_val = gconf_client_get_string (client, KEY_FOCUS_MODE,
|
||
|
&err);
|
||
|
cleanup_error (&err);
|
||
|
update_focus_mode (str_val);
|
||
|
g_free (str_val);
|
||
|
|
||
|
bool_val = gconf_client_get_bool (client, KEY_USE_DESKTOP_FONT,
|
||
|
&err);
|
||
|
cleanup_error (&err);
|
||
|
update_use_desktop_font (bool_val);
|
||
|
|
||
|
int_val = gconf_client_get_int (client, KEY_TITLEBAR_FONT_SIZE,
|
||
|
&err);
|
||
|
cleanup_error (&err);
|
||
|
update_titlebar_font_size (int_val);
|
||
|
|
||
|
str_val = gconf_client_get_string (client, KEY_TITLEBAR_FONT,
|
||
|
&err);
|
||
|
cleanup_error (&err);
|
||
|
update_titlebar_font (str_val);
|
||
|
g_free (str_val);
|
||
|
|
||
|
gconf_client_notify_add (client, "/apps/metacity",
|
||
|
change_notify,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&err);
|
||
|
cleanup_error (&err);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
change_notify (GConfClient *client,
|
||
|
guint cnxn_id,
|
||
|
GConfEntry *entry,
|
||
|
gpointer user_data)
|
||
|
{
|
||
|
const char *key;
|
||
|
GConfValue *value;
|
||
|
|
||
|
key = gconf_entry_get_key (entry);
|
||
|
value = gconf_entry_get_value (entry);
|
||
|
|
||
|
if (strcmp (key, KEY_FOCUS_MODE) == 0)
|
||
|
{
|
||
|
const char *str;
|
||
|
|
||
|
if (value && value->type != GCONF_VALUE_STRING)
|
||
|
{
|
||
|
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
|
||
|
KEY_FOCUS_MODE);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
str = value ? gconf_value_get_string (value) : NULL;
|
||
|
|
||
|
if (update_focus_mode (str))
|
||
|
queue_changed (META_PREF_FOCUS_MODE);
|
||
|
}
|
||
|
else if (strcmp (key, KEY_TITLEBAR_FONT) == 0)
|
||
|
{
|
||
|
const char *str;
|
||
|
|
||
|
if (value && value->type != GCONF_VALUE_STRING)
|
||
|
{
|
||
|
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
|
||
|
KEY_TITLEBAR_FONT);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
str = value ? gconf_value_get_string (value) : NULL;
|
||
|
|
||
|
if (update_titlebar_font (str))
|
||
|
queue_changed (META_PREF_TITLEBAR_FONT);
|
||
|
}
|
||
|
else if (strcmp (key, KEY_TITLEBAR_FONT_SIZE) == 0)
|
||
|
{
|
||
|
int d;
|
||
|
|
||
|
if (value && value->type != GCONF_VALUE_INT)
|
||
|
{
|
||
|
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
|
||
|
KEY_TITLEBAR_FONT_SIZE);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
d = value ? gconf_value_get_int (value) : 0;
|
||
|
|
||
|
if (update_titlebar_font_size (d))
|
||
|
queue_changed (META_PREF_TITLEBAR_FONT_SIZE);
|
||
|
}
|
||
|
else if (strcmp (key, KEY_USE_DESKTOP_FONT) == 0)
|
||
|
{
|
||
|
gboolean b;
|
||
|
|
||
|
if (value && value->type != GCONF_VALUE_BOOL)
|
||
|
{
|
||
|
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
|
||
|
KEY_USE_DESKTOP_FONT);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
b = value ? gconf_value_get_bool (value) : TRUE;
|
||
|
|
||
|
/* There's no external pref for this, it just affects whether
|
||
|
* get_titlebar_font returns NULL, so that's what we queue
|
||
|
* the change on
|
||
|
*/
|
||
|
if (update_use_desktop_font (b))
|
||
|
queue_changed (META_PREF_TITLEBAR_FONT);
|
||
|
}
|
||
|
else
|
||
|
meta_verbose ("Key %s doesn't mean anything to Metacity\n",
|
||
|
key);
|
||
|
|
||
|
out:
|
||
|
/* nothing */
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
update_focus_mode (const char *value)
|
||
|
{
|
||
|
MetaFocusMode old_mode = focus_mode;
|
||
|
|
||
|
if (value != NULL)
|
||
|
{
|
||
|
if (g_ascii_strcasecmp (value, "click") == 0)
|
||
|
focus_mode = META_FOCUS_MODE_CLICK;
|
||
|
else if (g_ascii_strcasecmp (value, "sloppy") == 0)
|
||
|
focus_mode = META_FOCUS_MODE_SLOPPY;
|
||
|
else if (g_ascii_strcasecmp (value, "mouse") == 0)
|
||
|
focus_mode = META_FOCUS_MODE_MOUSE;
|
||
|
else
|
||
|
meta_warning (_("GConf key '%s' is set to an invalid value"),
|
||
|
KEY_FOCUS_MODE);
|
||
|
}
|
||
|
|
||
|
return (old_mode != focus_mode);
|
||
|
}
|
||
|
|
||
|
MetaFocusMode
|
||
|
meta_prefs_get_focus_mode (void)
|
||
|
{
|
||
|
return focus_mode;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
update_use_desktop_font (gboolean value)
|
||
|
{
|
||
|
gboolean old = use_desktop_font;
|
||
|
|
||
|
use_desktop_font = value;
|
||
|
|
||
|
return old != value;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
update_titlebar_font (const char *value)
|
||
|
{
|
||
|
PangoFontDescription *new_desc;
|
||
|
|
||
|
new_desc = NULL;
|
||
|
|
||
|
if (value)
|
||
|
{
|
||
|
new_desc = pango_font_description_from_string (value);
|
||
|
if (new_desc == NULL)
|
||
|
meta_warning (_("Could not parse font description \"%s\" from GConf key %s\n"),
|
||
|
value, KEY_TITLEBAR_FONT);
|
||
|
}
|
||
|
|
||
|
if (new_desc && titlebar_font &&
|
||
|
pango_font_description_equal (new_desc, titlebar_font))
|
||
|
{
|
||
|
pango_font_description_free (new_desc);
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (titlebar_font)
|
||
|
pango_font_description_free (titlebar_font);
|
||
|
|
||
|
titlebar_font = new_desc;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const PangoFontDescription*
|
||
|
meta_prefs_get_titlebar_font (void)
|
||
|
{
|
||
|
if (use_desktop_font)
|
||
|
return NULL;
|
||
|
else
|
||
|
return titlebar_font;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
update_titlebar_font_size (int value)
|
||
|
{
|
||
|
int old = titlebar_font_size;
|
||
|
|
||
|
if (value < 0)
|
||
|
{
|
||
|
meta_warning (_("%d stored in GConf key %s is not a valid font size\n"),
|
||
|
value, KEY_TITLEBAR_FONT_SIZE);
|
||
|
value = 0;
|
||
|
}
|
||
|
|
||
|
titlebar_font_size = value;
|
||
|
|
||
|
return old != titlebar_font_size;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
meta_prefs_get_titlebar_font_size (void)
|
||
|
{
|
||
|
return titlebar_font_size;
|
||
|
}
|
||
|
|
||
|
const char*
|
||
|
meta_preference_to_string (MetaPreference pref)
|
||
|
{
|
||
|
switch (pref)
|
||
|
{
|
||
|
case META_PREF_FOCUS_MODE:
|
||
|
return "FOCUS_MODE";
|
||
|
break;
|
||
|
|
||
|
case META_PREF_TITLEBAR_FONT:
|
||
|
return "TITLEBAR_FONT";
|
||
|
break;
|
||
|
|
||
|
case META_PREF_TITLEBAR_FONT_SIZE:
|
||
|
return "TITLEBAR_FONT_SIZE";
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return "(unknown)";
|
||
|
}
|