]> code.delx.au - gnu-emacs/blobdiff - src/xsettings.c
Fix Myanmar OTF support
[gnu-emacs] / src / xsettings.c
index f84dd6cb7cad0b79bcd7eee5cd027a96ed8d1975..945007db2f06229fd24d2e379f173c5fd36f9a3e 100644 (file)
@@ -1,5 +1,5 @@
 /* Functions for handle font changes dynamically.
-   Copyright (C) 2009
+   Copyright (C) 2009, 2010
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -24,6 +24,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "xterm.h"
 #include "xsettings.h"
 #include "frame.h"
+#include "keyboard.h"
 #include "blockinput.h"
 #include "termhooks.h"
 #include "termopts.h"
@@ -40,6 +41,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 static char *current_mono_font;
 static struct x_display_info *first_dpyinfo;
 static Lisp_Object Qfont_name, Qfont_render;
+static int use_system_font;
+static Lisp_Object Vxft_settings;
+
 
 #ifdef HAVE_GCONF
 static GConfClient *gconf_client;
@@ -81,7 +85,7 @@ something_changedCB (client, cnxn_id, entry, user_data)
       const char *value = gconf_value_get_string (v);
       int i;
       if (current_mono_font != NULL && strcmp (value, current_mono_font) == 0)
-        return; // No change.
+        return; /* No change. */
 
       xfree (current_mono_font);
       current_mono_font = xstrdup (value);
@@ -96,7 +100,7 @@ something_changedCB (client, cnxn_id, entry, user_data)
       for (dpyinfo = x_display_list; !found && dpyinfo; dpyinfo = dpyinfo->next)
         found = dpyinfo == first_dpyinfo;
 
-      if (found)
+      if (found && use_system_font)
         store_font_changed_event (Qfont_name,
                                   XCAR (first_dpyinfo->name_list_element));
     }
@@ -105,6 +109,17 @@ something_changedCB (client, cnxn_id, entry, user_data)
 
 #ifdef HAVE_XFT
 
+/* Older fontconfig versions don't have FC_LCD_*.  */
+#ifndef FC_LCD_NONE
+#define FC_LCD_NONE 0
+#endif
+#ifndef FC_LCD_DEFAULT
+#define FC_LCD_DEFAULT 1
+#endif
+#ifndef FC_LCD_FILTER
+#define FC_LCD_FILTER "lcdfilter"
+#endif
+
 /* Find the window that contains the XSETTINGS property values.  */
 
 static void
@@ -125,11 +140,21 @@ get_prop_window (dpyinfo)
   XUngrabServer (dpy);
 }
 
+enum {
+  SEEN_AA         = 0x01,
+  SEEN_HINTING    = 0x02,
+  SEEN_RGBA       = 0x04,
+  SEEN_LCDFILTER  = 0x08,
+  SEEN_HINTSTYLE  = 0x10,
+  SEEN_DPI        = 0x20,
+};
 struct xsettings 
 {
   FcBool aa, hinting;
   int rgba, lcdfilter, hintstyle;
   double dpi;
+
+  unsigned seen;
 };
 
 #define SWAP32(nr) (((nr) << 24) | (((nr) << 8) & 0xff0000)     \
@@ -184,6 +209,7 @@ struct xsettings
    2      CARD16        green
    2      CARD16        alpha
 
+   Returns non-zero if some Xft settings was seen, zero otherwise.
 */
 
 static int
