From 3a46642b081c504b6e25c65d81999fcc0dff5fb2 Mon Sep 17 00:00:00 2001 From: Jan D Date: Wed, 11 Aug 2010 20:28:10 +0200 Subject: [PATCH] Take colors for region face (selected text) from the Gtk+ theme. * lisp/dynamic-setting.el (dynamic-setting-handle-config-changed-event): Handle theme-name change. * lisp/faces.el (region): Add type gtk that uses gtk colors. * src/gtkutil.c (xg_check_special_colors, style_changed_cb): New functions. (xg_create_frame_widgets): Connect theme name changes to style_changed_cb. * src/gtkutil.h (xg_check_special_colors): Declare. * src/xfns.c (x_defined_color): If USE_GTK, call xg_check_special_colors first. --- etc/NEWS | 3 ++ lisp/ChangeLog | 7 ++++ lisp/dynamic-setting.el | 5 +++ lisp/faces.el | 3 ++ src/ChangeLog | 9 ++++++ src/gtkutil.c | 71 +++++++++++++++++++++++++++++++++++++++++ src/gtkutil.h | 3 ++ src/xfns.c | 8 +++-- 8 files changed, 107 insertions(+), 2 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 9837e6c95b8..a8908379ce4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -109,6 +109,9 @@ The frame-parameter tool-bar-position controls this. It takes the values top, left, tight or bottom. The Options => Show/Hide menu has entries for this. +** The colors for selected text (the region face) are taken from the GTK +theme when Emacs is built with GTK. + ** Emacs uses GTK tooltips by default if built with GTK. You can turn that off by customizing x-gtk-use-system-tooltips. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 6f15ae942fc..763ffd0dd0f 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,10 @@ +2010-08-11 Jan Djärv + + * faces.el (region): Add type gtk that uses gtk colors. + + * dynamic-setting.el (dynamic-setting-handle-config-changed-event): + Handle theme-name change. + 2010-08-10 Michael R. Mauger * progmodes/sql.el: Version 2.5 diff --git a/lisp/dynamic-setting.el b/lisp/dynamic-setting.el index f61a0078e17..790aaf7170e 100644 --- a/lisp/dynamic-setting.el +++ b/lisp/dynamic-setting.el @@ -96,6 +96,11 @@ Changes can be ((eq type 'font-render) (font-setting-change-default-font display-name nil)) + ;; This is a bit heavy, ideally we would just clear faces + ;; on the affected display, and perhaps only the relevant + ;; faces. Oh well. + ((eq type 'theme-name) (clear-face-cache)) + ((eq type 'tool-bar-style) (force-mode-line-update t))))) (define-key special-event-map [config-changed-event] diff --git a/lisp/faces.el b/lisp/faces.el index b7c238e14f3..d8b6f20035c 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -2281,6 +2281,9 @@ terminal type to a different value." (defface region '((((class color) (min-colors 88) (background dark)) :background "blue3") + (((class color) (min-colors 88) (background light) (type gtk)) + :foreground "gtk_selection_fg_color" + :background "gtk_selection_bg_color") (((class color) (min-colors 88) (background light) (type ns)) :background "ns_selection_color") (((class color) (min-colors 88) (background light)) diff --git a/src/ChangeLog b/src/ChangeLog index 89414fa4d78..1275b4a8def 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,14 @@ 2010-08-11 Jan Djärv + * xfns.c (x_defined_color): If USE_GTK, call xg_check_special_colors + first. + + * gtkutil.h (xg_check_special_colors): Declare. + + * gtkutil.c (xg_check_special_colors, style_changed_cb): New functions. + (xg_create_frame_widgets): Connect theme name changes to + style_changed_cb. + * xterm.c (emacs_class): New char[] for EMACS_CLASS. (xim_open_dpy, xim_initialize, xim_close_dpy): Use emacs_class. (x_term_init): Use char[] display_opt and name_opt instead of diff --git a/src/gtkutil.c b/src/gtkutil.c index a9f2d103702..fd89015aedc 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -506,6 +506,41 @@ get_utf8_string (const char *str) return utf8_str; } +/* Check for special colors used in face spec for region face. + The colors are fetched from the Gtk+ theme. + Return 1 if color was found, 0 if not. */ + +int +xg_check_special_colors (struct frame *f, + const char *color_name, + XColor *color) +{ + int success_p = 0; + if (FRAME_GTK_WIDGET (f)) + { + if (strcmp ("gtk_selection_bg_color", color_name) == 0) + { + GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); + color->red = gsty->bg[GTK_STATE_SELECTED].red; + color->green = gsty->bg[GTK_STATE_SELECTED].green; + color->blue = gsty->bg[GTK_STATE_SELECTED].blue; + color->pixel = gsty->bg[GTK_STATE_SELECTED].pixel; + success_p = 1; + } + else if (strcmp ("gtk_selection_fg_color", color_name) == 0) + { + GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); + color->red = gsty->fg[GTK_STATE_SELECTED].red; + color->green = gsty->fg[GTK_STATE_SELECTED].green; + color->blue = gsty->fg[GTK_STATE_SELECTED].blue; + color->pixel = gsty->fg[GTK_STATE_SELECTED].pixel; + success_p = 1; + } + } + + return success_p; +} + /*********************************************************************** @@ -898,6 +933,26 @@ xg_pix_to_gcolor (GtkWidget *w, long unsigned int pixel, GdkColor *c) gdk_colormap_query_color (map, pixel, c); } +/* Callback called when the gtk theme changes. + We notify lisp code so it can fix faces used for region for example. */ + +static void +style_changed_cb (GObject *go, + GParamSpec *spec, + gpointer user_data) +{ + struct input_event event; + GdkDisplay *gdpy = (GdkDisplay *) user_data; + const char *display_name = gdk_display_get_name (gdpy); + + EVENT_INIT (event); + event.kind = CONFIG_CHANGED_EVENT; + event.frame_or_window = make_string (display_name, strlen (display_name)); + /* Theme doesn't change often, so intern is called seldom. */ + event.arg = intern ("theme-name"); + kbd_buffer_store_event (&event); +} + /* Create and set up the GTK widgets for frame F. Return 0 if creation failed, non-zero otherwise. */ @@ -1023,6 +1078,22 @@ xg_create_frame_widgets (FRAME_PTR f) g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f); #endif + { + GdkScreen *screen = gtk_widget_get_screen (wtop); + GtkSettings *gs = gtk_settings_get_for_screen (screen); + /* Only connect this signal once per screen. */ + if (! g_signal_handler_find (G_OBJECT (gs), + G_SIGNAL_MATCH_FUNC, + 0, 0, 0, + G_CALLBACK (style_changed_cb), + 0)) + { + g_signal_connect (G_OBJECT (gs), "notify::gtk-theme-name", + G_CALLBACK (style_changed_cb), + gdk_screen_get_display (screen)); + } + } + UNBLOCK_INPUT; return 1; diff --git a/src/gtkutil.h b/src/gtkutil.h index 6e86425fb74..9b796e1138c 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -156,6 +156,9 @@ extern void x_wm_set_size_hint (FRAME_PTR f, long flags, int user_position); extern void xg_set_background_color (FRAME_PTR f, unsigned long bg); +extern int xg_check_special_colors (struct frame *f, + const char *color_name, + XColor *color); extern void xg_set_frame_icon (FRAME_PTR f, Pixmap icon_pixmap, diff --git a/src/xfns.c b/src/xfns.c index bc28ccd3a63..8544d9e3e10 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -648,12 +648,16 @@ int x_defined_color (struct frame *f, const char *color_name, XColor *color, int alloc_p) { - int success_p; + int success_p = 0; Display *dpy = FRAME_X_DISPLAY (f); Colormap cmap = FRAME_X_COLORMAP (f); BLOCK_INPUT; - success_p = XParseColor (dpy, cmap, color_name, color); +#ifdef USE_GTK + success_p = xg_check_special_colors (f, color_name, color); +#endif + if (!success_p) + success_p = XParseColor (dpy, cmap, color_name, color); if (success_p && alloc_p) success_p = x_alloc_nearest_color (f, cmap, color); UNBLOCK_INPUT; -- 2.39.2