1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-02-01 20:06:00 +00:00

Handle system default font and changing font parameters.

* 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.

* 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.

* NEWS: Mention dynamic font changes (font-use-system-font).

* configure.in: New option: --with(out)-gconf.
Set HAVE_GCONF if we find gconf.
This commit is contained in:
Jan Djärv 2009-11-17 08:21:23 +00:00
parent 77fd3e0c13
commit 637fa98808
29 changed files with 1288 additions and 48 deletions

View File

@ -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.

118
configure vendored
View File

@ -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}"

View File

@ -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}"

View File

@ -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.

View File

@ -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',

View File

@ -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.

View File

@ -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 \

109
lisp/font-setting.el Normal file
View File

@ -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)

View File

@ -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")

View File

@ -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"))

View File

@ -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

View File

@ -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 \

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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));
};

View File

@ -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. */

View File

@ -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 ()
{

View File

@ -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.

View File

@ -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) ()));

View File

@ -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.

View File

@ -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 */
};

View File

@ -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)

View File

@ -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;

View File

@ -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)

627
src/xsettings.c Normal file
View File

@ -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
}

29
src/xsettings.h Normal file
View File

@ -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 */

View File

@ -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)

View File

@ -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