@@ -281,11 +307,18 @@ parse_xft_settings (prop, bytes, settings)
         {
           ++settings_seen;
           if (strcmp (name, "Xft/Antialias") == 0)
-            settings->aa = ival != 0;
+            {
+              settings->seen |= SEEN_AA;
+              settings->aa = ival != 0;
+            }
           else if (strcmp (name, "Xft/Hinting") == 0)
-            settings->hinting = ival != 0;
+            {
+              settings->seen |= SEEN_HINTING;
+              settings->hinting = ival != 0;
+            }
           else if (strcmp (name, "Xft/HintStyle") == 0)
             {
+              settings->seen |= SEEN_HINTSTYLE;
               if (strcmp (sval, "hintnone") == 0)
                 settings->hintstyle = FC_HINT_NONE;
               else if (strcmp (sval, "hintslight") == 0)
@@ -294,9 +327,12 @@ parse_xft_settings (prop, bytes, settings)
                 settings->hintstyle = FC_HINT_MEDIUM;
               else if (strcmp (sval, "hintfull") == 0)
                 settings->hintstyle = FC_HINT_FULL;
+              else
+                settings->seen &= ~SEEN_HINTSTYLE;
             }
           else if (strcmp (name, "Xft/RGBA") == 0)
             {
+              settings->seen |= SEEN_RGBA;
               if (strcmp (sval, "none") == 0)
                 settings->rgba = FC_RGBA_NONE;
               else if (strcmp (sval, "rgb") == 0)
@@ -307,23 +343,28 @@ parse_xft_settings (prop, bytes, settings)
                 settings->rgba = FC_RGBA_VRGB;
               else if (strcmp (sval, "vbgr") == 0)
                 settings->rgba = FC_RGBA_VBGR;
+              else
+                settings->seen &= ~SEEN_RGBA;
             }
           else if (strcmp (name, "Xft/DPI") == 0)
-            settings->dpi = (double)ival/1024.0;
-#ifdef FC_LCD_FILTER
-          /* Older fontconfig versions don't have FC_LCD_FILTER. */
+            {
+              settings->seen |= SEEN_DPI;
+              settings->dpi = (double)ival/1024.0;
+            }
           else if (strcmp (name, "Xft/lcdfilter") == 0)
             {
+              settings->seen |= SEEN_LCDFILTER;
               if (strcmp (sval, "none") == 0)
                 settings->lcdfilter = FC_LCD_NONE;
               else if (strcmp (sval, "lcddefault") == 0)
                 settings->lcdfilter = FC_LCD_DEFAULT;
+              else
+                settings->seen &= ~SEEN_LCDFILTER;
             }
-#endif
         }
     }
 
-  return Success;
+  return settings_seen;
 }
 
 static int
@@ -355,9 +396,10 @@ read_xft_settings (dpyinfo, settings)
 
   x_uncatch_errors ();
 
-  return rc == Success;
+  return rc != 0;
 }
 
+
 static void
 apply_xft_settings (dpyinfo, send_event_p)
      struct x_display_info *dpyinfo;
@@ -366,12 +408,13 @@ apply_xft_settings (dpyinfo, send_event_p)
   FcPattern *pat;
   struct xsettings settings, oldsettings;
   int changed = 0;
+  char buf[256];
 
   if (!read_xft_settings (dpyinfo, &settings))
     return;
 
   memset (&oldsettings, 0, sizeof (oldsettings));
-
+  buf[0] = '\0';
   pat = FcPatternCreate ();
   XftDefaultSubstitute (dpyinfo->display,
                         XScreenNumberOfScreen (dpyinfo->screen),
@@ -379,54 +422,72 @@ apply_xft_settings (dpyinfo, send_event_p)
   FcPatternGetBool (pat, FC_ANTIALIAS, 0, &oldsettings.aa);
   FcPatternGetBool (pat, FC_HINTING, 0, &oldsettings.hinting);
   FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &oldsettings.hintstyle);
-#ifdef FC_LCD_FILTER
-  /* Older fontconfig versions don't have FC_LCD_FILTER. */
   FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &oldsettings.lcdfilter);
-#endif
   FcPatternGetInteger (pat, FC_RGBA, 0, &oldsettings.rgba);
   FcPatternGetDouble (pat, FC_DPI, 0, &oldsettings.dpi);
 
