summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rwxr-xr-xconfigure118
-rw-r--r--configure.in12
-rw-r--r--etc/ChangeLog4
-rw-r--r--etc/NEWS12
-rw-r--r--lisp/ChangeLog10
-rw-r--r--lisp/Makefile.in1
-rw-r--r--lisp/font-setting.el109
-rw-r--r--lisp/loadup.el4
-rw-r--r--lisp/menu-bar.el10
-rw-r--r--src/ChangeLog51
-rw-r--r--src/Makefile.in18
-rw-r--r--src/config.in3
-rw-r--r--src/emacs.c3
-rw-r--r--src/font.c40
-rw-r--r--src/font.h2
-rw-r--r--src/frame.c3
-rw-r--r--src/ftfont.c97
-rw-r--r--src/keyboard.c17
-rw-r--r--src/lisp.h3
-rw-r--r--src/termhooks.h2
-rw-r--r--src/w32font.c5
-rw-r--r--src/xfns.c45
-rw-r--r--src/xfont.c4
-rw-r--r--src/xftfont.c54
-rw-r--r--src/xsettings.c627
-rw-r--r--src/xsettings.h29
-rw-r--r--src/xterm.c44
-rw-r--r--src/xterm.h4
29 files changed, 1288 insertions, 48 deletions
diff --git a/ChangeLog b/ChangeLog
index 316d5a84ee4..5b96dc43e9d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-11-17 Jan Djärv <jan.h.d@swipnet.se>
+
+ * configure.in: New option: --with(out)-gconf.
+ Set HAVE_GCONF if we find gconf.
+
2009-11-17 Glenn Morris <rgm@gnu.org>
* Makefile.in (INFO_FILES): Add semantic.
diff --git a/configure b/configure
index 01dd6f1cfbc..3f1b2bcde69 100755
--- a/configure
+++ b/configure
@@ -716,6 +716,8 @@ GTK_CFLAGS
GTK_LIBS
DBUS_CFLAGS
DBUS_LIBS
+GCONF_CFLAGS
+GCONF_LIBS
FONTCONFIG_CFLAGS
FONTCONFIG_LIBS
XFT_CFLAGS
@@ -791,6 +793,7 @@ with_xim
with_ns
with_gpm
with_dbus
+with_gconf
with_makeinfo
with_gtk
with_gcc
@@ -1499,6 +1502,7 @@ Optional Packages:
--without-gpm don't use -lgpm for mouse support on a GNU/Linux
console
--without-dbus don't compile with D-Bus support
+ --without-gconf don't compile with GConf support
--without-makeinfo don't require makeinfo for building manuals
--with-pkg-config-prog=PATH
@@ -2240,6 +2244,14 @@ else
fi
+# Check whether --with-gconf was given.
+if test "${with_gconf+set}" = set; then
+ withval=$with_gconf;
+else
+ with_gconf=yes
+fi
+
+
## For the times when you want to build Emacs but don't have
## a suitable makeinfo, and can live without the manuals.
@@ -12519,6 +12531,111 @@ done
fi
fi
+HAVE_GCONF=no
+if test "${with_gconf}" = "yes"; then
+
+ succeeded=no
+
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+ if test "$PKG_CONFIG" = "no" ; then
+ HAVE_GCONF=no
+ else
+ PKG_CONFIG_MIN_VERSION=0.9.0
+ if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
+ { $as_echo "$as_me:$LINENO: checking for gconf-2.0 >= 2.13" >&5
+$as_echo_n "checking for gconf-2.0 >= 2.13... " >&6; }
+
+ if $PKG_CONFIG --exists "gconf-2.0 >= 2.13" 2>&5; then
+ { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+ succeeded=yes
+
+ { $as_echo "$as_me:$LINENO: checking GCONF_CFLAGS" >&5
+$as_echo_n "checking GCONF_CFLAGS... " >&6; }
+ GCONF_CFLAGS=`$PKG_CONFIG --cflags "gconf-2.0 >= 2.13"|sed -e 's,///*,/,g'`
+ { $as_echo "$as_me:$LINENO: result: $GCONF_CFLAGS" >&5
+$as_echo "$GCONF_CFLAGS" >&6; }
+
+ { $as_echo "$as_me:$LINENO: checking GCONF_LIBS" >&5
+$as_echo_n "checking GCONF_LIBS... " >&6; }
+ GCONF_LIBS=`$PKG_CONFIG --libs "gconf-2.0 >= 2.13"|sed -e 's,///*,/,g'`
+ { $as_echo "$as_me:$LINENO: result: $GCONF_LIBS" >&5
+$as_echo "$GCONF_LIBS" >&6; }
+ else
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+ GCONF_CFLAGS=""
+ GCONF_LIBS=""
+ ## If we have a custom action on failure, don't print errors, but
+ ## do set a variable so people can do so.
+ GCONF_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gconf-2.0 >= 2.13"`
+
+ fi
+
+
+
+ else
+ echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
+ echo "*** See http://www.freedesktop.org/software/pkgconfig"
+ fi
+ fi
+
+ if test $succeeded = yes; then
+ HAVE_GCONF=yes
+ else
+ HAVE_GCONF=no
+ fi
+
+ if test "$HAVE_GCONF" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GCONF 1
+_ACEOF
+
+ fi
+fi
+
HAVE_XAW3D=no
if test x"${USE_X_TOOLKIT}" = xmaybe || test x"${USE_X_TOOLKIT}" = xLUCID; then
if test "$with_xaw3d" != no; then
@@ -25513,6 +25630,7 @@ echo " Does Emacs use -lpng? ${HAVE_PNG}"
echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}"
echo " Does Emacs use -lgpm? ${HAVE_GPM}"
echo " Does Emacs use -ldbus? ${HAVE_DBUS}"
+echo " Does Emacs use -lgconf? ${HAVE_GCONF}"
echo " Does Emacs use -lfreetype? ${HAVE_FREETYPE}"
echo " Does Emacs use -lm17n-flt? ${HAVE_M17N_FLT}"
diff --git a/configure.in b/configure.in
index c2f680106dc..d469cb13d44 100644
--- a/configure.in
+++ b/configure.in
@@ -144,6 +144,7 @@ OPTION_DEFAULT_OFF([ns],[use nextstep (Cocoa or GNUstep) windowing system])
OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console])
OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support])
+OPTION_DEFAULT_ON([gconf],[don't compile with GConf support])
## For the times when you want to build Emacs but don't have
## a suitable makeinfo, and can live without the manuals.
@@ -1739,6 +1740,16 @@ if test "${with_dbus}" = "yes"; then
fi
fi
+dnl GConf has been tested under GNU/Linux only.
+dnl The version is really arbitrary, it is about the same age as Gtk+ 2.6.
+HAVE_GCONF=no
+if test "${with_gconf}" = "yes"; then
+ PKG_CHECK_MODULES(GCONF, gconf-2.0 >= 2.13, HAVE_GCONF=yes, HAVE_GCONF=no)
+ if test "$HAVE_GCONF" = yes; then
+ AC_DEFINE(HAVE_GCONF, 1, [Define to 1 if using GConf.])
+ fi
+fi
+
dnl Do not put whitespace before the #include statements below.
dnl Older compilers (eg sunos4 cc) choke on it.
HAVE_XAW3D=no
@@ -2985,6 +2996,7 @@ echo " Does Emacs use -lpng? ${HAVE_PNG}"
echo " Does Emacs use -lrsvg-2? ${HAVE_RSVG}"
echo " Does Emacs use -lgpm? ${HAVE_GPM}"
echo " Does Emacs use -ldbus? ${HAVE_DBUS}"
+echo " Does Emacs use -lgconf? ${HAVE_GCONF}"
echo " Does Emacs use -lfreetype? ${HAVE_FREETYPE}"
echo " Does Emacs use -lm17n-flt? ${HAVE_M17N_FLT}"
diff --git a/etc/ChangeLog b/etc/ChangeLog
index 0752d6571b1..0b134576973 100644
--- a/etc/ChangeLog
+++ b/etc/ChangeLog
@@ -1,3 +1,7 @@
+2009-11-17 Jan Djärv <jan.h.d@swipnet.se>
+
+ * NEWS: Mention dynamic font changes (font-use-system-font).
+
2009-11-15 Carsten Dominik <dominik@u016822.science.uva.nl>
* refcards/orgcard.tex: Push version number to 6.33a.
diff --git a/etc/NEWS b/etc/NEWS
index 7fbb7d2b63e..aad0d2a3375 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -78,6 +78,18 @@ frame parameter fullscreen makes the Emacs frame maximized.
** The pointer now becomes invisible when typing.
Customize make-pointer-invisible to turn it off.
+** Emacs can use the system default monospaced font in Gnome.
+The use of the system default font can be turned on or off by customizing
+the variable 'font-use-system-font'. It is off by default.
+If the system default is changed, Emacs changes also.
+This requires that gconf-support is built in. If configure finds the
+gconf-libraries, that support is included. Gconf-support can be
+turned off with the configure option --without-gconf.
+
+** Emacs now reacts to Xft-changes made by configuration tools on X11.
+Changes to antialias, hinting, hintstyle, RGBA, DPI and lcdfilter are
+handeled. The XSETTINGS mechanism is used to implement this.
+
** Killing a buffer with a running process now asks for confirmation.
You can remove this query in two ways: either remove
`process-kill-buffer-query-function' from `kill-buffer-query-functions',
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 67add62f6ff..61f1b5d97ad 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,13 @@
+2009-11-17 Jan Djärv <jan.h.d@swipnet.se>
+
+ * menu-bar.el: Put "Use system font" in Option-menu.
+
+ * loadup.el: If feature system-font-setting or font-render-setting is
+ there, load font-setting.
+
+ * Makefile.in (ELCFILES): font-settings.el is new.
+ * font-setting.el: New file.
+
2009-11-17 Glenn Morris <rgm@gnu.org>
* vc-svn.el (vc-svn-print-log): Fix typo in previous.
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index ecd358840c5..3faa6a75647 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -680,6 +680,7 @@ ELCFILES = \
$(lisp)/follow.elc \
$(lisp)/font-core.elc \
$(lisp)/font-lock.elc \
+ $(lisp)/font-setting.elc \
$(lisp)/format-spec.elc \
$(lisp)/format.elc \
$(lisp)/forms.elc \
diff --git a/lisp/font-setting.el b/lisp/font-setting.el
new file mode 100644
index 00000000000..f426a141bbf
--- /dev/null
+++ b/lisp/font-setting.el
@@ -0,0 +1,109 @@
+;;; xsettings.el --- Support dynamic font changes
+
+;; Copyright (C) 2009 Free Software Foundation, Inc.
+
+;; Author: Jan Djärv <jan.h.d@swipnet.se>
+;; Maintainer: FSF
+;; Keywords: font, system-font
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file provides the lisp part of the GConf and XSetting code in
+;; xsetting.c. But it is nothing that prevents it from being used by
+;; other configuration schemes.
+
+;;; Code:
+
+;;; Customizable variables
+
+(defun font-setting-set-system-font (symbol value)
+ (set-default symbol value)
+ (if (symbol-value symbol)
+ (let ((f (selected-frame)))
+ (if (display-graphic-p f)
+ (font-setting-change-default-font f t)))))
+
+(defcustom font-use-system-font nil
+ "If non-nil, use the system monospaced font"
+ :version "23.2"
+ :type 'boolean
+ :group 'font-selection
+ :set 'font-setting-set-system-font)
+
+(declare-function font-get-system-font "xsettings.c" ())
+
+(defun font-setting-change-default-font (display-or-frame set-font)
+ "Change font and/or font settings for frames on display DISPLAY-OR-FRAME.
+If DISPLAY-OR-FRAME is a frame, the display is the one for that frame.
+
+If set-font is non-nil, change the font for frames. Otherwise re-apply the
+current form for the frame (i.e. hinting or somesuch changed)."
+
+ (let ((new-font (and (fboundp 'font-get-system-font)
+ (font-get-system-font))))
+ (when new-font
+ ;; Be careful here: when set-face-attribute is called for the
+ ;; :font attribute, Emacs tries to guess the best matching font
+ ;; by examining the other face attributes (Bug#2476).
+
+ (clear-font-cache)
+ ;; Set for current frames. Only change font for those that have
+ ;; the old font now. If they don't have the old font, the user
+ ;; probably changed it.
+ (dolist (f (frames-on-display-list display-or-frame))
+ (if (display-graphic-p f)
+ (let* ((frame-font
+ (or (font-get (face-attribute 'default :font f
+ 'default) :name)
+ (frame-parameter f 'font-parameter)))
+ (font-to-set
+ (if set-font new-font
+ ;; else set font again, hinting etc. may have changed.
+ frame-font)))
+ (progn
+ (set-frame-parameter f 'font-parameter font-to-set)
+ (set-face-attribute 'default f
+ :width 'normal
+ :weight 'normal
+ :slant 'normal
+ :font font-to-set)))))
+
+ ;; Set for future frames.
+ (set-face-attribute 'default t :font new-font)
+ (let ((spec (list (list t (face-attr-construct 'default)))))
+ (progn
+ (put 'default 'customized-face spec)
+ (custom-push-theme 'theme-face 'default 'user 'set spec)
+ (put 'default 'face-modified nil))))))
+
+(defun font-setting-handle-config-changed-event (event)
+ "Handle config-changed-event to change fonts on the display in EVENT.
+If `font-use-system-font' is nil, the font is not changed."
+ (interactive "e")
+ (let ((type (nth 1 event)) ;; font-name or font-render
+ (display-name (nth 2 event)))
+ (if (or (not (eq type 'font-name))
+ font-use-system-font)
+ (font-setting-change-default-font display-name
+ (eq type 'font-name)))))
+
+(if (or (featurep 'system-font-setting) (featurep 'font-render-setting))
+ (define-key special-event-map [config-changed-event]
+ 'font-setting-handle-config-changed-event))
+
+(provide 'font-setting)
diff --git a/lisp/loadup.el b/lisp/loadup.el
index e12d88447ca..dcb61378a98 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -198,6 +198,10 @@
(load "international/fontset")
(load "dnd")
(load "tool-bar")))
+
+(if (or (featurep 'system-font-setting) (featurep 'font-render-setting))
+ (load "font-setting"))
+
(if (featurep 'x)
(progn
(load "x-dnd")
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index 21495b32f5d..13319f41269 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -660,6 +660,8 @@ by \"Save Options\" in Custom buffers.")
(custom-push-theme 'theme-face 'default 'user 'set spec)
(put 'default 'face-modified nil))))
+
+
;;; Assemble all the top-level items of the "Options" menu
(define-key menu-bar-options-menu [customize]
`(menu-item ,(purecopy "Customize Emacs") ,menu-bar-custom-menu))
@@ -713,6 +715,14 @@ by \"Save Options\" in Custom buffers.")
:visible (display-multi-font-p)
:help ,(purecopy "Select a default font")))
+(if (featurep 'system-font-setting)
+ (define-key menu-bar-options-menu [menu-system-font]
+ (menu-bar-make-toggle toggle-use-system-font font-use-system-font
+ "Use system font"
+ "Use system font: %s"
+ "Use the monospaced font defined by the system")))
+
+
;; The "Show/Hide" submenu of menu "Options"
(defvar menu-bar-showhide-menu (make-sparse-keymap "Show/Hide"))
diff --git a/src/ChangeLog b/src/ChangeLog
index 0bc2ad403e7..c09d11d5ecf 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,54 @@
+2009-11-17 Jan Djärv <jan.h.d@swipnet.se>
+
+ * xterm.h (struct x_display_info): Add atoms and Window for xsettings.
+
+ * xterm.c (handle_one_xevent): Call xft_settings_event for
+ ClientMessage, PropertyNotify and DestroyNotify.
+ (x_term_init): If we have XFT, get DPI from Xft.dpi.
+ Call xsettings_initialize.
+
+ * xftfont.c (xftfont_fix_match): New function.
+ (xftfont_open): Call XftDefaultSubstitute before XftFontMatch.
+ Call xftfont_fix_match after XftFontMatch.
+
+ * xfont.c (xfont_driver): Initialize all members.
+
+ * xfns.c (x_default_font_parameter): Try font from Ffont_get_system_font.
+ Do not get font from x_default_parameter if we got one from
+ Ffont_get_system_font.
+ (Fx_select_font): Get the defaut font name from :name of FRAME_FONT (f).
+
+ * w32font.c (w32font_driver): Initialize all members.
+
+ * termhooks.h (enum event_kind): CONFIG_CHANGED_EVENT is new.
+
+ * lisp.h: Declare syms_of_xsettings.
+
+ * keyboard.c (kbd_buffer_get_event, make_lispy_event): Handle
+ CONFIG_CHANGED_EVENT.
+
+ * ftfont.c (ftfont_filter_properties): New function.
+
+ * frame.c (x_set_font): Remove unused variable lval.
+
+ * font.h (struct font_driver): filter_properties is new.
+
+ * font.c (font_put_extra): Don't return if val is nil, it means
+ boolean option is off.
+ (font_parse_fcname): Collect all extra properties in extra_props
+ and call filter_properties for all drivers with extra_props and
+ font as parameter.
+ (font_open_entity): Do not use cache, it does not pick up new fontconfig
+ settings like hinting.
+ (font_load_for_lface): If spec had a name in it, store it in entity.
+
+ * emacs.c (main): Call syms_of_xsettings
+
+ * config.in: HAVE_GCONF is new.
+
+ * Makefile.in (GCONF_CFLAGS, GCONF_LIBS): New variables for HAVE_GCONF.
+ xsettings.o is new.
+
2009-11-17 Kenichi Handa <handa@m17n.org>
* xdisp.c (x_produce_glyphs): Consider face-remapping when falling
diff --git a/src/Makefile.in b/src/Makefile.in
index 038689c6359..824381c812f 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -248,6 +248,11 @@ DBUS_LIBS = @DBUS_LIBS@
DBUS_OBJ = dbusbind.o
#endif
+#ifdef HAVE_GCONF
+GCONF_CFLAGS = @GCONF_CFLAGS@
+GCONF_LIBS = @GCONF_LIBS@
+#endif
+
/* DO NOT use -R. There is a special hack described in lastfile.c
which is used instead. Some initialized data areas are modified
at initial startup, then labeled as part of the text area when
@@ -261,7 +266,7 @@ DBUS_OBJ = dbusbind.o
/* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM
since it may have -I options that should override those two. */
-ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${DBUS_CFLAGS} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ @M17N_FLT_CFLAGS@ ${DEPFLAGS}
+ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${DBUS_CFLAGS} ${GCONF_CFLAGS} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ @M17N_FLT_CFLAGS@ ${DEPFLAGS}
ALL_OBJC_CFLAGS=$(ALL_CFLAGS) @GNU_OBJC_CFLAGS@
.SUFFIXES: .m
@@ -286,7 +291,8 @@ ALL_OBJC_CFLAGS=$(ALL_CFLAGS) @GNU_OBJC_CFLAGS@
#ifdef HAVE_X_WINDOWS
XMENU_OBJ = xmenu.o
-XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o xsmfns.o fringe.o image.o
+XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o xsmfns.o fringe.o image.o \
+ xsettings.o
#ifdef HAVE_MENUS
@@ -904,7 +910,7 @@ SOME_MACHINE_LISP = ../lisp/mouse.elc \
LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) $(DBUS_LIBS) \
LIBGPM LIBRESOLV LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \
- LIBS_DEBUG $(GETLOADAVG_LIBS) \
+ LIBS_DEBUG $(GETLOADAVG_LIBS) ${GCONF_LIBS} \
@FREETYPE_LIBS@ @FONTCONFIG_LIBS@ @LIBOTF_LIBS@ @M17N_FLT_LIBS@ \
$(GNULIB_VAR) LIB_MATH LIB_STANDARD $(GNULIB_VAR)
@@ -1212,7 +1218,7 @@ xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \
xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \
$(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \
character.h charset.h coding.h gtkutil.h lisp.h $(config_h) termhooks.h \
- fontset.h termchar.h font.h
+ fontset.h termchar.h font.h xsettings.h
xfont.o: dispextern.h xterm.h frame.h blockinput.h character.h charset.h \
font.h lisp.h $(config_h)
xftfont.o: dispextern.h xterm.h frame.h blockinput.h character.h charset.h \
@@ -1228,13 +1234,13 @@ xmenu.o: xmenu.c xterm.h termhooks.h window.h dispextern.h frame.h buffer.h \
xterm.o: xterm.c xterm.h termhooks.h termopts.h termchar.h window.h buffer.h \
dispextern.h frame.h disptab.h blockinput.h atimer.h systime.h syssignal.h \
keyboard.h emacs-icon.h character.h charset.h ccl.h fontset.h composite.h \
- coding.h process.h gtkutil.h font.h fontset.h lisp.h $(config_h)
+ coding.h process.h gtkutil.h font.h fontset.h lisp.h $(config_h) xsettings.h
xselect.o: xselect.c process.h dispextern.h frame.h xterm.h blockinput.h \
buffer.h atimer.h systime.h termhooks.h lisp.h $(config_h)
xrdb.o: xrdb.c lisp.h $(config_h) epaths.h
xsmfns.o: xsmfns.c lisp.h $(config_h) systime.h sysselect.h termhooks.h xterm.h \
lisp.h termopts.h
-
+xsettings.o: xterm.h xsettings.h lisp.h frame.h termhooks.h $(config_h)
/* The files of Lisp proper */
alloc.o: alloc.c process.h frame.h window.h buffer.h puresize.h syssignal.h keyboard.h \
diff --git a/src/config.in b/src/config.in
index 04b6de5714d..e7e1c9d0868 100644
--- a/src/config.in
+++ b/src/config.in
@@ -201,6 +201,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Define to 1 if you have the `gai_strerror' function. */
#undef HAVE_GAI_STRERROR
+/* Define to 1 if using GConf. */
+#undef HAVE_GCONF
+
/* Define to 1 if you have the `gdk_display_open' function. */
#undef HAVE_GDK_DISPLAY_OPEN
diff --git a/src/emacs.c b/src/emacs.c
index 4099a4f4795..d96b3a1daf1 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1669,6 +1669,7 @@ main (int argc, char **argv)
syms_of_xfns ();
syms_of_xmenu ();
syms_of_fontset ();
+ syms_of_xsettings ();
#ifdef HAVE_X_SM
syms_of_xsmfns ();
#endif
@@ -1749,7 +1750,7 @@ main (int argc, char **argv)
#endif
init_window ();
init_font ();
-
+
if (!initialized)
{
char *file;
diff --git a/src/font.c b/src/font.c
index bab3d9f821c..1c0a9dfb236 100644
--- a/src/font.c
+++ b/src/font.c
@@ -718,8 +718,6 @@ font_put_extra (font, prop, val)
{
Lisp_Object prev = Qnil;
- if (NILP (val))
- return val;
while (CONSP (extra)
&& NILP (Fstring_lessp (prop, XCAR (XCAR (extra)))))
prev = extra, extra = XCDR (extra);
@@ -1431,6 +1429,8 @@ font_parse_fcname (name, font)
if (family_end)
{
+ Lisp_Object extra_props = Qnil;
+
/* A fontconfig name with size and/or property data. */
if (family_end > name)
{
@@ -1504,13 +1504,25 @@ font_parse_fcname (name, font)
if (prop >= FONT_FOUNDRY_INDEX
&& prop < FONT_EXTRA_INDEX)
- ASET (font, prop, font_prop_validate (prop, Qnil, val));
- else
- Ffont_put (font, key, val);
+ ASET (font, prop, font_prop_validate (prop, Qnil, val));
+ else
+ {
+ extra_props = nconc2 (extra_props,
+ Fcons (Fcons (key, val), Qnil));
+ }
}
p = q;
}
}
+
+ if (! NILP (extra_props))
+ {
+ struct font_driver_list *driver_list = font_driver_list;
+ for ( ; driver_list; driver_list = driver_list->next)
+ if (driver_list->driver->filter_properties)
+ (*driver_list->driver->filter_properties) (font, extra_props);
+ }
+
}
else
{
@@ -2975,11 +2987,15 @@ font_open_entity (f, entity, pixel_size)
else if (CONSP (Vface_font_rescale_alist))
scaled_pixel_size = pixel_size * font_rescale_ratio (entity);
+#if 0
+ /* This doesn't work if you have changed hinting or any other parameter.
+ We need to make a new object in every case to be sure. */
for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist);
objlist = XCDR (objlist))
if (! NILP (AREF (XCAR (objlist), FONT_TYPE_INDEX))
&& XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size)
return XCAR (objlist);
+#endif
val = AREF (entity, FONT_TYPE_INDEX);
for (driver_list = f->font_driver_list;
@@ -3155,12 +3171,14 @@ font_clear_prop (attrs, prop)
if (! FONTP (font))
return;
+#if 0
if (! NILP (Ffont_get (font, QCname)))
{
font = Fcopy_font_spec (font);
font_put_extra (font, QCname, Qnil);
}
+#endif
if (NILP (AREF (font, prop))
&& prop != FONT_FAMILY_INDEX
&& prop != FONT_FOUNDRY_INDEX
@@ -3438,7 +3456,7 @@ font_find_for_lface (f, attrs, spec, c)
val = font_select_entity (frame, entities,
attrs, pixel_size, c);
if (! NILP (val))
- return val;
+ return val;
}
}
}
@@ -3500,7 +3518,7 @@ font_load_for_lface (f, attrs, spec)
FRAME_PTR f;
Lisp_Object *attrs, spec;
{
- Lisp_Object entity;
+ Lisp_Object entity, name;
entity = font_find_for_lface (f, attrs, spec, -1);
if (NILP (entity))
@@ -3512,7 +3530,13 @@ font_load_for_lface (f, attrs, spec)
if (NILP (entity))
return Qnil;
}
- return font_open_for_lface (f, entity, attrs, spec);
+ /* Don't loose the original name that was put in initially. We need
+ it to re-apply the font when font parameters (like hinting or dpi) have
+ changed. */
+ entity = font_open_for_lface (f, entity, attrs, spec);
+ name = Ffont_get (spec, QCname);
+ if (STRINGP (name)) font_put_extra (entity, QCname, name);
+ return entity;
}
diff --git a/src/font.h b/src/font.h
index 5726ffd319c..1a09df2558c 100644
--- a/src/font.h
+++ b/src/font.h
@@ -687,6 +687,8 @@ struct font_driver
the (N-1)th element of VARIATIONS. */
int (*get_variation_glyphs) P_ ((struct font *font,
int c, unsigned variations[256]));
+
+ void (*filter_properties) P_ ((Lisp_Object font, Lisp_Object properties));
};
diff --git a/src/frame.c b/src/frame.c
index 467f6bd1482..323bfc1c37d 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3359,7 +3359,7 @@ x_set_font (f, arg, oldval)
struct frame *f;
Lisp_Object arg, oldval;
{
- Lisp_Object frame, font_object, lval;
+ Lisp_Object frame, font_object;
int fontset = -1;
/* Set the frame parameter back to the old value because we may
@@ -3427,7 +3427,6 @@ x_set_font (f, arg, oldval)
if (! NILP (Fequal (font_object, oldval)))
return;
-
x_new_font (f, font_object, fontset);
store_frame_param (f, Qfont, arg);
/* Recalculate toolbar height. */
diff --git a/src/ftfont.c b/src/ftfont.c
index ed9cb6f19d2..4ba4712965f 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -86,6 +86,8 @@ static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object,
static Lisp_Object ftfont_lookup_cache P_ ((Lisp_Object,
enum ftfont_cache_for));
+static void ftfont_filter_properties P_ ((Lisp_Object font, Lisp_Object alist));
+
Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
#define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
@@ -545,10 +547,12 @@ struct font_driver ftfont_driver =
NULL, /* check */
#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
- ftfont_variation_glyphs
+ ftfont_variation_glyphs,
#else
- NULL
+ NULL,
#endif
+
+ ftfont_filter_properties, /* filter_properties */
};
extern Lisp_Object QCname;
@@ -2226,7 +2230,94 @@ ftfont_font_format (FcPattern *pattern, Lisp_Object filename)
return intern ("unknown");
}
-
+static const char *ftfont_booleans [] = {
+ ":antialias",
+ ":hinting",
+ ":verticallayout",
+ ":autohint",
+ ":globaladvance",
+ ":outline",
+ ":scalable",
+ ":minspace",
+ ":embolden",
+ NULL,
+};
+
+static const char *ftfont_non_booleans [] = {
+ ":family",
+ ":familylang",
+ ":style",
+ ":stylelang",
+ ":fullname",
+ ":fullnamelang",
+ ":slant",
+ ":weight",
+ ":size",
+ ":width",
+ ":aspect",
+ ":pixelsize",
+ ":spacing",
+ ":foundry",
+ ":hintstyle",
+ ":file",
+ ":index",
+ ":ftface",
+ ":rasterizer",
+ ":scale",
+ ":dpi",
+ ":rgba",
+ ":lcdfilter",
+ ":charset",
+ ":lang",
+ ":fontversion",
+ ":capability",
+ NULL,
+};
+
+static void
+ftfont_filter_properties (font, alist)
+ Lisp_Object font;
+ Lisp_Object alist;
+{
+ Lisp_Object it;
+ int i;
+
+ /* Set boolean values to Qt or Qnil */
+ for (i = 0; ftfont_booleans[i] != NULL; ++i)
+ for (it = alist; ! NILP (it); it = XCDR (it))
+ {
+ Lisp_Object key = XCAR (XCAR (it));
+ Lisp_Object val = XCDR (XCAR (it));
+ char *keystr = SDATA (SYMBOL_NAME (key));
+
+ if (strcmp (ftfont_booleans[i], keystr) == 0)
+ {
+ char *str = SYMBOLP (val) ? SDATA (SYMBOL_NAME (val)) : NULL;
+ if (INTEGERP (val)) str = XINT (val) != 0 ? "true" : "false";
+ if (str == NULL) str = "true";
+
+ val = Qt;
+ if (strcmp ("false", str) == 0 || strcmp ("False", str) == 0
+ || strcmp ("FALSE", str) == 0 || strcmp ("FcFalse", str) == 0
+ || strcmp ("off", str) == 0 || strcmp ("OFF", str) == 0
+ || strcmp ("Off", str) == 0)
+ val = Qnil;
+ Ffont_put (font, key, val);
+ }
+ }
+
+ for (i = 0; ftfont_non_booleans[i] != NULL; ++i)
+ for (it = alist; ! NILP (it); it = XCDR (it))
+ {
+ Lisp_Object key = XCAR (XCAR (it));
+ Lisp_Object val = XCDR (XCAR (it));
+ char *keystr = SDATA (SYMBOL_NAME (key));
+ if (strcmp (ftfont_non_booleans[i], keystr) == 0)
+ Ffont_put (font, key, val);
+ }
+}
+
+
void
syms_of_ftfont ()
{
diff --git a/src/keyboard.c b/src/keyboard.c
index 5ea4f350809..f15b7971c45 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -489,6 +489,8 @@ Lisp_Object Qsave_session;
#ifdef HAVE_DBUS
Lisp_Object Qdbus_event;
#endif
+Lisp_Object Qconfig_changed_event;
+
/* Lisp_Object Qmouse_movement; - also an event header */
/* Properties of event headers. */
@@ -4283,6 +4285,11 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
kbd_fetch_ptr = event + 1;
}
#endif
+ else if (event->kind == CONFIG_CHANGED_EVENT)
+ {
+ obj = make_lispy_event (event);
+ kbd_fetch_ptr = event + 1;
+ }
else
{
/* If this event is on a different frame, return a switch-frame this
@@ -6196,6 +6203,10 @@ make_lispy_event (event)
}
#endif /* HAVE_DBUS */
+ case CONFIG_CHANGED_EVENT:
+ return Fcons (Qconfig_changed_event,
+ Fcons (event->arg,
+ Fcons (event->frame_or_window, Qnil)));
#ifdef HAVE_GPM
case GPM_CLICK_EVENT:
{
@@ -11805,6 +11816,9 @@ syms_of_keyboard ()
staticpro (&Qdbus_event);
#endif
+ Qconfig_changed_event = intern_c_string ("config-changed-event");
+ staticpro (&Qconfig_changed_event);
+
Qmenu_enable = intern_c_string ("menu-enable");
staticpro (&Qmenu_enable);
QCenable = intern_c_string (":enable");
@@ -12547,6 +12561,9 @@ keys_of_keyboard ()
initial_define_lispy_key (Vspecial_event_map, "dbus-event",
"dbus-handle-event");
#endif
+
+ initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
+ "ignore");
}
/* Mark the pointers in the kboard objects.
diff --git a/src/lisp.h b/src/lisp.h
index 65c88dcfab7..01b2d61247e 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2643,6 +2643,9 @@ extern Lisp_Object safe_eval P_ ((Lisp_Object));
extern int pos_visible_p P_ ((struct window *, int, int *,
int *, int *, int *, int *, int *));
+/* Defined in xsettings.c */
+extern void syms_of_xsettings P_ ((void));
+
/* Defined in vm-limit.c. */
extern void memory_warnings P_ ((POINTER_TYPE *, void (*warnfun) ()));
diff --git a/src/termhooks.h b/src/termhooks.h
index bd9b4ec4575..33585e832a6 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -184,6 +184,8 @@ enum event_kind
, DBUS_EVENT
#endif
+ , CONFIG_CHANGED_EVENT
+
#ifdef WINDOWSNT
/* Generated when an APPCOMMAND event is received, in response to
Multimedia or Internet buttons on some keyboards.
diff --git a/src/w32font.c b/src/w32font.c
index 69462512ca3..b9ffea7cd30 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -2472,7 +2472,10 @@ struct font_driver w32font_driver =
NULL, /* otf_drive */
NULL, /* start_for_frame */
NULL, /* end_for_frame */
- NULL /* shape */
+ NULL, /* shape */
+ NULL, /* check */
+ NULL, /* get_variation_glyphs */
+ NULL, /* filter_properties */
};
diff --git a/src/xfns.c b/src/xfns.c
index 0a041a7dc9d..3d5a2a127d6 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -98,6 +98,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <Xm/FileSB.h>
#endif
+#include "xsettings.h"
+
#if !defined(NO_EDITRES)
#define HACK_EDITRES
extern void _XEditResCheckMessages ();
@@ -3025,13 +3027,19 @@ x_default_font_parameter (f, parms)
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
- RES_TYPE_STRING);
+ RES_TYPE_STRING);
Lisp_Object font;
+ int got_from_gconf = 0;
if (EQ (font_param, Qunbound))
- font_param = Qnil;
+ {
+ font_param = Qnil;
+ font_param = Ffont_get_system_font();
+ got_from_gconf = !NILP (font_param);
+ }
+
font = !NILP (font_param) ? font_param
: x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
-
+
if (! STRINGP (font))
{
char *names[]
@@ -3068,7 +3076,11 @@ x_default_font_parameter (f, parms)
we've applied the `default' face settings. */
x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil));
}
- x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
+
+ x_default_parameter (f, parms, Qfont, font,
+ got_from_gconf ? NULL : "font",
+ got_from_gconf ? NULL : "Font",
+ RES_TYPE_STRING);
}
@@ -5569,10 +5581,10 @@ If FRAME is omitted or nil, it defaults to the selected frame. */)
{
FRAME_PTR f = check_x_frame (frame);
char *name;
- Lisp_Object default_font, font = Qnil;
+ Lisp_Object font;
Lisp_Object font_param;
char *default_name = NULL;
- struct gcpro gcpro1;
+ struct gcpro gcpro1, gcpro2;
int count = SPECPDL_INDEX ();
check_x ();
@@ -5586,21 +5598,22 @@ If FRAME is omitted or nil, it defaults to the selected frame. */)
BLOCK_INPUT;
- GCPRO1(font_param);
- font_param = Fframe_parameter (frame, Qfont_param);
+ GCPRO2(font_param, font);
- if (x_last_font_name != NULL)
- default_name = x_last_font_name;
- else if (STRINGP (font_param))
+ XSETFONT (font, FRAME_FONT (f));
+ font_param = Ffont_get (font, intern_c_string (":name"));
+ if (STRINGP (font_param))
default_name = SDATA (font_param);
- else if (FONTP (default_font))
+ else
{
- XSETFONT (default_font, FRAME_FONT (f));
- default_name = alloca (256);
- if (font_unparse_gtkname (default_font, f, default_name, 256) < 0)
- default_name = NULL;
+ font_param = Fframe_parameter (frame, Qfont_param);
+ if (STRINGP (font_param))
+ default_name = SDATA (font_param);
}
+ if (default_name == NULL && x_last_font_name != NULL)
+ default_name = x_last_font_name;
+
name = xg_get_font_name (f, default_name);
if (name)
diff --git a/src/xfont.c b/src/xfont.c
index 36ac09fcb18..ab37350ddf6 100644
--- a/src/xfont.c
+++ b/src/xfont.c
@@ -151,7 +151,9 @@ struct font_driver xfont_driver =
xfont_text_extents,
xfont_draw,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- xfont_check
+ xfont_check,
+ NULL, /* get_variation_glyphs */
+ NULL, /* filter_properties */
};
extern Lisp_Object QCname;
diff --git a/src/xftfont.c b/src/xftfont.c
index e66b538fa15..6455c5f2c52 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -184,6 +184,53 @@ extern Lisp_Object QCantialias;
static FcChar8 ascii_printable[95];
+static void
+xftfont_fix_match (pat, match)
+ FcPattern *pat, *match;
+{
+ /* These values are not used for matching (except antialias), but for
+ rendering, so make sure they are carried over to the match.
+ We also put antialias here because most fonts are antialiased, so
+ the match will have antialias true. */
+
+ FcBool b = FcTrue;
+ int i;
+ double dpi;
+
+ FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
+ if (! b)
+ {
+ FcPatternDel (match, FC_ANTIALIAS);
+ FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
+ }
+ FcPatternGetBool (pat, FC_HINTING, 0, &b);
+ if (! b)
+ {
+ FcPatternDel (match, FC_HINTING);
+ FcPatternAddBool (match, FC_HINTING, FcFalse);
+ }
+ if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
+ {
+ FcPatternDel (match, FC_HINT_STYLE);
+ FcPatternAddInteger (match, FC_HINT_STYLE, i);
+ }
+ if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
+ {
+ FcPatternDel (match, FC_LCD_FILTER);
+ FcPatternAddInteger (match, FC_LCD_FILTER, i);
+ }
+ if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
+ {
+ FcPatternDel (match, FC_RGBA);
+ FcPatternAddInteger (match, FC_RGBA, i);
+ }
+ if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
+ {
+ FcPatternDel (match, FC_DPI);
+ FcPatternAddDouble (match, FC_DPI, dpi);
+ }
+}
+
static Lisp_Object
xftfont_open (f, entity, pixel_size)
FRAME_PTR f;
@@ -249,7 +296,7 @@ xftfont_open (f, entity, pixel_size)
key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
if (EQ (key, QCantialias))
- FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
+ FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
else if (EQ (key, QChinting))
FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
else if (EQ (key, QCautohint))
@@ -285,7 +332,12 @@ xftfont_open (f, entity, pixel_size)
int event_base, error_base;
XRenderQueryExtension (display, &event_base, &error_base);
}
+
+ /* Substitute in values from X resources and XftDefaultSet. */
+ XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
+ xftfont_fix_match (pat, match);
+
FcPatternDestroy (pat);
xftfont = XftFontOpenPattern (display, match);
if (!xftfont)
diff --git a/src/xsettings.c b/src/xsettings.c
new file mode 100644
index 00000000000..84e05a1898a
--- /dev/null
+++ b/src/xsettings.c
@@ -0,0 +1,627 @@
+/* Functions for handle font changes dynamically.
+ Copyright (C) 2009
+ Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include <setjmp.h>
+#include <fcntl.h>
+#include "lisp.h"
+#include "xterm.h"
+#include "xsettings.h"
+#include "frame.h"
+#include "blockinput.h"
+#include "termhooks.h"
+#include "termopts.h"
+
+#include <X11/Xproto.h>
+
+#ifdef HAVE_GCONF
+#include <gconf/gconf-client.h>
+#endif
+#ifdef HAVE_XFT
+#include <X11/Xft/Xft.h>
+#endif
+
+static char *current_mono_font;
+static struct x_display_info *first_dpyinfo;
+static Lisp_Object Qfont_name, Qfont_render;
+
+#ifdef HAVE_GCONF
+static GConfClient *gconf_client;
+#endif
+
+
+static void
+store_font_changed_event (arg, display_name)
+ Lisp_Object arg;
+ Lisp_Object display_name;
+{
+ struct input_event event;
+ EVENT_INIT (event);
+ event.kind = CONFIG_CHANGED_EVENT;
+ event.frame_or_window = display_name;
+ event.arg = arg;
+ kbd_buffer_store_event (&event);
+}
+
+#ifdef HAVE_GCONF
+
+#define SYSTEM_MONO_FONT "/desktop/gnome/interface/monospace_font_name"
+
+/* Callback called when something changed in GConf that we care about,
+ that is SYSTEM_MONO_FONT. */
+
+static void
+something_changedCB (client, cnxn_id, entry, user_data)
+ GConfClient *client;
+ guint cnxn_id;
+ GConfEntry *entry;
+ gpointer user_data;
+{
+ GConfValue *v = gconf_entry_get_value (entry);
+
+ if (!v) return;
+ if (v->type == GCONF_VALUE_STRING)
+ {
+ const char *value = gconf_value_get_string (v);
+ int i;
+ if (current_mono_font != NULL && strcmp (value, current_mono_font) == 0)
+ return; // No change.
+
+ xfree (current_mono_font);
+ current_mono_font = xstrdup (value);
+ }
+
+
+ if (first_dpyinfo != NULL)
+ {
+ /* Check if display still open */
+ struct x_display_info *dpyinfo;
+ int found = 0;
+ for (dpyinfo = x_display_list; !found && dpyinfo; dpyinfo = dpyinfo->next)
+ found = dpyinfo == first_dpyinfo;
+
+ if (found)
+ store_font_changed_event (Qfont_name,
+ XCAR (first_dpyinfo->name_list_element));
+ }
+}
+#endif /* HAVE_GCONF */
+
+#ifdef HAVE_XFT
+
+/* Find the window that contains the XSETTINGS property values. */
+
+static void
+get_prop_window (dpyinfo)
+ struct x_display_info *dpyinfo;
+{
+ Display *dpy = dpyinfo->display;
+
+ XGrabServer (dpy);
+ dpyinfo->xsettings_window = XGetSelectionOwner (dpy,
+ dpyinfo->Xatom_xsettings_sel);
+ if (dpyinfo->xsettings_window != None)
+ /* Select events so we can detect if window is deleted or if settings
+ are changed. */
+ XSelectInput (dpy, dpyinfo->xsettings_window,
+ PropertyChangeMask|StructureNotifyMask);
+
+ XUngrabServer (dpy);
+}
+
+struct xsettings
+{
+ FcBool aa, hinting;
+ int rgba, lcdfilter, hintstyle;
+ double dpi;
+};
+
+#define SWAP32(nr) (((nr) << 24) | (((nr) << 8) & 0xff0000) \
+ | (((nr) >> 8) & 0xff00) | ((nr) >> 24))
+#define SWAP16(nr) (((nr) << 8) | ((nr) >> 8))
+#define PAD(nr) (((nr) + 3) & ~3)
+
+/* Parse xsettings and extract those that deal with Xft.
+ See http://freedesktop.org/wiki/Specifications/XSettingsRegistry
+ and http://standards.freedesktop.org/xsettings-spec/xsettings-spec-0.5.html.
+
+ Layout of prop. First is a header:
+
+ bytes type what
+ ------------------------------------
+ 1 CARD8 byte-order
+ 3 unused
+ 4 CARD32 SERIAL
+ 4 CARD32 N_SETTINGS
+
+ Then N_SETTINGS records, with header:
+
+ bytes type what
+ ------------------------------------
+ 1 SETTING_TYPE type (0 = integer, 1 = string, 2 RGB color).
+ 1 unused
+ 2 CARD16 n == name-length
+ n STRING8 name
+ p unused, p=pad_to_even_4(n)
+ 4 CARD32 last-change-serial
+
+ and then the value, For string:
+
+ bytes type what
+ ------------------------------------
+ 4 CARD32 n = value-length
+ n STRING8 value
+ p unused, p=pad_to_even_4(n)
+
+ For integer:
+
+ bytes type what
+ ------------------------------------
+ 4 INT32 value
+
+ For RGB color:
+
+ bytes type what
+ ------------------------------------
+ 2 CARD16 red
+ 2 CARD16 blue
+ 2 CARD16 green
+ 2 CARD16 alpha
+
+*/
+
+static int
+parse_xft_settings (prop, bytes, settings)
+ unsigned char *prop;
+ unsigned long bytes;
+ struct xsettings *settings;
+{
+ Lisp_Object byteorder = Fbyteorder ();
+ int my_bo = XFASTINT (byteorder) == 'B' ? MSBFirst : LSBFirst;
+ int that_bo = prop[0];
+ CARD32 n_settings;
+ int bytes_parsed = 0;
+ int settings_seen = 0;
+ int i = 0;
+
+ /* First 4 bytes is a serial number, skip that. */
+
+ if (bytes < 12) return BadLength;
+ memcpy (&n_settings, prop+8, 4);
+ if (my_bo != that_bo) n_settings = SWAP32 (n_settings);
+ bytes_parsed = 12;
+
+ memset (settings, 0, sizeof (*settings));
+
+ while (bytes_parsed+4 < bytes && settings_seen < 6
+ && i < n_settings)
+ {
+ int type = prop[bytes_parsed++];
+ CARD16 nlen;
+ CARD32 vlen, ival = 0;
+ char name[128]; /* The names we are looking for are not this long. */
+ char sval[128]; /* The values we are looking for are not this long. */
+ int is_xft;
+ int to_cpy;
+
+ sval[0] = '\0';
+ ++i;
+ ++bytes_parsed; /* Padding */
+
+ memcpy (&nlen, prop+bytes_parsed, 2);
+ bytes_parsed += 2;
+ if (my_bo != that_bo) nlen = SWAP16 (nlen);
+ if (bytes_parsed+nlen > bytes) return BadLength;
+ to_cpy = nlen > 127 ? 127 : nlen;
+ memcpy (name, prop+bytes_parsed, to_cpy);
+ name[to_cpy] = '\0';
+
+ bytes_parsed += nlen;
+ bytes_parsed = PAD (bytes_parsed);
+
+ bytes_parsed += 4; /* Skip serial for this value */
+ if (bytes_parsed > bytes) return BadLength;
+
+ is_xft = nlen > 6 && strncmp (name, "Xft/", 4) == 0;
+
+ switch (type)
+ {
+ case 0: /* Integer */
+ if (bytes_parsed+4 > bytes) return BadLength;
+ if (is_xft)
+ {
+ memcpy (&ival, prop+bytes_parsed, 4);
+ if (my_bo != that_bo) ival = SWAP32 (ival);
+ }
+ bytes_parsed += 4;
+ break;
+
+ case 1: /* String */
+ if (bytes_parsed+4 > bytes) return BadLength;
+ memcpy (&vlen, prop+bytes_parsed, 4);
+ bytes_parsed += 4;
+ if (my_bo != that_bo) vlen = SWAP32 (vlen);
+ if (is_xft)
+ {
+ to_cpy = vlen > 127 ? 127 : vlen;
+ memcpy (sval, prop+bytes_parsed, to_cpy);
+ sval[to_cpy] = '\0';
+ }
+ bytes_parsed += vlen;
+ bytes_parsed = PAD (bytes_parsed);
+ break;
+
+ case 2: /* RGB value */
+ /* No need to parse this */
+ if (bytes_parsed+8 > bytes) return BadLength;
+ bytes_parsed += 8; /* 4 values (r, b, g, alpha), 2 bytes each. */
+ break;
+
+ default: /* Parse Error */
+ return BadValue;
+ }
+
+ if (is_xft)
+ {
+ ++settings_seen;
+ if (strcmp (name, "Xft/Antialias") == 0)
+ settings->aa = ival != 0;
+ else if (strcmp (name, "Xft/Hinting") == 0)
+ settings->hinting = ival != 0;
+ else if (strcmp (name, "Xft/HintStyle") == 0)
+ {
+ if (strcmp (sval, "hintnone") == 0)
+ settings->hintstyle = FC_HINT_NONE;
+ else if (strcmp (sval, "hintslight") == 0)
+ settings->hintstyle = FC_HINT_SLIGHT;
+ else if (strcmp (sval, "hintmedium") == 0)
+ settings->hintstyle = FC_HINT_MEDIUM;
+ else if (strcmp (sval, "hintfull") == 0)
+ settings->hintstyle = FC_HINT_FULL;
+ }
+ else if (strcmp (name, "Xft/RGBA") == 0)
+ {
+ if (strcmp (sval, "none") == 0)
+ settings->rgba = FC_RGBA_NONE;
+ else if (strcmp (sval, "rgb") == 0)
+ settings->rgba = FC_RGBA_RGB;
+ else if (strcmp (sval, "bgr") == 0)
+ settings->rgba = FC_RGBA_BGR;
+ else if (strcmp (sval, "vrgb") == 0)
+ settings->rgba = FC_RGBA_VRGB;
+ else if (strcmp (sval, "vbgr") == 0)
+ settings->rgba = FC_RGBA_VBGR;
+ }
+ else if (strcmp (name, "Xft/DPI") == 0)
+ settings->dpi = (double)ival/1024.0;
+ else if (strcmp (name, "Xft/lcdfilter") == 0)
+ {
+ if (strcmp (sval, "none") == 0)
+ settings->lcdfilter = FC_LCD_NONE;
+ else if (strcmp (sval, "lcddefault") == 0)
+ settings->lcdfilter = FC_LCD_DEFAULT;
+ }
+ }
+ }
+
+ return Success;
+}
+
+static int
+read_xft_settings (dpyinfo, settings)
+ struct x_display_info *dpyinfo;
+ struct xsettings *settings;
+{
+ long long_len;
+ Atom act_type;
+ int act_form;
+ unsigned long nitems, bytes_after;
+ unsigned char *prop = NULL;
+ Display *dpy = dpyinfo->display;
+ int rc;
+
+ x_catch_errors (dpy);
+ rc = XGetWindowProperty (dpy,
+ dpyinfo->xsettings_window,
+ dpyinfo->Xatom_xsettings_prop,
+ 0, LONG_MAX, False, AnyPropertyType,
+ &act_type, &act_form, &nitems, &bytes_after,
+ &prop);
+
+ if (rc == Success && prop != NULL && act_form == 8 && nitems > 0
+ && act_type == dpyinfo->Xatom_xsettings_prop)
+ rc = parse_xft_settings (prop, nitems, settings);
+
+ XFree (prop);
+
+ x_uncatch_errors ();
+
+ return rc == Success;
+}
+
+static void
+apply_xft_settings (dpyinfo, send_event_p)
+ struct x_display_info *dpyinfo;
+ int send_event_p;
+{
+ FcPattern *pat;
+ struct xsettings settings, oldsettings;
+ int changed = 0;
+
+ if (!read_xft_settings (dpyinfo, &settings))
+ return;
+
+ memset (&oldsettings, 0, sizeof (oldsettings));
+
+ pat = FcPatternCreate ();
+ XftDefaultSubstitute (dpyinfo->display,
+ XScreenNumberOfScreen (dpyinfo->screen),
+ pat);
+ FcPatternGetBool (pat, FC_ANTIALIAS, 0, &oldsettings.aa);
+ FcPatternGetBool (pat, FC_HINTING, 0, &oldsettings.hinting);
+ FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &oldsettings.hintstyle);
+ FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &oldsettings.lcdfilter);
+ FcPatternGetInteger (pat, FC_RGBA, 0, &oldsettings.rgba);
+ FcPatternGetDouble (pat, FC_DPI, 0, &oldsettings.dpi);
+
+ if (oldsettings.aa != settings.aa)
+ {
+ FcPatternDel (pat, FC_ANTIALIAS);
+ FcPatternAddBool (pat, FC_ANTIALIAS, settings.aa);
+ ++changed;
+ }
+ if (oldsettings.hinting != settings.hinting)
+ {
+ FcPatternDel (pat, FC_HINTING);
+ FcPatternAddBool (pat, FC_HINTING, settings.hinting);
+ ++changed;
+ }
+ if (oldsettings.rgba != settings.rgba)
+ {
+ FcPatternDel (pat, FC_RGBA);
+ FcPatternAddInteger (pat, FC_RGBA, settings.rgba);
+ ++changed;
+ }
+ if (oldsettings.lcdfilter != settings.lcdfilter)
+ {
+ FcPatternDel (pat, FC_LCD_FILTER);
+ FcPatternAddInteger (pat, FC_LCD_FILTER, settings.lcdfilter);
+ ++changed;
+ }
+ if (oldsettings.hintstyle != settings.hintstyle)
+ {
+ FcPatternDel (pat, FC_HINT_STYLE);
+ FcPatternAddInteger (pat, FC_HINT_STYLE, settings.hintstyle);
+ ++changed;
+ }
+ if (oldsettings.dpi != settings.dpi)
+ {
+ Lisp_Object frame, tail;
+
+ FcPatternDel (pat, FC_DPI);
+ FcPatternAddDouble (pat, FC_DPI, settings.dpi);
+ ++changed;
+
+ /* Change the DPI on this display and all frames on the display. */
+ dpyinfo->resy = dpyinfo->resx = settings.dpi;
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_X_P (XFRAME (frame))
+ && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
+ XFRAME (frame)->resy = XFRAME (frame)->resx = settings.dpi;
+ }
+
+ if (changed)
+ {
+ XftDefaultSet (dpyinfo->display, pat);
+ if (send_event_p)
+ store_font_changed_event (Qfont_render,
+ XCAR (dpyinfo->name_list_element));
+ }
+ else
+ FcPatternDestroy (pat);
+}
+
+#endif /* HAVE_XFT */
+
+void
+xft_settings_event (dpyinfo, event)
+ struct x_display_info *dpyinfo;
+ XEvent *event;
+{
+#ifdef HAVE_XFT
+ int check_window_p = 0;
+
+ switch (event->type)
+ {
+ case DestroyNotify:
+ if (dpyinfo->xsettings_window == event->xany.window)
+ check_window_p = 1;
+ break;
+
+ case ClientMessage:
+ if (event->xclient.message_type == dpyinfo->Xatom_xsettings_mgr
+ && event->xclient.data.l[1] == dpyinfo->Xatom_xsettings_sel
+ && event->xclient.window == dpyinfo->root_window)
+ check_window_p = 1;
+ break;
+
+ case PropertyNotify:
+ if (event->xproperty.window == dpyinfo->xsettings_window
+ && event->xproperty.state == PropertyNewValue
+ && event->xproperty.atom == dpyinfo->Xatom_xsettings_prop)
+ {
+ apply_xft_settings (dpyinfo, True);
+ }
+ break;
+ }
+
+ if (check_window_p)
+ {
+ dpyinfo->xsettings_window = None;
+ get_prop_window (dpyinfo);
+ if (dpyinfo->xsettings_window != None)
+ apply_xft_settings (dpyinfo, True);
+ }
+#endif /* HAVE_XFT */
+}
+
+
+static void
+init_gconf ()
+{
+#ifdef HAVE_GCONF
+ 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 ();
+ s = gconf_client_get_string (gconf_client, SYSTEM_MONO_FONT, NULL);
+ if (s)
+ {
+ current_mono_font = xstrdup (s);
+ g_free (s);
+ }
+ gconf_client_set_error_handling (gconf_client, GCONF_CLIENT_HANDLE_NONE);
+ gconf_client_add_dir (gconf_client,
+ SYSTEM_MONO_FONT,
+ GCONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+ gconf_client_notify_add (gconf_client,
+ 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 */
+}
+
+static void
+init_xfd_settings (dpyinfo)
+ struct x_display_info *dpyinfo;
+{
+#ifdef HAVE_XFT
+ char sel[64];
+ Display *dpy = dpyinfo->display;
+
+ BLOCK_INPUT;
+
+ sprintf (sel, "_XSETTINGS_S%d", XScreenNumberOfScreen (dpyinfo->screen));
+ dpyinfo->Xatom_xsettings_sel = XInternAtom (dpy, sel, False);
+ dpyinfo->Xatom_xsettings_prop = XInternAtom (dpy,
+ "_XSETTINGS_SETTINGS",
+ False);
+ dpyinfo->Xatom_xsettings_mgr = XInternAtom (dpy, "MANAGER", False);
+
+ /* Select events so we can detect client messages sent when selection
+ owner changes. */
+ XSelectInput (dpy, dpyinfo->root_window, StructureNotifyMask);
+
+ get_prop_window (dpyinfo);
+ if (dpyinfo->xsettings_window != None)
+ apply_xft_settings (dpyinfo, False);
+
+ UNBLOCK_INPUT;
+
+#else /* ! HAVE_XFT */
+
+ dpyinfo->Xatom_xsettings_sel = None;
+ dpyinfo->Xatom_xsettings_prop = None;
+ dpyinfo->Xatom_xsettings_mgr = None;
+ dpyinfo->xsettings_window = None;
+
+#endif /* ! HAVE_XFT */
+}
+
+void
+xsettings_initialize (dpyinfo)
+ struct x_display_info *dpyinfo;
+{
+ if (first_dpyinfo == NULL) first_dpyinfo = dpyinfo;
+ init_gconf ();
+ init_xfd_settings (dpyinfo);
+}
+
+
+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
+ ? make_string (current_mono_font, strlen (current_mono_font))
+ : Qnil;
+}
+
+void
+syms_of_xsettings ()
+{
+ current_mono_font = NULL;
+ first_dpyinfo = NULL;
+#ifdef HAVE_GCONF
+ gconf_client = NULL;
+#endif
+
+ Qfont_name = intern_c_string ("font-name");
+ staticpro (&Qfont_name);
+ Qfont_render = intern_c_string ("font-render");
+ staticpro (&Qfont_render);
+ defsubr (&Sfont_get_system_font);
+
+#ifdef HAVE_GCONF
+ Fprovide (intern_c_string ("system-font-setting"), Qnil);
+#endif
+#ifdef HAVE_XFT
+ Fprovide (intern_c_string ("font-render-setting"), Qnil);
+#endif
+}
diff --git a/src/xsettings.h b/src/xsettings.h
new file mode 100644
index 00000000000..f8d73db2ee0
--- /dev/null
+++ b/src/xsettings.h
@@ -0,0 +1,29 @@
+/* Functions for handle font changes dynamically.
+ Copyright (C) 2009
+ Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef XSETTINGS_H
+#define XSETTINGS_H
+
+extern Lisp_Object Ffont_get_system_font P_ ((void));
+extern void xsettings_initialize P_ ((struct x_display_info *dpyinfo));
+extern void xft_settings_event P_ ((struct x_display_info *dpyinfo,
+ XEvent *));
+
+
+#endif /* XSETTINGS_H */
diff --git a/src/xterm.c b/src/xterm.c
index 9936e98b1ed..3349dc05b95 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -86,6 +86,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "keymap.h"
#include "font.h"
#include "fontset.h"
+#include "xsettings.h"
#include "sysselect.h"
#ifdef USE_X_TOOLKIT
@@ -6026,6 +6027,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
goto done;
}
+ xft_settings_event (dpyinfo, &event);
+
f = x_any_window_to_frame (dpyinfo, event.xclient.window);
if (!f)
goto OTHER;
@@ -6088,6 +6091,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
x_handle_net_wm_state (f, &event.xproperty);
x_handle_property_notify (&event.xproperty);
+ xft_settings_event (dpyinfo, &event);
goto OTHER;
case ReparentNotify:
@@ -6991,6 +6995,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
}
goto OTHER;
+ case DestroyNotify:
+ xft_settings_event (dpyinfo, &event);
+ break;
+
default:
OTHER:
#ifdef USE_X_TOOLKIT
@@ -10300,17 +10308,33 @@ x_term_init (display_name, xrm_option, resource_name)
dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
dpyinfo->visual, AllocNone);
+#ifdef HAVE_XFT
{
- int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
- double pixels = DisplayHeight (dpyinfo->display, screen_number);
- double mm = DisplayHeightMM (dpyinfo->display, screen_number);
- /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
- dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
- pixels = DisplayWidth (dpyinfo->display, screen_number);
- mm = DisplayWidthMM (dpyinfo->display, screen_number);
- /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
- dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
+ /* If we are using Xft, check dpi value in X resources.
+ It is better we use it as well, since Xft will use it, as will all
+ Gnome applications. If our real DPI is smaller or larger than the
+ one Xft uses, our font will look smaller or larger than other
+ for other applications, even if it is the same font name (monospace-10
+ for example). */
+ char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
+ double d;
+ if (v != NULL && sscanf (v, "%lf", &d) == 1)
+ dpyinfo->resy = dpyinfo->resx = d;
}
+#endif
+
+ if (dpyinfo->resy < 1)
+ {
+ int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
+ double pixels = DisplayHeight (dpyinfo->display, screen_number);
+ double mm = DisplayHeightMM (dpyinfo->display, screen_number);
+ /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
+ dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
+ pixels = DisplayWidth (dpyinfo->display, screen_number);
+ mm = DisplayWidthMM (dpyinfo->display, screen_number);
+ /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
+ dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
+ }
dpyinfo->Xatom_wm_protocols
= XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
@@ -10415,6 +10439,8 @@ x_term_init (display_name, xrm_option, resource_name)
xim_initialize (dpyinfo, resource_name);
#endif
+ xsettings_initialize (dpyinfo);
+
#ifdef subprocesses
/* This is only needed for distinguishing keyboard and process input. */
if (connection != 0)
diff --git a/src/xterm.h b/src/xterm.h
index e76634d7d43..1ad2a097016 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -364,6 +364,10 @@ struct x_display_info
Atom Xatom_net_wm_state, Xatom_net_wm_state_fullscreen_atom,
Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert,
Xatom_net_wm_state_sticky;
+
+ /* XSettings atoms and windows. */
+ Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
+ Window xsettings_window;
};
#ifdef HAVE_X_I18N