changeset 109749:be18c3b67d66

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.
author Jan D <jan.h.d@swipnet.se>
date Wed, 11 Aug 2010 20:28:10 +0200
parents e2f8226efb99
children 0851022edd4b
files etc/NEWS lisp/ChangeLog lisp/dynamic-setting.el lisp/faces.el src/ChangeLog src/gtkutil.c src/gtkutil.h src/xfns.c
diffstat 8 files changed, 107 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS	Wed Aug 11 14:34:46 2010 +0200
+++ b/etc/NEWS	Wed Aug 11 20:28:10 2010 +0200
@@ -109,6 +109,9 @@
 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.
 
--- a/lisp/ChangeLog	Wed Aug 11 14:34:46 2010 +0200
+++ b/lisp/ChangeLog	Wed Aug 11 20:28:10 2010 +0200
@@ -1,3 +1,10 @@
+2010-08-11  Jan Djärv  <jan.h.d@swipnet.se>
+
+	* 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  <mmaug@yahoo.com>
 
 	* progmodes/sql.el: Version 2.5
--- a/lisp/dynamic-setting.el	Wed Aug 11 14:34:46 2010 +0200
+++ b/lisp/dynamic-setting.el	Wed Aug 11 20:28:10 2010 +0200
@@ -96,6 +96,11 @@
 	  ((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]
--- a/lisp/faces.el	Wed Aug 11 14:34:46 2010 +0200
+++ b/lisp/faces.el	Wed Aug 11 20:28:10 2010 +0200
@@ -2281,6 +2281,9 @@
 (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))
--- a/src/ChangeLog	Wed Aug 11 14:34:46 2010 +0200
+++ b/src/ChangeLog	Wed Aug 11 20:28:10 2010 +0200
@@ -1,5 +1,14 @@
 2010-08-11  Jan Djärv  <jan.h.d@swipnet.se>
 
+	* 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
--- a/src/gtkutil.c	Wed Aug 11 14:34:46 2010 +0200
+++ b/src/gtkutil.c	Wed Aug 11 20:28:10 2010 +0200
@@ -506,6 +506,41 @@
   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 @@
   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 @@
   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;
--- a/src/gtkutil.h	Wed Aug 11 14:34:46 2010 +0200
+++ b/src/gtkutil.h	Wed Aug 11 20:28:10 2010 +0200
@@ -156,6 +156,9 @@
                                 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,
--- a/src/xfns.c	Wed Aug 11 14:34:46 2010 +0200
+++ b/src/xfns.c	Wed Aug 11 20:28:10 2010 +0200
@@ -648,12 +648,16 @@
 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;