-  if (oldsettings.aa != settings.aa)
+  if ((settings.seen & SEEN_AA) != 0 && oldsettings.aa != settings.aa)
     {
       FcPatternDel (pat, FC_ANTIALIAS);
       FcPatternAddBool (pat, FC_ANTIALIAS, settings.aa);
       ++changed;
+      oldsettings.aa = settings.aa;
     }
-  if (oldsettings.hinting != settings.hinting)
+  sprintf (buf, "Antialias: %d", oldsettings.aa);
+
+  if ((settings.seen & SEEN_HINTING) != 0
+      && oldsettings.hinting != settings.hinting)
     {
       FcPatternDel (pat, FC_HINTING);
       FcPatternAddBool (pat, FC_HINTING, settings.hinting);
       ++changed;
+      oldsettings.hinting = settings.hinting;
     }
-  if (oldsettings.rgba != settings.rgba)
+  if (strlen (buf) > 0) strcat (buf, ", ");
+  sprintf (buf+strlen (buf), "Hinting: %d", oldsettings.hinting);
+  if ((settings.seen & SEEN_RGBA) != 0 && oldsettings.rgba != settings.rgba)
     {
       FcPatternDel (pat, FC_RGBA);
       FcPatternAddInteger (pat, FC_RGBA, settings.rgba);
+      oldsettings.rgba = settings.rgba;
       ++changed;
     }
-#ifdef FC_LCD_FILTER
+  if (strlen (buf) > 0) strcat (buf, ", ");
+  sprintf (buf+strlen (buf), "RGBA: %d", oldsettings.rgba);
+
   /* Older fontconfig versions don't have FC_LCD_FILTER. */
-  if (oldsettings.lcdfilter != settings.lcdfilter)
+  if ((settings.seen & SEEN_LCDFILTER) != 0
+      && oldsettings.lcdfilter != settings.lcdfilter)
     {
       FcPatternDel (pat, FC_LCD_FILTER);
       FcPatternAddInteger (pat, FC_LCD_FILTER, settings.lcdfilter);
       ++changed;
+      oldsettings.lcdfilter = settings.lcdfilter;
     }
-#endif
-  if (oldsettings.hintstyle != settings.hintstyle)
+  if (strlen (buf) > 0) strcat (buf, ", ");
+  sprintf (buf+strlen (buf), "LCDFilter: %d", oldsettings.lcdfilter);
+
+  if ((settings.seen & SEEN_HINTSTYLE) != 0
+      && oldsettings.hintstyle != settings.hintstyle)
     {
       FcPatternDel (pat, FC_HINT_STYLE);
       FcPatternAddInteger (pat, FC_HINT_STYLE, settings.hintstyle);
       ++changed;
+      oldsettings.hintstyle = settings.hintstyle;
     }
-  if (oldsettings.dpi != settings.dpi)
+  if (strlen (buf) > 0) strcat (buf, ", ");
+  sprintf (buf+strlen (buf), "Hintstyle: %d", oldsettings.hintstyle);
+
+  if ((settings.seen & SEEN_DPI) != 0 && oldsettings.dpi != settings.dpi
+      && settings.dpi > 0)
     {
       Lisp_Object frame, tail;
 
       FcPatternDel (pat, FC_DPI);
       FcPatternAddDouble (pat, FC_DPI, settings.dpi);
       ++changed;
-
+      oldsettings.dpi = settings.dpi;
+      
       /* Change the DPI on this display and all frames on the display.  */
       dpyinfo->resy = dpyinfo->resx = settings.dpi;
       FOR_EACH_FRAME (tail, frame)
@@ -435,12 +496,16 @@ apply_xft_settings (dpyinfo, send_event_p)
           XFRAME (frame)->resy = XFRAME (frame)->resx = settings.dpi;
     }
 
+  if (strlen (buf) > 0) strcat (buf, ", ");
+  sprintf (buf+strlen (buf), "DPI: %lf", oldsettings.dpi);
+
   if (changed)
     {
       XftDefaultSet (dpyinfo->display, pat);
       if (send_event_p)
         store_font_changed_event (Qfont_render,
                                   XCAR (dpyinfo->name_list_element));
+      Vxft_settings = make_string (buf, strlen (buf));
     }
   else
     FcPatternDestroy (pat);
