diff options
author | Owen Taylor <otaylor@redhat.com> | 2001-04-02 23:33:47 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2001-04-02 23:33:47 +0000 |
commit | b52b326d5f34b09af70e9f277a43b48c5bf3be2d (patch) | |
tree | 2593b2dffad11ac442a89514a39988d75e53701d /gdk | |
parent | 0aef43bcbcb208d7419711ffd48dd7942d538952 (diff) | |
download | gdk-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.am | 31 | ||||
-rw-r--r-- | gdk/gdk.c | 2 | ||||
-rw-r--r-- | gdk/gdk.h | 3 | ||||
-rw-r--r-- | gdk/gdkcolor.c | 32 | ||||
-rw-r--r-- | gdk/gdkcolor.h | 3 | ||||
-rw-r--r-- | gdk/gdkevents.c | 44 | ||||
-rw-r--r-- | gdk/gdkevents.h | 27 | ||||
-rw-r--r-- | gdk/gdkfont.c | 14 | ||||
-rw-r--r-- | gdk/gdkfont.h | 4 | ||||
-rw-r--r-- | gdk/gdkvisual.h | 4 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 6 | ||||
-rwxr-xr-x | gdk/makeenums.pl | 279 | ||||
-rw-r--r-- | gdk/x11/Makefile.am | 4 | ||||
-rw-r--r-- | gdk/x11/gdkevents-x11.c | 169 | ||||
-rw-r--r-- | gdk/x11/xsettings-client.c | 535 | ||||
-rw-r--r-- | gdk/x11/xsettings-client.h | 68 | ||||
-rw-r--r-- | gdk/x11/xsettings-common.c | 261 | ||||
-rw-r--r-- | gdk/x11/xsettings-common.h | 110 |
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 @@ -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 (); @@ -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 */ |