summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2001-04-02 23:33:47 +0000
committerOwen Taylor <otaylor@src.gnome.org>2001-04-02 23:33:47 +0000
commitb52b326d5f34b09af70e9f277a43b48c5bf3be2d (patch)
tree2593b2dffad11ac442a89514a39988d75e53701d /gdk
parent0aef43bcbcb208d7419711ffd48dd7942d538952 (diff)
downloadgdk-pixbuf-b52b326d5f34b09af70e9f277a43b48c5bf3be2d.tar.gz
Add GdkEventSetting event for notification of changes to system settings,
Mon Apr 2 18:18:07 2001 Owen Taylor <otaylor@redhat.com> * gdk/gdkevents.h: Add GdkEventSetting event for notification of changes to system settings, gdk_setting_get() to retrieve a single system setting. * gdk/x11/gdkevents-x11.c: Bridge gdk_setting_get() and GdkEventSetting to the draft XSETTINGS mechanism. * gdk/x11/xsettings-{common,client}.[ch]: Sample-implementation of XSETTINGS. * gtk/gtkmain.c gtk/gtksettings.[ch]: Propagate notification of GDK settings changes to the GtkSettings object. * gdk/gdkevents.[ch] gdk/gtk/gtksettings.c: Hook up the double-click-timeout property to GDK. * gdk/gdkcolor.[ch] gdk/gdkvisual.h gdk/gdkevent.[ch] gdk/gdkfont.[ch]: Define GDK boxed types here. * gdk/Makefile.am gdk/makeenums.pl: Generate source files gdk/gdkenumtypes.[ch] for enum definitions. * gtk/gtkcompat.h: Add defines for GTK_TYPE_GDK_* * gtk/gtk-boxed.defs: Comment out GDK types * gtk/gtktypeutils.h: Remove GDK types * gtk/Makefile.am: No longer scan GDK headers for enumerataions
Diffstat (limited to 'gdk')
-rw-r--r--gdk/Makefile.am31
-rw-r--r--gdk/gdk.c2
-rw-r--r--gdk/gdk.h3
-rw-r--r--gdk/gdkcolor.c32
-rw-r--r--gdk/gdkcolor.h3
-rw-r--r--gdk/gdkevents.c44
-rw-r--r--gdk/gdkevents.h27
-rw-r--r--gdk/gdkfont.c14
-rw-r--r--gdk/gdkfont.h4
-rw-r--r--gdk/gdkvisual.h4
-rw-r--r--gdk/gdkwindow.c6
-rwxr-xr-xgdk/makeenums.pl279
-rw-r--r--gdk/x11/Makefile.am4
-rw-r--r--gdk/x11/gdkevents-x11.c169
-rw-r--r--gdk/x11/xsettings-client.c535
-rw-r--r--gdk/x11/xsettings-client.h68
-rw-r--r--gdk/x11/xsettings-common.c261
-rw-r--r--gdk/x11/xsettings-common.h110
18 files changed, 1575 insertions, 21 deletions
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
index a2d3e3c4d..d6b770b72 100644
--- a/gdk/Makefile.am
+++ b/gdk/Makefile.am
@@ -68,7 +68,6 @@ gdk_public_h_sources = @STRIP_BEGIN@ \
gdkpango.h \
gdkpixbuf.h \
gdkpixmap.h \
- gdkprivate.h \
gdkproperty.h \
gdkregion.h \
gdkrgb.h \
@@ -78,6 +77,12 @@ gdk_public_h_sources = @STRIP_BEGIN@ \
gdkwindow.h \
@STRIP_END@
+gdk_headers = @STRIP_BEGIN@ \
+ $(gdk_public_h_sources) \
+ gdkenumtypes.h \
+ gdkprivate.h \
+@STRIP_END@
+
gdk_c_sources = @STRIP_BEGIN@ \
gdk.c \
gdkcolor.c \
@@ -115,8 +120,8 @@ libgdk_x11_includedir = $(includedir)/gtk-2.0/gdk
libgdk_x11_1_3_la_LIBADD = \
$(gtarget)/libgdk-$(gtarget).la
-libgdk_x11_include_HEADERS = $(gdk_public_h_sources)
-libgdk_x11_1_3_la_SOURCES = $(gdk_c_sources)
+libgdk_x11_include_HEADERS = $(gdk_headers)
+libgdk_x11_1_3_la_SOURCES = $(gdk_c_sources) gdkenumtypes.c
endif
if USE_NANOX
@@ -125,8 +130,8 @@ libgdk_nanox_includedir = $(includedir)/gtk-2.0/gdk
libgdk_nanox_1_3_la_LIBADD = \
$(gtarget)/libgdk-$(gtarget).la
-libgdk_nanox_include_HEADERS = $(gdk_public_h_sources)
-libgdk_nanox_1_3_la_SOURCES = $(gdk_c_sources)
+libgdk_nanox_include_HEADERS = $(gdk_headers)
+libgdk_nanox_1_3_la_SOURCES = $(gdk_c_sources) gdkenumtypes.c
endif
if USE_LINUX_FB
@@ -135,8 +140,8 @@ libgdk_linux_fb_includedir = $(includedir)/gtk-2.0/gdk
libgdk_linux_fb_1_3_la_LIBADD = \
$(gtarget)/libgdk-$(gtarget).la
-libgdk_linux_fb_include_HEADERS = $(gdk_public_h_sources)
-libgdk_linux_fb_1_3_la_SOURCES = $(gdk_c_sources)
+libgdk_linux_fb_include_HEADERS = $(gdk_headers)
+libgdk_linux_fb_1_3_la_SOURCES = $(gdk_c_sources) gdkenumtypes.c
endif
# now define the real one to workaround automake's mishandling
@@ -173,7 +178,17 @@ install-exec-local: gdkconfig.h
if test -r $$file && cmp -s gdkconfig.h $$file; then :; \
else $(INSTALL_DATA) gdkconfig.h $$file; fi
-BUILT_SOURCES = stamp-gc-h #note: not gdkconfig.h
+#note: not gdkconfig.h
+BUILT_SOURCES = stamp-gc-h @REBUILD@ gdkenumtypes.c gdkenumtypes.h
+
+gdkenumtypes.h: @REBUILD@ $(gdk_public_h_sources) makeenums.pl
+ cd $(srcdir) \
+ && $(PERL) ./makeenums.pl include $(gdk_public_h_sources) > gdkenumtypes.h
+
+gdkenumtypes.c: @REBUILD@ $(gdk_public_h_sources) makeenums.pl
+ cd $(srcdir) \
+ && $(PERL) ./makeenums.pl cfile $(gdk_public_h_sources) > gdkenumtypes.c
+
gdkconfig.h: stamp-gc-h
@if test -f gdkconfig.h; then :; \
else rm -f stamp-gc-h; $(MAKE) stamp-gc-h; fi
diff --git a/gdk/gdk.c b/gdk/gdk.c
index acdd3ec90..ae95ddfaf 100644
--- a/gdk/gdk.c
+++ b/gdk/gdk.c
@@ -333,10 +333,10 @@ gdk_init_check (int *argc,
if (!result)
return FALSE;
- gdk_events_init ();
gdk_visual_init ();
_gdk_windowing_window_init ();
_gdk_windowing_image_init ();
+ gdk_events_init ();
gdk_input_init ();
gdk_dnd_init ();
diff --git a/gdk/gdk.h b/gdk/gdk.h
index 1e03c4f35..0fc565f93 100644
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -31,6 +31,7 @@
#include <gdk/gdkcursor.h>
#include <gdk/gdkdnd.h>
#include <gdk/gdkdrawable.h>
+#include <gdk/gdkenumtypes.h>
#include <gdk/gdkevents.h>
#include <gdk/gdkfont.h>
#include <gdk/gdkgc.h>
@@ -114,6 +115,8 @@ gint gdk_screen_height_mm (void) G_GNUC_CONST;
void gdk_flush (void);
void gdk_beep (void);
+void gdk_set_double_click_time (guint msec);
+
/* Rectangle utilities
*/
gboolean gdk_rectangle_intersect (GdkRectangle *src1,
diff --git a/gdk/gdkcolor.c b/gdk/gdkcolor.c
index d548d7386..237835632 100644
--- a/gdk/gdkcolor.c
+++ b/gdk/gdkcolor.c
@@ -216,3 +216,35 @@ gdk_color_equal (const GdkColor *colora,
(colora->green == colorb->green) &&
(colora->blue == colorb->blue));
}
+
+GType
+gdk_color_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static ("GdkColor",
+ NULL,
+ (GBoxedCopyFunc)gdk_color_copy,
+ (GBoxedFreeFunc)gdk_color_free,
+ FALSE);
+ return our_type;
+}
+
+/* We define this here to avoid having to create a new .C file just for this
+ * function. The rest of GdkVisual is platform-specific
+ */
+GType
+gdk_visual_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static ("GdkVisual",
+ NULL,
+ (GBoxedCopyFunc)gdk_visual_ref,
+ (GBoxedFreeFunc)gdk_visual_unref,
+ TRUE);
+ return our_type;
+}
+
diff --git a/gdk/gdkcolor.h b/gdk/gdkcolor.h
index 8487ca36e..ad820830a 100644
--- a/gdk/gdkcolor.h
+++ b/gdk/gdkcolor.h
@@ -34,6 +34,7 @@ typedef struct _GdkColormapClass GdkColormapClass;
#define GDK_IS_COLORMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_COLORMAP))
#define GDK_COLORMAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_COLORMAP, GdkColormapClass))
+#define GDK_TYPE_COLOR (gdk_color_get_type ())
struct _GdkColormap
{
@@ -96,6 +97,8 @@ guint gdk_color_hash (const GdkColor *colora);
gboolean gdk_color_equal (const GdkColor *colora,
const GdkColor *colorb);
+GType gdk_color_get_type (void);
+
/* The following functions are deprecated */
#ifndef GDK_DISABLE_DEPRECATED
void gdk_colors_store (GdkColormap *colormap,
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index 92972578c..2f86c5aa1 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -30,11 +30,6 @@
typedef struct _GdkIOClosure GdkIOClosure;
typedef struct _GdkEventPrivate GdkEventPrivate;
-#define DOUBLE_CLICK_TIME 250
-#define TRIPLE_CLICK_TIME 500
-#define DOUBLE_CLICK_DIST 5
-#define TRIPLE_CLICK_DIST 5
-
typedef enum
{
/* Following flag is set for events on the event queue during
@@ -84,6 +79,11 @@ GDestroyNotify gdk_event_notify = NULL;
GPollFD event_poll_fd;
+static guint double_click_time = 250;
+#define TRIPLE_CLICK_TIME (2*double_click_time)
+#define DOUBLE_CLICK_DIST 5
+#define TRIPLE_CLICK_DIST 5
+
/*********************************************
* Functions for maintaining the event queue *
*********************************************/
@@ -326,7 +326,12 @@ gdk_event_copy (GdkEvent *event)
if (event->expose.region)
new_event->expose.region = gdk_region_copy (event->expose.region);
break;
- default:
+
+ case GDK_SETTING:
+ new_event->setting.name = g_strdup (new_event->setting.name);
+ break;
+
+ default:
break;
}
@@ -399,6 +404,10 @@ gdk_event_free (GdkEvent *event)
g_free (event->motion.axes);
break;
+ case GDK_SETTING:
+ g_free (event->setting.name);
+ break;
+
default:
break;
}
@@ -464,6 +473,7 @@ gdk_event_get_time (GdkEvent *event)
case GDK_MAP:
case GDK_UNMAP:
case GDK_WINDOW_STATE:
+ case GDK_SETTING:
/* return current time */
break;
}
@@ -540,6 +550,7 @@ gdk_event_get_state (GdkEvent *event,
case GDK_MAP:
case GDK_UNMAP:
case GDK_WINDOW_STATE:
+ case GDK_SETTING:
/* no state field */
break;
}
@@ -791,7 +802,7 @@ gdk_event_button_generate (GdkEvent *event)
button_number[1] = -1;
button_number[0] = -1;
}
- else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
+ else if ((event->button.time < (button_click_time[0] + double_click_time)) &&
(event->button.window == button_window[0]) &&
(event->button.button == button_number[0]))
{
@@ -867,3 +878,22 @@ gdk_synthesize_window_state (GdkWindow *window,
}
}
+void
+gdk_set_double_click_time (guint msec)
+{
+ double_click_time = msec;
+}
+
+GType
+gdk_event_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static ("GdkEvent",
+ NULL,
+ (GBoxedCopyFunc)gdk_event_copy,
+ (GBoxedFreeFunc)gdk_event_free,
+ FALSE);
+ return our_type;
+}
diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
index 14232fd93..a1eeb02ed 100644
--- a/gdk/gdkevents.h
+++ b/gdk/gdkevents.h
@@ -1,6 +1,7 @@
#ifndef __GDK_EVENTS_H__
#define __GDK_EVENTS_H__
+#include <gdk/gdkcolor.h>
#include <gdk/gdktypes.h>
#include <gdk/gdkdnd.h>
#include <gdk/gdkinput.h>
@@ -9,6 +10,8 @@
extern "C" {
#endif /* __cplusplus */
+#define GDK_TYPE_EVENT (gdk_event_get_type ())
+
#define GDK_PRIORITY_EVENTS (G_PRIORITY_DEFAULT)
#define GDK_PRIORITY_REDRAW (G_PRIORITY_HIGH_IDLE + 20)
@@ -30,6 +33,7 @@ typedef struct _GdkEventProximity GdkEventProximity;
typedef struct _GdkEventClient GdkEventClient;
typedef struct _GdkEventDND GdkEventDND;
typedef struct _GdkEventWindowState GdkEventWindowState;
+typedef struct _GdkEventSetting GdkEventSetting;
typedef union _GdkEvent GdkEvent;
@@ -111,7 +115,8 @@ typedef enum
GDK_VISIBILITY_NOTIFY = 29,
GDK_NO_EXPOSE = 30,
GDK_SCROLL = 31,
- GDK_WINDOW_STATE = 32
+ GDK_WINDOW_STATE = 32,
+ GDK_SETTING = 33
} GdkEventType;
/* Event masks. (Used to select what types of events a window
@@ -202,6 +207,13 @@ typedef enum
GDK_WINDOW_STATE_STICKY = 1 << 3
} GdkWindowState;
+typedef enum
+{
+ GDK_SETTING_ACTION_NEW,
+ GDK_SETTING_ACTION_CHANGED,
+ GDK_SETTING_ACTION_DELETED
+} GdkSettingAction;
+
struct _GdkEventAny
{
GdkEventType type;
@@ -376,6 +388,14 @@ struct _GdkEventClient
} data;
};
+struct _GdkEventSetting
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkSettingAction action;
+ char *name;
+};
struct _GdkEventWindowState
{
@@ -418,8 +438,11 @@ union _GdkEvent
GdkEventClient client;
GdkEventDND dnd;
GdkEventWindowState window_state;
+ GdkEventSetting setting;
};
+GType gdk_event_get_type (void);
+
gboolean gdk_events_pending (void);
GdkEvent* gdk_event_get (void);
@@ -452,6 +475,8 @@ void gdk_add_client_message_filter (GdkAtom message_type,
GdkFilterFunc func,
gpointer data);
+gboolean gdk_setting_get (const gchar *name,
+ GValue *value);
#ifdef __cplusplus
}
diff --git a/gdk/gdkfont.c b/gdk/gdkfont.c
index 59fed5061..a3c6d6459 100644
--- a/gdk/gdkfont.c
+++ b/gdk/gdkfont.c
@@ -27,6 +27,20 @@
#include "gdkfont.h"
#include "gdkinternals.h"
+GType
+gdk_font_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static ("GdkFont",
+ NULL,
+ (GBoxedCopyFunc)gdk_font_ref,
+ (GBoxedFreeFunc)gdk_font_unref,
+ TRUE);
+ return our_type;
+}
+
GdkFont*
gdk_font_ref (GdkFont *font)
{
diff --git a/gdk/gdkfont.h b/gdk/gdkfont.h
index b0bfb6e8e..4e2c8ed56 100644
--- a/gdk/gdkfont.h
+++ b/gdk/gdkfont.h
@@ -10,6 +10,8 @@
extern "C" {
#endif /* __cplusplus */
+#define GDK_TYPE_FONT gdk_font_get_type
+
/* Types of font.
* GDK_FONT_FONT: the font is an XFontStruct.
* GDK_FONT_FONTSET: the font is an XFontSet used for I18N.
@@ -27,6 +29,8 @@ struct _GdkFont
gint descent;
};
+GType gdk_font_get_type (void);
+
GdkFont* gdk_font_load (const gchar *font_name);
GdkFont* gdk_fontset_load (const gchar *fontset_name);
diff --git a/gdk/gdkvisual.h b/gdk/gdkvisual.h
index 1bd58f996..f42bae819 100644
--- a/gdk/gdkvisual.h
+++ b/gdk/gdkvisual.h
@@ -7,6 +7,8 @@
extern "C" {
#endif /* __cplusplus */
+#define GDK_TYPE_VISUAL gdk_visual_get_type
+
/* Types of visuals.
* StaticGray:
* Grayscale:
@@ -58,6 +60,8 @@ struct _GdkVisual
gint blue_prec;
};
+GType gdk_visual_get_type (void);
+
gint gdk_visual_get_best_depth (void);
GdkVisualType gdk_visual_get_best_type (void);
GdkVisual* gdk_visual_get_system (void);
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index f64fab21a..1e6ec4bce 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -478,8 +478,7 @@ gdk_window_add_filter (GdkWindow *window,
GList *tmp_list;
GdkEventFilter *filter;
- g_return_if_fail (window != NULL);
- g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
private = (GdkWindowObject*) window;
if (private && GDK_WINDOW_DESTROYED (window))
@@ -517,8 +516,7 @@ gdk_window_remove_filter (GdkWindow *window,
GList *tmp_list, *node;
GdkEventFilter *filter;
- g_return_if_fail (window != NULL);
- g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
private = (GdkWindowObject*) window;
diff --git a/gdk/makeenums.pl b/gdk/makeenums.pl
new file mode 100755
index 000000000..257c84208
--- /dev/null
+++ b/gdk/makeenums.pl
@@ -0,0 +1,279 @@
+#!/usr/bin/perl -w
+
+# Information about the current enumeration
+
+my $flags; # Is enumeration a bitmask
+my $seenbitshift; # Have we seen bitshift operators?
+my $prefix; # Prefix for this enumeration
+my $enumname; # Name for this enumeration
+my $firstenum = 1; # Is this the first enumeration in file?
+my @entries; # [ $name, $val ] for each entry
+
+sub parse_options {
+ my $opts = shift;
+ my @opts;
+
+ for $opt (split /\s*,\s*/, $opts) {
+ my ($key,$val) = $opt =~ /\s*(\w+)(?:=(\S+))?/;
+ defined $val or $val = 1;
+ push @opts, $key, $val;
+ }
+ @opts;
+}
+sub parse_entries {
+ my $file = shift;
+
+ while (<$file>) {
+ # Read lines until we have no open comments
+ while (m@/\*
+ ([^*]|\*(?!/))*$
+ @x) {
+ my $new;
+ defined ($new = <$file>) || die "Unmatched comment";
+ $_ .= $new;
+ }
+ # Now strip comments
+ s@/\*(?!<)
+ ([^*]+|\*(?!/))*
+ \*/@@gx;
+
+ s@\n@ @;
+
+ next if m@^\s*$@;
+
+ # Handle include files
+ if (/^\#include\s*<([^>]*)>/ ) {
+ my $file= "../$1";
+ open NEWFILE, $file or die "Cannot open include file $file: $!\n";
+
+ if (parse_entries (\*NEWFILE)) {
+ return 1;
+ } else {
+ next;
+ }
+ }
+
+ if (/^\s*\}\s*(\w+)/) {
+ $enumname = $1;
+ return 1;
+ }
+
+ if (m@^\s*
+ (\w+)\s* # name
+ (?:=( # value
+ (?:[^,/]|/(?!\*))*
+ ))?,?\s*
+ (?:/\*< # options
+ (([^*]|\*(?!/))*)
+ >\*/)?
+ \s*$
+ @x) {
+ my ($name, $value, $options) = ($1,$2,$3);
+
+ if (!defined $flags && defined $value && $value =~ /<</) {
+ $seenbitshift = 1;
+ }
+ if (defined $options) {
+ my %options = parse_options($options);
+ if (!defined $options{skip}) {
+ push @entries, [ $name, $options{nick} ];
+ }
+ } else {
+ push @entries, [ $name ];
+ }
+ } else {
+ print STDERR "Can't understand: $_\n";
+ }
+ }
+ return 0;
+}
+
+
+my $gen_arrays = 0;
+my $gen_defs = 0;
+my $gen_includes = 0;
+my $gen_cfile = 0;
+
+# Parse arguments
+
+if (@ARGV) {
+ if ($ARGV[0] eq "arrays") {
+ shift @ARGV;
+ $gen_arrays = 1;
+ } elsif ($ARGV[0] eq "defs") {
+ shift @ARGV;
+ $gen_defs = 1;
+ } elsif ($ARGV[0] eq "include") {
+ shift @ARGV;
+ $gen_includes = 1;
+ } elsif ($ARGV[0] eq "cfile") {
+ shift @ARGV;
+ $gen_cfile = 1;
+ }
+}
+
+if ($gen_defs) {
+ print ";; generated by makeenums.pl ; -*- scheme -*-\n\n";
+} else {
+ print "/* Generated by makeenums.pl */\n\n";
+}
+
+if ($gen_includes) {
+ print "#ifndef __GDK_ENUM_TYPES_H__\n";
+ print "#define __GDK_ENUM_TYPES_H__\n";
+}
+
+if ($gen_cfile) {
+ print "#include \"gdk.h\"\n";
+}
+
+ENUMERATION:
+while (<>) {
+ if (eof) {
+ close (ARGV); # reset line numbering
+ $firstenum = 1; # Flag to print filename at next enum
+ }
+
+ if (m@^\s*typedef\s+enum\s*
+ ({)?\s*
+ (?:/\*<
+ (([^*]|\*(?!/))*)
+ >\*/)?
+ @x) {
+ print "\n";
+ if (defined $2) {
+ my %options = parse_options($2);
+ $prefix = $options{prefix};
+ $flags = $options{flags};
+ } else {
+ $prefix = undef;
+ $flags = undef;
+ }
+ # Didn't have trailing '{' look on next lines
+ if (!defined $1) {
+ while (<>) {
+ if (s/^\s*\{//) {
+ last;
+ }
+ }
+ }
+
+ $seenbitshift = 0;
+ @entries = ();
+
+ # Now parse the entries
+ parse_entries (\*ARGV);
+
+ # figure out if this was a flags or enums enumeration
+
+ if (!defined $flags) {
+ $flags = $seenbitshift;
+ }
+
+ # Autogenerate a prefix
+
+ if (!defined $prefix) {
+ for (@entries) {
+ my $name = $_->[0];
+ if (defined $prefix) {
+ my $tmp = ~ ($name ^ $prefix);
+ ($tmp) = $tmp =~ /(^\xff*)/;
+ $prefix = $prefix & $tmp;
+ } else {
+ $prefix = $name;
+ }
+ }
+ # Trim so that it ends in an underscore
+ $prefix =~ s/_[^_]*$/_/;
+ }
+
+ for $entry (@entries) {
+ my ($name,$nick) = @{$entry};
+ if (!defined $nick) {
+ ($nick = $name) =~ s/^$prefix//;
+ $nick =~ tr/_/-/;
+ $nick = lc($nick);
+ @{$entry} = ($name, $nick);
+ }
+ }
+
+ # Spit out the output
+
+ my $valuename = $enumname;
+ $valuename =~ s/([^A-Z])([A-Z])/$1_$2/g;
+ $valuename =~ s/([A-Z][A-Z])([A-Z][0-9a-z])/$1_$2/g;
+ $valuename = lc($valuename);
+
+ my $typemacro = $enumname;
+ $typemacro =~ s/([^A-Z])([A-Z])/$1_$2/g;
+ $typemacro =~ s/([A-Z][A-Z])([A-Z][0-9a-z])/$1_$2/g;
+ $typemacro = uc($valuename);
+ $typemacro =~ s/GDK_/GDK_TYPE_/g;
+
+ if ($gen_defs) {
+ if ($firstenum) {
+ print qq(\n; enumerations from "$ARGV"\n);
+ $firstenum = 0;
+ }
+
+ print "\n(define-".($flags ? "flags" : "enum")." $enumname";
+
+ for (@entries) {
+ my ($name,$nick) = @{$_};
+ print "\n ($nick $name)";
+ }
+ print ")\n";
+
+ } elsif ($gen_arrays) {
+
+ print "static const GtkEnumValue _${valuename}_values[] = {\n";
+ for (@entries) {
+ my ($name,$nick) = @{$_};
+ print qq( { $name, "$name", "$nick" },\n);
+ }
+ print " { 0, NULL, NULL }\n";
+ print "};\n";
+ } elsif ($gen_includes) {
+ print "GType ${valuename}_get_type (void);\n";
+ print "#define ${typemacro} ${valuename}_get_type ()\n";
+ } elsif ($gen_cfile) {
+ print (<<EOF);
+GType
+${valuename}_get_type (void)
+{
+ static GType etype = 0;
+ if (etype == 0)
+ {
+EOF
+ if ($flags) {
+ print " static const GFlagsValue values[] = {\n";
+ } else {
+ print " static const GEnumValue values[] = {\n";
+ }
+ for (@entries) {
+ my ($name,$nick) = @{$_};
+ print qq( { $name, "$name", "$nick" },\n);
+ }
+ print " { 0, NULL, NULL }\n";
+ print " };\n";
+
+ if ($flags) {
+ print " etype = g_flags_register_static (\"$enumname\", values);\n";
+ } else {
+ print " etype = g_enum_register_static (\"$enumname\", values);\n";
+ }
+
+ print (<<EOF);
+ }
+ return etype;
+}
+EOF
+ }
+ print "\n";
+ }
+ }
+
+
+if ($gen_includes) {
+ print "#endif /* __GDK_ENUMS_H__ */\n";
+}
diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am
index b52021f63..a2fc09f29 100644
--- a/gdk/x11/Makefile.am
+++ b/gdk/x11/Makefile.am
@@ -70,6 +70,10 @@ libgdk_x11_la_SOURCES = \
gdkx.h \
gdkprivate-x11.h \
gdkinputprivate.h \
+ xsettings-client.h \
+ xsettings-client.c \
+ xsettings-common.h \
+ xsettings-common.c \
$(xinput_sources)
libgdkinclude_HEADERS = \
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c
index ccb50711a..bcb70be44 100644
--- a/gdk/x11/gdkevents-x11.c
+++ b/gdk/x11/gdkevents-x11.c
@@ -31,6 +31,8 @@
#include "gdkkeysyms.h"
+#include "xsettings-client.h"
+
#if HAVE_CONFIG_H
# include <config.h>
# if STDC_HEADERS
@@ -103,6 +105,15 @@ GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
GdkEvent *event,
gpointer data);
+static void gdk_xsettings_watch_cb (Window window,
+ Bool is_start,
+ long mask,
+ void *cb_data);
+static void gdk_xsettings_notify_cb (const char *name,
+ XSettingsAction action,
+ XSettingsSetting *setting,
+ void *data);
+
/* Private variable declarations
*/
@@ -125,6 +136,8 @@ static GPollFD event_poll_fd;
static Window wmspec_check_window = None;
+static XSettingsClient *xsettings_client;
+
/*********************************************
* Functions for maintaining the event queue *
*********************************************/
@@ -151,6 +164,11 @@ gdk_events_init (void)
gdk_add_client_message_filter (gdk_wm_protocols,
gdk_wm_protocols_filter, NULL);
+
+ xsettings_client = xsettings_client_new (gdk_display, DefaultScreen (gdk_display),
+ gdk_xsettings_notify_cb,
+ gdk_xsettings_watch_cb,
+ NULL);
}
/*
@@ -1772,5 +1790,156 @@ gdk_net_wm_supports (GdkAtom property)
return gdk_net_wm_supports (property);
}
+static struct
+{
+ const char *xsettings_name;
+ const char *gdk_name;
+} settings_map[] = {
+ { "Net/DoubleClickTime", "double-click-timeout" },
+ { "Net/DragThreshold", "drag-threshold" }
+};
+static void
+gdk_xsettings_notify_cb (const char *name,
+ XSettingsAction action,
+ XSettingsSetting *setting,
+ void *data)
+{
+ GdkEvent new_event;
+ int i;
+ new_event.type = GDK_SETTING;
+ new_event.setting.window = NULL;
+ new_event.setting.send_event = FALSE;
+ new_event.setting.name = NULL;
+
+ for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
+ if (strcmp (settings_map[i].xsettings_name, name) == 0)
+ {
+ new_event.setting.name = g_strdup (settings_map[i].gdk_name);
+ break;
+ }
+
+ if (!new_event.setting.name)
+ return;
+
+ switch (action)
+ {
+ case XSETTINGS_ACTION_NEW:
+ new_event.setting.action = GDK_SETTING_ACTION_NEW;
+ break;
+ case XSETTINGS_ACTION_CHANGED:
+ new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
+ break;
+ case XSETTINGS_ACTION_DELETED:
+ new_event.setting.action = GDK_SETTING_ACTION_DELETED;
+ break;
+ }
+
+ gdk_event_put (&new_event);
+}
+
+static gboolean
+check_transform (const gchar *xsettings_name,
+ GType src_type,
+ GType dest_type)
+{
+ if (!g_value_type_transformable (src_type, dest_type))
+ {
+ g_warning ("Cannot tranform xsetting %s of type %s to type %s\n",
+ xsettings_name,
+ g_type_name (src_type),
+ g_type_name (dest_type));
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+gboolean
+gdk_setting_get (const gchar *name,
+ GValue *value)
+{
+ const char *xsettings_name = NULL;
+ XSettingsResult result;
+ XSettingsSetting *setting;
+ gboolean success = FALSE;
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
+ if (strcmp (settings_map[i].gdk_name, name) == 0)
+ {
+ xsettings_name = settings_map[i].xsettings_name;
+ break;
+ }
+
+ if (!xsettings_name)
+ return FALSE;
+
+ result = xsettings_client_get_setting (xsettings_client, xsettings_name, &setting);
+ if (result != XSETTINGS_SUCCESS)
+ return FALSE;
+
+ switch (setting->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
+ {
+ g_value_set_int (value, setting->data.v_int);
+ success = TRUE;
+ }
+ break;
+ case XSETTINGS_TYPE_STRING:
+ if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
+ {
+ g_value_set_string (value, setting->data.v_string);
+ success = TRUE;
+ }
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
+ {
+ GdkColor color;
+
+ color.pixel = 0;
+ color.red = setting->data.v_color.red;
+ color.green = setting->data.v_color.green;
+ color.blue = setting->data.v_color.blue;
+
+ g_value_set_boxed (value, &color);
+
+ success = TRUE;
+ }
+ break;
+ }
+
+ xsettings_setting_free (setting);
+
+ return success;
+}
+
+GdkFilterReturn
+gdk_xsettings_client_event_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ if (xsettings_client_process_event (xsettings_client, (XEvent *)xevent))
+ return GDK_FILTER_REMOVE;
+ else
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+gdk_xsettings_watch_cb (Window window,
+ Bool is_start,
+ long mask,
+ void *cb_data)
+{
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_window_lookup (window);
+ if (is_start)
+ gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
+ else
+ gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, NULL);
+}
diff --git a/gdk/x11/xsettings-client.c b/gdk/x11/xsettings-client.c
new file mode 100644
index 000000000..fc4ef8065
--- /dev/null
+++ b/gdk/x11/xsettings-client.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xmd.h> /* For CARD16 */
+
+#include "xsettings-client.h"
+
+struct _XSettingsClient
+{
+ Display *display;
+ int screen;
+ XSettingsNotifyFunc notify;
+ XSettingsWatchFunc watch;
+ void *cb_data;
+
+ Window manager_window;
+ Atom manager_atom;
+ Atom selection_atom;
+ Atom xsettings_atom;
+
+ XSettingsList *settings;
+};
+
+static void
+notify_changes (XSettingsClient *client,
+ XSettingsList *old_list)
+{
+ XSettingsList *old_iter = old_list;
+ XSettingsList *new_iter = client->settings;
+
+ if (!client->notify)
+ return;
+
+ while (old_iter || new_iter)
+ {
+ int cmp;
+
+ if (old_iter && new_iter)
+ cmp = strcmp (old_iter->setting->name, new_iter->setting->name);
+ else if (old_iter)
+ cmp = -1;
+ else
+ cmp = 1;
+
+ if (cmp < 0)
+ {
+ client->notify (old_iter->setting->name,
+ XSETTINGS_ACTION_DELETED,
+ NULL,
+ client->cb_data);
+ }
+ else if (cmp == 0)
+ {
+ if (!xsettings_setting_equal (old_iter->setting,
+ new_iter->setting))
+ client->notify (old_iter->setting->name,
+ XSETTINGS_ACTION_CHANGED,
+ new_iter->setting,
+ client->cb_data);
+ }
+ else
+ {
+ client->notify (new_iter->setting->name,
+ XSETTINGS_ACTION_NEW,
+ new_iter->setting,
+ client->cb_data);
+ }
+
+ if (old_iter)
+ old_iter = old_iter->next;
+ if (new_iter)
+ new_iter = new_iter->next;
+ }
+}
+
+static int
+ignore_errors (Display *display, XErrorEvent *event)
+{
+ return True;
+}
+
+static char local_byte_order = '\0';
+
+#define BYTES_LEFT(buffer) ((buffer)->data + (buffer)->len - (buffer)->pos)
+
+static XSettingsResult
+fetch_card16 (XSettingsBuffer *buffer,
+ CARD16 *result)
+{
+ CARD16 x;
+
+ if (BYTES_LEFT (buffer) < 2)
+ return XSETTINGS_ACCESS;
+
+ x = *(CARD16 *)buffer->pos;
+ buffer->pos += 2;
+
+ if (buffer->byte_order == local_byte_order)
+ *result = x;
+ else
+ *result = (x << 8) | (x >> 8);
+
+ return XSETTINGS_SUCCESS;
+}
+
+static XSettingsResult
+fetch_ushort (XSettingsBuffer *buffer,
+ unsigned short *result)
+{
+ CARD16 x;
+ XSettingsResult r;
+
+ r = fetch_card16 (buffer, &x);
+ if (r == XSETTINGS_SUCCESS)
+ *result = x;
+
+ return r;
+}
+
+static XSettingsResult
+fetch_card32 (XSettingsBuffer *buffer,
+ CARD32 *result)
+{
+ CARD32 x;
+
+ if (BYTES_LEFT (buffer) < 4)
+ return XSETTINGS_ACCESS;
+
+ x = *(CARD32 *)buffer->pos;
+ buffer->pos += 4;
+
+ if (buffer->byte_order == local_byte_order)
+ *result = x;
+ else
+ *result = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
+
+ return XSETTINGS_SUCCESS;
+}
+
+static XSettingsResult
+fetch_card8 (XSettingsBuffer *buffer,
+ CARD8 *result)
+{
+ if (BYTES_LEFT (buffer) < 1)
+ return XSETTINGS_ACCESS;
+
+ *result = *(CARD32 *)buffer->pos;
+ buffer->pos += 1;
+
+ return XSETTINGS_SUCCESS;
+}
+
+#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1)))
+
+static XSettingsList *
+parse_settings (unsigned char *data,
+ size_t len)
+{
+ XSettingsBuffer buffer;
+ XSettingsResult result = XSETTINGS_SUCCESS;
+ XSettingsList *settings = NULL;
+ CARD32 serial;
+ CARD32 n_entries;
+ CARD32 i;
+ XSettingsSetting *setting = NULL;
+
+ local_byte_order = xsettings_byte_order ();
+
+ buffer.pos = buffer.data = data;
+ buffer.len = len;
+
+ result = fetch_card8 (&buffer, &buffer.byte_order);
+ if (buffer.byte_order != MSBFirst &&
+ buffer.byte_order != LSBFirst)
+ {
+ fprintf (stderr, "Invalid byte order in XSETTINGS property\n");
+ result = XSETTINGS_FAILED;
+ goto out;
+ }
+
+ buffer.pos += 3;
+
+ result = fetch_card32 (&buffer, &serial);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+
+ result = fetch_card32 (&buffer, &n_entries);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+
+ for (i = 0; i < n_entries; i++)
+ {
+ CARD8 type;
+ CARD16 name_len;
+ CARD32 v_int;
+ size_t pad_len;
+
+ result = fetch_card8 (&buffer, &type);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+
+ buffer.pos += 1;
+
+ result = fetch_card16 (&buffer, &name_len);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+
+ pad_len = XSETTINGS_PAD(name_len, 4);
+ if (BYTES_LEFT (&buffer) < pad_len)
+ {
+ result = XSETTINGS_ACCESS;
+ goto out;
+ }
+
+ setting = malloc (sizeof *setting);
+ if (!setting)
+ {
+ result = XSETTINGS_NO_MEM;
+ goto out;
+ }
+ setting->type = XSETTINGS_TYPE_INT; /* No allocated memory */
+
+ setting->name = malloc (name_len + 1);
+ if (!setting->name)
+ {
+ result = XSETTINGS_NO_MEM;
+ goto out;
+ }
+
+ memcpy (setting->name, buffer.pos, name_len);
+ setting->name[name_len] = '\0';
+ buffer.pos += pad_len;
+
+ result = fetch_card32 (&buffer, &v_int);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+ setting->last_change_serial = v_int;
+
+ switch (type)
+ {
+ case XSETTINGS_TYPE_INT:
+ result = fetch_card32 (&buffer, &v_int);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+
+ setting->data.v_int = (INT32)v_int;
+ break;
+ case XSETTINGS_TYPE_STRING:
+ result = fetch_card32 (&buffer, &v_int);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+
+ pad_len = XSETTINGS_PAD (v_int, 4);
+ if (v_int + 1 == 0 || /* Guard against wrap-around */
+ BYTES_LEFT (&buffer) < pad_len)
+ {
+ result = XSETTINGS_ACCESS;
+ goto out;
+ }
+
+ setting->data.v_string = malloc (v_int + 1);
+ if (!setting->data.v_string)
+ {
+ result = XSETTINGS_NO_MEM;
+ goto out;
+ }
+
+ memcpy (setting->data.v_string, buffer.pos, v_int);
+ setting->data.v_string[v_int] = '\0';
+ buffer.pos += pad_len;
+
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ result = fetch_ushort (&buffer, &setting->data.v_color.red);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+ result = fetch_ushort (&buffer, &setting->data.v_color.green);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+ result = fetch_ushort (&buffer, &setting->data.v_color.blue);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+ result = fetch_ushort (&buffer, &setting->data.v_color.alpha);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+
+ break;
+ default:
+ /* Quietly ignore unknown types */
+ break;
+ }
+
+ setting->type = type;
+
+ result = xsettings_list_insert (&settings, setting);
+ if (result != XSETTINGS_SUCCESS)
+ goto out;
+
+ setting = NULL;
+ }
+
+ out:
+
+ if (result != XSETTINGS_SUCCESS)
+ {
+ switch (result)
+ {
+ case XSETTINGS_NO_MEM:
+ fprintf(stderr, "Out of memory reading XSETTINGS property\n");
+ break;
+ case XSETTINGS_ACCESS:
+ fprintf(stderr, "Invalid XSETTINGS property (read off end)\n");
+ break;
+ case XSETTINGS_DUPLICATE_ENTRY:
+ fprintf (stderr, "Duplicate XSETTINGS entry for '%s'\n", setting->name);
+ case XSETTINGS_FAILED:
+ case XSETTINGS_SUCCESS:
+ case XSETTINGS_NO_ENTRY:
+ break;
+ }
+
+ if (setting)
+ xsettings_setting_free (setting);
+
+ xsettings_list_free (settings);
+ settings = NULL;
+
+ }
+
+ return settings;
+}
+
+static void
+read_settings (XSettingsClient *client)
+{
+ Atom type;
+ int format;
+ unsigned long n_items;
+ unsigned long bytes_after;
+ unsigned char *data;
+ int result;
+
+ int (*old_handler) (Display *, XErrorEvent *);
+
+ XSettingsList *old_list = client->settings;
+
+ client->settings = NULL;
+
+ old_handler = XSetErrorHandler (ignore_errors);
+ result = XGetWindowProperty (client->display, client->manager_window,
+ client->xsettings_atom, 0, LONG_MAX,
+ False, client->xsettings_atom,
+ &type, &format, &n_items, &bytes_after, &data);
+ XSetErrorHandler (old_handler);
+
+ if (result == Success && type == client->xsettings_atom)
+ {
+ if (format != 8)
+ {
+ fprintf (stderr, "Invalid format for XSETTINGS property %d", format);
+ }
+ else
+ client->settings = parse_settings (data, n_items);
+
+ XFree (data);
+ }
+
+ notify_changes (client, old_list);
+ xsettings_list_free (old_list);
+}
+
+static void
+add_events (Display *display,
+ Window window,
+ long mask)
+{
+ XWindowAttributes attr;
+
+ XGetWindowAttributes (display, window, &attr);
+ XSelectInput (display, window, attr.your_event_mask | mask);
+}
+
+static void
+check_manager_window (XSettingsClient *client)
+{
+ if (client->manager_window && client->watch)
+ client->watch (client->manager_window, False, 0, client->cb_data);
+
+ XGrabServer (client->display);
+
+ client->manager_window = XGetSelectionOwner (client->display,
+ client->selection_atom);
+ if (client->manager_window)
+ XSelectInput (client->display, client->manager_window,
+ PropertyChangeMask | StructureNotifyMask);
+
+ XUngrabServer (client->display);
+ XFlush (client->display);
+
+ if (client->manager_window && client->watch)
+ client->watch (client->manager_window, True,
+ PropertyChangeMask | StructureNotifyMask,
+ client->cb_data);
+
+ read_settings (client);
+}
+
+XSettingsClient *
+xsettings_client_new (Display *display,
+ int screen,
+ XSettingsNotifyFunc notify,
+ XSettingsWatchFunc watch,
+ void *cb_data)
+{
+ XSettingsClient *client;
+ char buffer[256];
+
+ client = malloc (sizeof *client);
+ if (!client)
+ return NULL;
+
+ client->display = display;
+ client->screen = screen;
+ client->notify = notify;
+ client->watch = watch;
+ client->cb_data = cb_data;
+
+ client->manager_window = None;
+ client->settings = NULL;
+
+ sprintf(buffer, "_XSETTINGS_S%d", screen);
+ client->selection_atom = XInternAtom (display, buffer, False);
+ client->xsettings_atom = XInternAtom (display, "_XSETTINGS_SETTINGS", False);
+ client->manager_atom = XInternAtom (display, "MANAGER", False);
+
+ /* Select on StructureNotify so we get MANAGER events
+ */
+ add_events (display, RootWindow (display, screen), StructureNotifyMask);
+
+ if (client->watch)
+ client->watch (RootWindow (display, screen), True, StructureNotifyMask,
+ client->cb_data);
+
+ check_manager_window (client);
+
+ return client;
+}
+
+void
+xsettings_client_destroy (XSettingsClient *client)
+{
+ if (client->watch)
+ client->watch (RootWindow (client->display, client->screen),
+ False, 0, client->cb_data);
+ if (client->manager_window && client->watch)
+ client->watch (client->manager_window, False, 0, client->cb_data);
+
+ xsettings_list_free (client->settings);
+ free (client);
+}
+
+XSettingsResult
+xsettings_client_get_setting (XSettingsClient *client,
+ const char *name,
+ XSettingsSetting **setting)
+{
+ XSettingsSetting *search = xsettings_list_lookup (client->settings, name);
+ if (search)
+ {
+ *setting = xsettings_setting_copy (search);
+ return *setting ? XSETTINGS_SUCCESS : XSETTINGS_NO_MEM;
+ }
+ else
+ return XSETTINGS_NO_ENTRY;
+}
+
+Bool
+xsettings_client_process_event (XSettingsClient *client,
+ XEvent *xev)
+{
+ /* The checks here will not unlikely cause us to reread
+ * the properties from the manager window a number of
+ * times when the manager changes from A->B. But manager changes
+ * are going to be pretty rare.
+ */
+ if (xev->xany.window == RootWindow (client->display, client->screen))
+ {
+ if (xev->xany.type == ClientMessage &&
+ xev->xclient.message_type == client->manager_atom)
+ {
+ check_manager_window (client);
+ return True;
+ }
+ }
+ else if (xev->xany.window == client->manager_window)
+ {
+ if (xev->xany.type == DestroyNotify)
+ {
+ check_manager_window (client);
+ return True;
+ }
+ else if (xev->xany.type == PropertyNotify)
+ {
+ read_settings (client);
+ return True;
+ }
+ }
+
+ return False;
+}
diff --git a/gdk/x11/xsettings-client.h b/gdk/x11/xsettings-client.h
new file mode 100644
index 000000000..12018295f
--- /dev/null
+++ b/gdk/x11/xsettings-client.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#ifndef XSETTINGS_CLIENT_H
+#define XSETTINGS_CLIENT_H
+
+#include <X11/Xlib.h>
+#include "xsettings-common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _XSettingsClient XSettingsClient;
+
+typedef enum
+{
+ XSETTINGS_ACTION_NEW,
+ XSETTINGS_ACTION_CHANGED,
+ XSETTINGS_ACTION_DELETED,
+} XSettingsAction;
+
+typedef void (*XSettingsNotifyFunc) (const char *name,
+ XSettingsAction action,
+ XSettingsSetting *setting,
+ void *cb_data);
+typedef void (*XSettingsWatchFunc) (Window window,
+ Bool is_start,
+ long mask,
+ void *cb_data);
+
+XSettingsClient *xsettings_client_new (Display *display,
+ int screen,
+ XSettingsNotifyFunc notify,
+ XSettingsWatchFunc watch,
+ void *cb_data);
+void xsettings_client_destroy (XSettingsClient *client);
+Bool xsettings_client_process_event (XSettingsClient *client,
+ XEvent *xev);
+
+XSettingsResult xsettings_client_get_setting (XSettingsClient *client,
+ const char *name,
+ XSettingsSetting **setting);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* XSETTINGS_CLIENT_H */
diff --git a/gdk/x11/xsettings-common.c b/gdk/x11/xsettings-common.c
new file mode 100644
index 000000000..750771456
--- /dev/null
+++ b/gdk/x11/xsettings-common.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#include "string.h"
+#include "stdlib.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xmd.h> /* For CARD32 */
+
+#include "xsettings-common.h"
+
+XSettingsSetting *
+xsettings_setting_copy (XSettingsSetting *setting)
+{
+ XSettingsSetting *result;
+ size_t str_len;
+
+ result = malloc (sizeof *result);
+ if (!result)
+ return NULL;
+
+ str_len = strlen (setting->name);
+ result->name = malloc (str_len + 1);
+ if (!result->name)
+ goto err;
+
+ memcpy (result->name, setting->name, str_len + 1);
+
+ result->type = setting->type;
+
+ switch (setting->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ result->data.v_int = setting->data.v_int;
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ result->data.v_color = setting->data.v_color;
+ break;
+ case XSETTINGS_TYPE_STRING:
+ str_len = strlen (setting->data.v_string);
+ result->data.v_string = malloc (str_len + 1);
+ if (!result->data.v_string)
+ goto err;
+
+ memcpy (result->data.v_string, setting->data.v_string, str_len + 1);
+ break;
+ }
+
+ result->last_change_serial = setting->last_change_serial;
+
+ return result;
+
+ err:
+ if (result->name)
+ free (result->name);
+ free (result);
+
+ return NULL;
+}
+
+XSettingsList *
+xsettings_list_copy (XSettingsList *list)
+{
+ XSettingsList *new = NULL;
+ XSettingsList *old_iter = list;
+ XSettingsList *new_iter = NULL;
+
+ while (old_iter)
+ {
+ XSettingsList *new_node;
+
+ new_node = malloc (sizeof *new_node);
+ if (!new_node)
+ goto error;
+
+ new_node->setting = xsettings_setting_copy (old_iter->setting);
+ if (!new_node->setting)
+ {
+ free (new_node);
+ goto error;
+ }
+
+ if (new_iter)
+ new_iter->next = new_node;
+ else
+ new = new_node;
+
+ new_iter = new_node;
+
+ old_iter = old_iter->next;
+ }
+
+ return new;
+
+ error:
+ xsettings_list_free (new);
+ return NULL;
+}
+
+int
+xsettings_setting_equal (XSettingsSetting *setting_a,
+ XSettingsSetting *setting_b)
+{
+ if (setting_a->type != setting_b->type)
+ return 0;
+
+ if (strcmp (setting_a->name, setting_b->name) != 0)
+ return 0;
+
+ switch (setting_a->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ return setting_a->data.v_int == setting_b->data.v_int;
+ case XSETTINGS_TYPE_COLOR:
+ return (setting_a->data.v_color.red == setting_b->data.v_color.red &&
+ setting_a->data.v_color.green == setting_b->data.v_color.green &&
+ setting_a->data.v_color.blue == setting_b->data.v_color.blue &&
+ setting_a->data.v_color.alpha == setting_b->data.v_color.alpha);
+ case XSETTINGS_TYPE_STRING:
+ return strcmp (setting_a->data.v_string, setting_b->data.v_string) == 0;
+ }
+
+ return 0;
+}
+
+void
+xsettings_setting_free (XSettingsSetting *setting)
+{
+ if (setting->type == XSETTINGS_TYPE_STRING)
+ free (setting->data.v_string);
+
+ free (setting);
+}
+
+void
+xsettings_list_free (XSettingsList *list)
+{
+ while (list)
+ {
+ XSettingsList *next = list->next;
+
+ xsettings_setting_free (list->setting);
+ free (list);
+
+ list = next;
+ }
+}
+
+XSettingsResult
+xsettings_list_insert (XSettingsList **list,
+ XSettingsSetting *setting)
+{
+ XSettingsList *node;
+ XSettingsList *iter;
+ XSettingsList *last = NULL;
+
+ node = malloc (sizeof *node);
+ if (!node)
+ return XSETTINGS_NO_MEM;
+ node->setting = setting;
+
+ iter = *list;
+ while (iter)
+ {
+ int cmp = strcmp (setting->name, iter->setting->name);
+
+ if (cmp < 0)
+ break;
+ else if (cmp == 0)
+ {
+ free (node);
+ return XSETTINGS_DUPLICATE_ENTRY;
+ }
+
+ last = iter;
+ iter = iter->next;
+ }
+
+ if (last)
+ last->next = node;
+ else
+ *list = node;
+
+ node->next = iter;
+
+ return XSETTINGS_SUCCESS;
+}
+
+XSettingsResult
+xsettings_list_delete (XSettingsList **list,
+ const char *name)
+{
+ XSettingsList *iter;
+ XSettingsList *last = NULL;
+
+ iter = *list;
+ while (iter)
+ {
+ if (strcmp (name, iter->setting->name) == 0)
+ {
+ if (last)
+ last->next = iter->next;
+ else
+ *list = iter->next;
+
+ xsettings_setting_free (iter->setting);
+ free (iter);
+
+ return XSETTINGS_SUCCESS;
+ }
+
+ last = iter;
+ iter = iter->next;
+ }
+
+ return XSETTINGS_FAILED;
+}
+
+XSettingsSetting *
+xsettings_list_lookup (XSettingsList *list,
+ const char *name)
+{
+ XSettingsList *iter;
+
+ iter = list;
+ while (iter)
+ {
+ if (strcmp (name, iter->setting->name) == 0)
+ return iter->setting;
+
+ iter = iter->next;
+ }
+
+ return NULL;
+}
+
+char
+xsettings_byte_order (void)
+{
+ CARD32 myint = 0x01020304;
+ return (*(char *)&myint == 1) ? MSBFirst : LSBFirst;
+}
diff --git a/gdk/x11/xsettings-common.h b/gdk/x11/xsettings-common.h
new file mode 100644
index 000000000..e3af4a662
--- /dev/null
+++ b/gdk/x11/xsettings-common.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#ifndef XSETTINGS_COMMON_H
+#define XSETTINGS_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _XSettingsBuffer XSettingsBuffer;
+typedef struct _XSettingsColor XSettingsColor;
+typedef struct _XSettingsList XSettingsList;
+typedef struct _XSettingsSetting XSettingsSetting;
+
+/* Types of settings possible. Enum values correspond to
+ * protocol values.
+ */
+typedef enum
+{
+ XSETTINGS_TYPE_INT = 0,
+ XSETTINGS_TYPE_STRING = 1,
+ XSETTINGS_TYPE_COLOR = 2
+} XSettingsType;
+
+typedef enum
+{
+ XSETTINGS_SUCCESS,
+ XSETTINGS_NO_MEM,
+ XSETTINGS_ACCESS,
+ XSETTINGS_FAILED,
+ XSETTINGS_NO_ENTRY,
+ XSETTINGS_DUPLICATE_ENTRY
+} XSettingsResult;
+
+struct _XSettingsBuffer
+{
+ char byte_order;
+ size_t len;
+ unsigned char *data;
+ unsigned char *pos;
+};
+
+struct _XSettingsColor
+{
+ unsigned short red, green, blue, alpha;
+};
+
+struct _XSettingsList
+{
+ XSettingsSetting *setting;
+ XSettingsList *next;
+};
+
+struct _XSettingsSetting
+{
+ char *name;
+ XSettingsType type;
+
+ union {
+ int v_int;
+ char *v_string;
+ XSettingsColor v_color;
+ } data;
+
+ unsigned long last_change_serial;
+};
+
+XSettingsSetting *xsettings_setting_copy (XSettingsSetting *setting);
+void xsettings_setting_free (XSettingsSetting *setting);
+int xsettings_setting_equal (XSettingsSetting *setting_a,
+ XSettingsSetting *setting_b);
+
+void xsettings_list_free (XSettingsList *list);
+XSettingsList *xsettings_list_copy (XSettingsList *list);
+XSettingsResult xsettings_list_insert (XSettingsList **list,
+ XSettingsSetting *setting);
+XSettingsSetting *xsettings_list_lookup (XSettingsList *list,
+ const char *name);
+XSettingsResult xsettings_list_delete (XSettingsList **list,
+ const char *name);
+
+char xsettings_byte_order (void);
+
+#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1)))
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* XSETTINGS_COMMON_H */