@@ -494,27 +559,9 @@ xft_settings_event (dpyinfo, event)
 static void
 init_gconf ()
 {
-#ifdef HAVE_GCONF
+#if defined (HAVE_GCONF) && defined (HAVE_XFT)
   int i;
   char *s;
-  /* Should be enough, this is called at startup */
-#define N_FDS 1024
-  int fd_before[N_FDS], fd_before1[N_FDS];
-  int dummy, n_fds;
-  GPollFD gfds[N_FDS];
-
-  /* To find out which filedecriptors GConf uses, check before and after.
-     If we do not do this, GConf changes will only happen when Emacs gets
-     an X event.  */
-  memset (fd_before, 0, sizeof (fd_before));
-  n_fds = g_main_context_query (g_main_context_default (),
-                                G_PRIORITY_LOW,
-                                &dummy,
-                                gfds,
-                                N_FDS);
-  for (i = 0; i < n_fds; ++i)
-    if (gfds[i].fd < N_FDS && gfds[i].fd > 0 && gfds[i].events > 0)
-      fd_before[gfds[i].fd] = 1;
 
   g_type_init ();
   gconf_client = gconf_client_get_default ();
@@ -533,26 +580,7 @@ init_gconf ()
                            SYSTEM_MONO_FONT,
                            something_changedCB,
                            NULL, NULL, NULL);
-  n_fds = g_main_context_query (g_main_context_default (),
-                                G_PRIORITY_LOW,
-                                &dummy,
-                                gfds,
-                                N_FDS);
-
-  for (i = 0; i < n_fds; ++i)
-    if (gfds[i].fd < N_FDS && gfds[i].fd > 0 && gfds[i].events > 0
-        && !fd_before[gfds[i].fd])
-      {
-#ifdef F_SETOWN
-        fcntl (i, F_SETOWN, getpid ());
-#endif /* ! defined (F_SETOWN) */
-
-#ifdef SIGIO
-        if (interrupt_input)
-          init_sigio (i);
-#endif /* ! defined (SIGIO) */
-      }
-#endif /* HAVE_GCONF */
+#endif /* HAVE_GCONF && HAVE_XFT */
 }
 
 static void
@@ -601,13 +629,18 @@ xsettings_initialize (dpyinfo)
   init_xfd_settings (dpyinfo);
 }
 
+const char *
+xsettings_get_system_font ()
+{
+  return current_mono_font;
+}
 
 DEFUN ("font-get-system-font", Ffont_get_system_font, Sfont_get_system_font,
        0, 0, 0,
        doc: /* Get the system default monospaced font. */)
   ()
 {
-  return current_mono_font
+  return current_mono_font && use_system_font
     ? make_string (current_mono_font, strlen (current_mono_font))
     : Qnil;
 }
@@ -627,10 +660,21 @@ syms_of_xsettings ()
   staticpro (&Qfont_render);
   defsubr (&Sfont_get_system_font);
 
+  DEFVAR_BOOL ("font-use-system-font", &use_system_font,
+    doc: /* *Non-nil means to use the system defined font.  */);
+  use_system_font = 0;
+
+  DEFVAR_LISP ("xft-settings", &Vxft_settings,
+               doc: /* Font settings applied to Xft.  */);
+  Vxft_settings = make_string ("", 0);
+
+#ifdef HAVE_XFT
+  Fprovide (intern_c_string ("font-render-setting"), Qnil);
 #ifdef HAVE_GCONF
   Fprovide (intern_c_string ("system-font-setting"), Qnil);
 #endif
-#ifdef HAVE_XFT
-  Fprovide (intern_c_string ("font-render-setting"), Qnil);
 #endif
 }
+
+/* arch-tag: 541716ed-2e6b-42e1-8212-3197e01ea61d
+   (do not change this comment) */