This source file includes following definitions.
- store_config_changed_event
- dpyinfo_valid
- store_monospaced_changed
- store_font_name_changed
- map_tool_bar_style
- store_tool_bar_style_changed
- xg_settings_key_valid_p
- store_font_options_changed
- apply_gsettings_font_hinting
- apply_gsettings_font_antialias
- apply_gsettings_font_rgba_order
- something_changed_gsettingsCB
- something_changed_gconfCB
- get_prop_window
- parse_settings
- read_settings
- apply_xft_settings
- read_and_apply_settings
- xft_settings_event
- init_gsettings
- init_gconf
- init_xsettings
- xsettings_initialize
- xsettings_get_system_font
- xsettings_get_system_normal_font
- xsettings_get_font_options
- DEFUN
- DEFUN
- DEFUN
- syms_of_xsettings
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include <float.h>
23 #include <limits.h>
24 #include <fcntl.h>
25
26 #include <byteswap.h>
27
28 #include "lisp.h"
29 #ifndef HAVE_PGTK
30 #include "xterm.h"
31 #else
32 #include "gtkutil.h"
33 #endif
34 #include "xsettings.h"
35 #include "frame.h"
36 #include "keyboard.h"
37 #include "blockinput.h"
38 #include "termhooks.h"
39 #include "pdumper.h"
40
41 #ifndef HAVE_PGTK
42 #include <X11/Xproto.h>
43 #else
44 typedef unsigned short CARD16;
45 typedef unsigned int CARD32;
46 #endif
47
48 #ifdef HAVE_GSETTINGS
49 #include <glib-object.h>
50 #include <gio/gio.h>
51 #endif
52
53 #ifdef HAVE_GCONF
54 #include <gconf/gconf-client.h>
55 #endif
56
57 #ifdef USE_CAIRO
58 #include <fontconfig/fontconfig.h>
59 #include "ftfont.h"
60 #elif defined HAVE_XFT
61 #include <X11/Xft/Xft.h>
62 #endif
63
64 #if defined USE_CAIRO && defined CAIRO_HAS_FT_FONT
65 #include <cairo/cairo-ft.h>
66 #endif
67
68 static char *current_mono_font;
69 static char *current_font;
70 static Display_Info *first_dpyinfo;
71 static Lisp_Object current_tool_bar_style;
72
73
74
75 static void
76 store_config_changed_event (Lisp_Object arg, Lisp_Object display_name)
77 {
78 struct input_event event;
79 EVENT_INIT (event);
80 event.kind = CONFIG_CHANGED_EVENT;
81 event.frame_or_window = display_name;
82 event.arg = arg;
83 kbd_buffer_store_event (&event);
84 }
85
86
87 static bool
88 dpyinfo_valid (Display_Info *dpyinfo)
89 {
90 bool found = false;
91 if (dpyinfo != NULL)
92 {
93 Display_Info *d;
94 for (d = x_display_list; !found && d; d = d->next)
95 #ifndef HAVE_PGTK
96 found = d == dpyinfo && d->display == dpyinfo->display;
97 #else
98 found = d == dpyinfo && d->gdpy == dpyinfo->gdpy;
99 #endif
100 }
101 return found;
102 }
103
104
105
106 #if (defined USE_CAIRO || defined HAVE_XFT) && (defined HAVE_GSETTINGS || defined HAVE_GCONF)
107 static void
108 store_monospaced_changed (const char *newfont)
109 {
110 if (current_mono_font != NULL && strcmp (newfont, current_mono_font) == 0)
111 return;
112
113 dupstring (¤t_mono_font, newfont);
114
115 if (dpyinfo_valid (first_dpyinfo) && use_system_font)
116 {
117 store_config_changed_event (Qmonospace_font_name,
118 XCAR (first_dpyinfo->name_list_element));
119 }
120 }
121 #endif
122
123
124
125 #if defined USE_CAIRO || defined HAVE_XFT
126 static void
127 store_font_name_changed (const char *newfont)
128 {
129 if (current_font != NULL && strcmp (newfont, current_font) == 0)
130 return;
131
132 dupstring (¤t_font, newfont);
133
134 if (dpyinfo_valid (first_dpyinfo))
135 {
136 store_config_changed_event (Qfont_name,
137 XCAR (first_dpyinfo->name_list_element));
138 }
139 }
140 #endif
141
142
143
144
145 static Lisp_Object
146 map_tool_bar_style (const char *tool_bar_style)
147 {
148 Lisp_Object style = Qnil;
149 if (tool_bar_style)
150 {
151 if (strcmp (tool_bar_style, "both") == 0)
152 style = Qboth;
153 else if (strcmp (tool_bar_style, "both-horiz") == 0)
154 style = Qboth_horiz;
155 else if (strcmp (tool_bar_style, "icons") == 0)
156 style = Qimage;
157 else if (strcmp (tool_bar_style, "text") == 0)
158 style = Qtext;
159 }
160
161 return style;
162 }
163
164
165
166 static void
167 store_tool_bar_style_changed (const char *newstyle,
168 Display_Info *dpyinfo)
169 {
170 Lisp_Object style = map_tool_bar_style (newstyle);
171 if (EQ (current_tool_bar_style, style))
172 return;
173
174 current_tool_bar_style = style;
175 if (dpyinfo_valid (dpyinfo))
176 store_config_changed_event (Qtool_bar_style,
177 XCAR (dpyinfo->name_list_element));
178 }
179
180 #ifndef HAVE_PGTK
181 #if defined USE_CAIRO || defined HAVE_XFT
182 #define XSETTINGS_FONT_NAME "Gtk/FontName"
183 #endif
184 #define XSETTINGS_TOOL_BAR_STYLE "Gtk/ToolbarStyle"
185 #endif
186
187 enum {
188 SEEN_AA = 0x01,
189 SEEN_HINTING = 0x02,
190 SEEN_RGBA = 0x04,
191 SEEN_LCDFILTER = 0x08,
192 SEEN_HINTSTYLE = 0x10,
193 SEEN_DPI = 0x20,
194 SEEN_FONT = 0x40,
195 SEEN_TB_STYLE = 0x80
196 };
197 struct xsettings
198 {
199 #if defined USE_CAIRO || defined HAVE_XFT
200 FcBool aa, hinting;
201 int rgba, lcdfilter, hintstyle;
202 double dpi;
203
204 char *font;
205 #endif
206
207 char *tb_style;
208
209 unsigned seen;
210 };
211
212 #ifdef HAVE_PGTK
213
214 static cairo_font_options_t *font_options;
215 #endif
216
217 #ifdef HAVE_GSETTINGS
218 #define GSETTINGS_SCHEMA "org.gnome.desktop.interface"
219 #define GSETTINGS_TOOL_BAR_STYLE "toolbar-style"
220
221 #if defined USE_CAIRO || defined HAVE_XFT
222 #define GSETTINGS_MONO_FONT "monospace-font-name"
223 #define GSETTINGS_FONT_NAME "font-name"
224 #endif
225
226 #ifdef HAVE_PGTK
227 #define GSETTINGS_FONT_ANTIALIASING "font-antialiasing"
228 #define GSETTINGS_FONT_RGBA_ORDER "font-rgba-order"
229 #define GSETTINGS_FONT_HINTING "font-hinting"
230 #endif
231
232
233
234 static GSettings *gsettings_client;
235
236 #if defined HAVE_PGTK && defined HAVE_GSETTINGS
237
238 static bool
239 xg_settings_key_valid_p (GSettings *settings, const char *key)
240 {
241 #ifdef GLIB_VERSION_2_32
242 GSettingsSchema *schema;
243 bool rc;
244
245 g_object_get (G_OBJECT (settings),
246 "settings-schema", &schema,
247 NULL);
248
249 if (!schema)
250 return false;
251
252 rc = g_settings_schema_has_key (schema, key);
253 g_settings_schema_unref (schema);
254
255 return rc;
256 #else
257 return false;
258 #endif
259 }
260
261 #endif
262
263 #ifdef HAVE_PGTK
264
265 static void
266 store_font_options_changed (void)
267 {
268 if (dpyinfo_valid (first_dpyinfo))
269 store_config_changed_event (Qfont_render,
270 XCAR (first_dpyinfo->name_list_element));
271 }
272
273
274 static void
275 apply_gsettings_font_hinting (GSettings *settings)
276 {
277 GVariant *val;
278 const char *hinting;
279
280 if (!xg_settings_key_valid_p (settings, GSETTINGS_FONT_HINTING))
281 return;
282
283 val = g_settings_get_value (settings, GSETTINGS_FONT_HINTING);
284
285 if (val)
286 {
287 g_variant_ref_sink (val);
288
289 if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
290 {
291 hinting = g_variant_get_string (val, NULL);
292
293 if (!strcmp (hinting, "full"))
294 cairo_font_options_set_hint_style (font_options,
295 CAIRO_HINT_STYLE_FULL);
296 else if (!strcmp (hinting, "medium"))
297 cairo_font_options_set_hint_style (font_options,
298 CAIRO_HINT_STYLE_MEDIUM);
299 else if (!strcmp (hinting, "slight"))
300 cairo_font_options_set_hint_style (font_options,
301 CAIRO_HINT_STYLE_SLIGHT);
302 else if (!strcmp (hinting, "none"))
303 cairo_font_options_set_hint_style (font_options,
304 CAIRO_HINT_STYLE_NONE);
305 }
306 g_variant_unref (val);
307 }
308 }
309
310
311 static void
312 apply_gsettings_font_antialias (GSettings *settings)
313 {
314 GVariant *val;
315 const char *antialias;
316
317 if (!xg_settings_key_valid_p (settings, GSETTINGS_FONT_ANTIALIASING))
318 return;
319
320 val = g_settings_get_value (settings, GSETTINGS_FONT_ANTIALIASING);
321
322 if (val)
323 {
324 g_variant_ref_sink (val);
325 if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
326 {
327 antialias = g_variant_get_string (val, NULL);
328
329 if (!strcmp (antialias, "none"))
330 cairo_font_options_set_antialias (font_options,
331 CAIRO_ANTIALIAS_NONE);
332 else if (!strcmp (antialias, "grayscale"))
333 cairo_font_options_set_antialias (font_options,
334 CAIRO_ANTIALIAS_GRAY);
335 else if (!strcmp (antialias, "rgba"))
336 cairo_font_options_set_antialias (font_options,
337 CAIRO_ANTIALIAS_SUBPIXEL);
338 }
339 g_variant_unref (val);
340 }
341 }
342
343
344 static void
345 apply_gsettings_font_rgba_order (GSettings *settings)
346 {
347 GVariant *val;
348 const char *rgba_order;
349
350 if (!xg_settings_key_valid_p (settings, GSETTINGS_FONT_RGBA_ORDER))
351 return;
352
353 val = g_settings_get_value (settings,
354 GSETTINGS_FONT_RGBA_ORDER);
355
356 if (val)
357 {
358 g_variant_ref_sink (val);
359
360 if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
361 {
362 rgba_order = g_variant_get_string (val, NULL);
363
364 if (!strcmp (rgba_order, "rgb"))
365 cairo_font_options_set_subpixel_order (font_options,
366 CAIRO_SUBPIXEL_ORDER_RGB);
367 else if (!strcmp (rgba_order, "bgr"))
368 cairo_font_options_set_subpixel_order (font_options,
369 CAIRO_SUBPIXEL_ORDER_BGR);
370 else if (!strcmp (rgba_order, "vrgb"))
371 cairo_font_options_set_subpixel_order (font_options,
372 CAIRO_SUBPIXEL_ORDER_VRGB);
373 else if (!strcmp (rgba_order, "vbgr"))
374 cairo_font_options_set_subpixel_order (font_options,
375 CAIRO_SUBPIXEL_ORDER_VBGR);
376 }
377 g_variant_unref (val);
378 }
379 }
380 #endif
381
382
383
384 static void
385 something_changed_gsettingsCB (GSettings *settings,
386 gchar *key,
387 gpointer user_data)
388 {
389 GVariant *val;
390
391 if (strcmp (key, GSETTINGS_TOOL_BAR_STYLE) == 0)
392 {
393 val = g_settings_get_value (settings, GSETTINGS_TOOL_BAR_STYLE);
394 if (val)
395 {
396 g_variant_ref_sink (val);
397 if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
398 {
399 const gchar *newstyle = g_variant_get_string (val, NULL);
400 store_tool_bar_style_changed (newstyle, first_dpyinfo);
401 }
402 g_variant_unref (val);
403 }
404 }
405 #if defined USE_CAIRO || defined HAVE_XFT
406 else if (strcmp (key, GSETTINGS_MONO_FONT) == 0)
407 {
408 val = g_settings_get_value (settings, GSETTINGS_MONO_FONT);
409 if (val)
410 {
411 g_variant_ref_sink (val);
412 if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
413 {
414 const gchar *newfont = g_variant_get_string (val, NULL);
415 store_monospaced_changed (newfont);
416 }
417 g_variant_unref (val);
418 }
419 }
420 else if (strcmp (key, GSETTINGS_FONT_NAME) == 0)
421 {
422 val = g_settings_get_value (settings, GSETTINGS_FONT_NAME);
423 if (val)
424 {
425 g_variant_ref_sink (val);
426 if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
427 {
428 const gchar *newfont = g_variant_get_string (val, NULL);
429 store_font_name_changed (newfont);
430 }
431 g_variant_unref (val);
432 }
433 }
434 #endif
435 #ifdef HAVE_PGTK
436 else if (!strcmp (key, GSETTINGS_FONT_ANTIALIASING))
437 {
438 apply_gsettings_font_antialias (settings);
439 store_font_options_changed ();
440 }
441 else if (!strcmp (key, GSETTINGS_FONT_HINTING))
442 {
443 apply_gsettings_font_hinting (settings);
444 store_font_options_changed ();
445 }
446 else if (!strcmp (key, GSETTINGS_FONT_RGBA_ORDER))
447 {
448 apply_gsettings_font_rgba_order (settings);
449 store_font_options_changed ();
450 }
451 #endif
452 }
453
454 #endif
455
456 #ifdef HAVE_GCONF
457 #define GCONF_TOOL_BAR_STYLE "/desktop/gnome/interface/toolbar_style"
458 #if defined USE_CAIRO || defined HAVE_XFT
459 #define GCONF_MONO_FONT "/desktop/gnome/interface/monospace_font_name"
460 #define GCONF_FONT_NAME "/desktop/gnome/interface/font_name"
461 #endif
462
463
464
465 static GConfClient *gconf_client;
466
467
468
469 static void
470 something_changed_gconfCB (GConfClient *client,
471 guint cnxn_id,
472 GConfEntry *entry,
473 gpointer user_data)
474 {
475 GConfValue *v = gconf_entry_get_value (entry);
476 const char *key = gconf_entry_get_key (entry);
477
478 if (!v || v->type != GCONF_VALUE_STRING || ! key) return;
479 if (strcmp (key, GCONF_TOOL_BAR_STYLE) == 0)
480 {
481 const char *value = gconf_value_get_string (v);
482 store_tool_bar_style_changed (value, first_dpyinfo);
483 }
484 #if defined USE_CAIRO || defined HAVE_XFT
485 else if (strcmp (key, GCONF_MONO_FONT) == 0)
486 {
487 const char *value = gconf_value_get_string (v);
488 store_monospaced_changed (value);
489 }
490 else if (strcmp (key, GCONF_FONT_NAME) == 0)
491 {
492 const char *value = gconf_value_get_string (v);
493 store_font_name_changed (value);
494 }
495 #endif
496 }
497
498 #endif
499
500 #if defined USE_CAIRO || defined HAVE_XFT
501
502
503 #ifndef FC_LCD_NONE
504 #define FC_LCD_NONE 0
505 #endif
506 #ifndef FC_LCD_DEFAULT
507 #define FC_LCD_DEFAULT 1
508 #endif
509 #ifndef FC_LCD_FILTER
510 #define FC_LCD_FILTER "lcdfilter"
511 #endif
512
513 #endif
514
515 #ifndef HAVE_PGTK
516
517
518 static void
519 get_prop_window (Display_Info *dpyinfo)
520 {
521 Display *dpy = dpyinfo->display;
522
523 XGrabServer (dpy);
524 dpyinfo->xsettings_window = XGetSelectionOwner (dpy,
525 dpyinfo->Xatom_xsettings_sel);
526 if (dpyinfo->xsettings_window != None)
527
528
529 XSelectInput (dpy, dpyinfo->xsettings_window,
530 PropertyChangeMask|StructureNotifyMask);
531
532 XUngrabServer (dpy);
533 }
534 #endif
535
536 #ifndef HAVE_PGTK
537
538 #define PAD(nr) (((nr) + 3) & ~3)
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590 static int
591 parse_settings (unsigned char *prop,
592 unsigned long bytes,
593 struct xsettings *settings)
594 {
595 int int1 = 1;
596 int my_bo = *(char *) &int1 == 1 ? LSBFirst : MSBFirst;
597 int that_bo = prop[0];
598 CARD32 n_settings;
599 int bytes_parsed = 0;
600 int settings_seen = 0;
601 int i = 0;
602
603
604
605 if (bytes < 12) return settings_seen;
606 memcpy (&n_settings, prop+8, 4);
607 if (my_bo != that_bo) n_settings = bswap_32 (n_settings);
608 bytes_parsed = 12;
609
610 memset (settings, 0, sizeof (*settings));
611
612 while (bytes_parsed+4 < bytes && settings_seen < 7
613 && i < n_settings)
614 {
615 int type = prop[bytes_parsed++];
616 CARD16 nlen;
617 CARD32 vlen, ival = 0;
618 char name[128];
619 char sval[128];
620 bool want_this;
621 int to_cpy;
622
623 sval[0] = '\0';
624 ++i;
625 ++bytes_parsed;
626
627 memcpy (&nlen, prop+bytes_parsed, 2);
628 bytes_parsed += 2;
629 if (my_bo != that_bo) nlen = bswap_16 (nlen);
630 if (bytes_parsed + nlen > bytes) return settings_seen;
631 to_cpy = min (nlen, sizeof name - 1);
632 memcpy (name, prop+bytes_parsed, to_cpy);
633 name[to_cpy] = '\0';
634
635 bytes_parsed += nlen;
636 bytes_parsed = PAD (bytes_parsed);
637
638 bytes_parsed += 4;
639 if (bytes_parsed > bytes) return settings_seen;
640
641 want_this = strcmp (XSETTINGS_TOOL_BAR_STYLE, name) == 0;
642 #if defined USE_CAIRO || defined HAVE_XFT
643 if ((nlen > 6 && memcmp (name, "Xft/", 4) == 0)
644 || strcmp (XSETTINGS_FONT_NAME, name) == 0)
645 want_this = true;
646 #endif
647
648 switch (type)
649 {
650 case 0:
651 if (bytes_parsed + 4 > bytes) return settings_seen;
652 if (want_this)
653 {
654 memcpy (&ival, prop+bytes_parsed, 4);
655 if (my_bo != that_bo) ival = bswap_32 (ival);
656 }
657 bytes_parsed += 4;
658 break;
659
660 case 1:
661 if (bytes_parsed + 4 > bytes) return settings_seen;
662 memcpy (&vlen, prop+bytes_parsed, 4);
663 bytes_parsed += 4;
664 if (my_bo != that_bo) vlen = bswap_32 (vlen);
665 if (want_this)
666 {
667 to_cpy = min (vlen, sizeof sval - 1);
668 memcpy (sval, prop+bytes_parsed, to_cpy);
669 sval[to_cpy] = '\0';
670 }
671 bytes_parsed += vlen;
672 bytes_parsed = PAD (bytes_parsed);
673 break;
674
675 case 2:
676
677 if (bytes_parsed + 8 > bytes) return settings_seen;
678 bytes_parsed += 8;
679 break;
680
681 default:
682 return settings_seen;
683 }
684
685 if (want_this)
686 {
687 if (strcmp (name, XSETTINGS_TOOL_BAR_STYLE) == 0)
688 {
689 dupstring (&settings->tb_style, sval);
690 settings->seen |= SEEN_TB_STYLE;
691 }
692 #if defined USE_CAIRO || defined HAVE_XFT
693 else if (strcmp (name, XSETTINGS_FONT_NAME) == 0)
694 {
695 dupstring (&settings->font, sval);
696 settings->seen |= SEEN_FONT;
697 }
698 else if (strcmp (name, "Xft/Antialias") == 0)
699 {
700 settings->seen |= SEEN_AA;
701 settings->aa = ival != 0;
702 }
703 else if (strcmp (name, "Xft/Hinting") == 0)
704 {
705 settings->seen |= SEEN_HINTING;
706 settings->hinting = ival != 0;
707 }
708 # ifdef FC_HINT_STYLE
709 else if (strcmp (name, "Xft/HintStyle") == 0)
710 {
711 settings->seen |= SEEN_HINTSTYLE;
712 if (strcmp (sval, "hintnone") == 0)
713 settings->hintstyle = FC_HINT_NONE;
714 else if (strcmp (sval, "hintslight") == 0)
715 settings->hintstyle = FC_HINT_SLIGHT;
716 else if (strcmp (sval, "hintmedium") == 0)
717 settings->hintstyle = FC_HINT_MEDIUM;
718 else if (strcmp (sval, "hintfull") == 0)
719 settings->hintstyle = FC_HINT_FULL;
720 else
721 settings->seen &= ~SEEN_HINTSTYLE;
722 }
723 # endif
724 else if (strcmp (name, "Xft/RGBA") == 0)
725 {
726 settings->seen |= SEEN_RGBA;
727 if (strcmp (sval, "none") == 0)
728 settings->rgba = FC_RGBA_NONE;
729 else if (strcmp (sval, "rgb") == 0)
730 settings->rgba = FC_RGBA_RGB;
731 else if (strcmp (sval, "bgr") == 0)
732 settings->rgba = FC_RGBA_BGR;
733 else if (strcmp (sval, "vrgb") == 0)
734 settings->rgba = FC_RGBA_VRGB;
735 else if (strcmp (sval, "vbgr") == 0)
736 settings->rgba = FC_RGBA_VBGR;
737 else
738 settings->seen &= ~SEEN_RGBA;
739 }
740 else if (strcmp (name, "Xft/DPI") == 0 && ival != (CARD32) -1)
741 {
742 settings->seen |= SEEN_DPI;
743 settings->dpi = ival / 1024.0;
744 }
745 else if (strcmp (name, "Xft/lcdfilter") == 0)
746 {
747 settings->seen |= SEEN_LCDFILTER;
748 if (strcmp (sval, "none") == 0)
749 settings->lcdfilter = FC_LCD_NONE;
750 else if (strcmp (sval, "lcddefault") == 0)
751 settings->lcdfilter = FC_LCD_DEFAULT;
752 else
753 settings->seen &= ~SEEN_LCDFILTER;
754 }
755 #endif
756 else
757 want_this = false;
758 settings_seen += want_this;
759 }
760 }
761
762 return settings_seen;
763 }
764 #endif
765
766 #ifndef HAVE_PGTK
767
768
769
770
771 static bool
772 read_settings (Display_Info *dpyinfo, struct xsettings *settings)
773 {
774 Atom act_type;
775 int act_form;
776 unsigned long nitems, bytes_after;
777 unsigned char *prop = NULL;
778 Display *dpy = dpyinfo->display;
779 int rc;
780 bool got_settings = false;
781
782 x_catch_errors (dpy);
783 rc = XGetWindowProperty (dpy,
784 dpyinfo->xsettings_window,
785 dpyinfo->Xatom_xsettings_prop,
786 0, LONG_MAX, False, AnyPropertyType,
787 &act_type, &act_form, &nitems, &bytes_after,
788 &prop);
789
790 if (rc == Success && prop != NULL && act_form == 8 && nitems > 0
791 && act_type == dpyinfo->Xatom_xsettings_prop)
792 got_settings = parse_settings (prop, nitems, settings) != 0;
793
794 XFree (prop);
795
796 x_uncatch_errors ();
797
798 return got_settings;
799 }
800 #endif
801
802 #ifndef HAVE_PGTK
803
804
805
806 static void
807 apply_xft_settings (Display_Info *dpyinfo,
808 struct xsettings *settings)
809 {
810 #if defined HAVE_XFT \
811 || (defined USE_CAIRO && defined CAIRO_HAS_FC_FONT \
812 && defined CAIRO_HAS_FT_FONT)
813 FcPattern *pat;
814 struct xsettings oldsettings;
815 bool changed = false;
816 #ifndef HAVE_XFT
817 cairo_font_options_t *options;
818 #endif
819
820
821 memset (&oldsettings, 0, sizeof (oldsettings));
822 pat = FcPatternCreate ();
823 #ifdef HAVE_XFT
824 XftDefaultSubstitute (dpyinfo->display,
825 XScreenNumberOfScreen (dpyinfo->screen),
826 pat);
827 #else
828 FcConfigSubstitute (NULL, pat, FcMatchPattern);
829 options = cairo_font_options_create ();
830 ftcrfont_get_default_font_options (dpyinfo, options);
831 cairo_ft_font_options_substitute (options, pat);
832 cairo_font_options_destroy (options);
833 FcDefaultSubstitute (pat);
834 #endif
835 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &oldsettings.aa);
836 FcPatternGetBool (pat, FC_HINTING, 0, &oldsettings.hinting);
837 #ifdef FC_HINT_STYLE
838 FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &oldsettings.hintstyle);
839 #endif
840 FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &oldsettings.lcdfilter);
841 FcPatternGetInteger (pat, FC_RGBA, 0, &oldsettings.rgba);
842 FcPatternGetDouble (pat, FC_DPI, 0, &oldsettings.dpi);
843
844 if ((settings->seen & SEEN_AA) != 0 && oldsettings.aa != settings->aa)
845 {
846 FcPatternDel (pat, FC_ANTIALIAS);
847 FcPatternAddBool (pat, FC_ANTIALIAS, settings->aa);
848 changed = true;
849 oldsettings.aa = settings->aa;
850 }
851
852 if ((settings->seen & SEEN_HINTING) != 0
853 && oldsettings.hinting != settings->hinting)
854 {
855 FcPatternDel (pat, FC_HINTING);
856 FcPatternAddBool (pat, FC_HINTING, settings->hinting);
857 changed = true;
858 oldsettings.hinting = settings->hinting;
859 }
860 if ((settings->seen & SEEN_RGBA) != 0 && oldsettings.rgba != settings->rgba)
861 {
862 FcPatternDel (pat, FC_RGBA);
863 FcPatternAddInteger (pat, FC_RGBA, settings->rgba);
864 oldsettings.rgba = settings->rgba;
865 changed = true;
866 }
867
868
869 if ((settings->seen & SEEN_LCDFILTER) != 0
870 && oldsettings.lcdfilter != settings->lcdfilter)
871 {
872 FcPatternDel (pat, FC_LCD_FILTER);
873 FcPatternAddInteger (pat, FC_LCD_FILTER, settings->lcdfilter);
874 changed = true;
875 oldsettings.lcdfilter = settings->lcdfilter;
876 }
877
878 #ifdef FC_HINT_STYLE
879 if ((settings->seen & SEEN_HINTSTYLE) != 0
880 && oldsettings.hintstyle != settings->hintstyle)
881 {
882 FcPatternDel (pat, FC_HINT_STYLE);
883 FcPatternAddInteger (pat, FC_HINT_STYLE, settings->hintstyle);
884 changed = true;
885 oldsettings.hintstyle = settings->hintstyle;
886 }
887 #endif
888
889 #ifdef USE_CAIRO
890
891
892
893
894 oldsettings.dpi = dpyinfo->resx;
895 #endif
896
897 if ((settings->seen & SEEN_DPI) != 0
898 && settings->dpi > 0
899
900
901
902
903
904
905
906
907
908
909
910 && ((oldsettings.dpi >= settings->dpi
911 && (oldsettings.dpi - settings->dpi) > 2)
912 || ((settings->dpi > oldsettings.dpi)
913 && (settings->dpi - oldsettings.dpi) > 2)))
914 {
915 FcPatternDel (pat, FC_DPI);
916 FcPatternAddDouble (pat, FC_DPI, settings->dpi);
917 changed = true;
918 oldsettings.dpi = settings->dpi;
919
920
921
922 dpyinfo->resy = dpyinfo->resx = settings->dpi;
923 }
924
925 if (changed)
926 {
927 static char const format[] =
928 "Antialias: %d, Hinting: %d, RGBA: %d, LCDFilter: %d, "
929 "Hintstyle: %d, DPI: %f";
930 enum
931 {
932 d_formats = 5,
933 d_growth = INT_BUFSIZE_BOUND (int) - sizeof "%d",
934 lf_formats = 1,
935 max_f_integer_digits = DBL_MAX_10_EXP + 1,
936 f_precision = 6,
937 lf_growth = (sizeof "-." + max_f_integer_digits + f_precision
938 - sizeof "%f")
939 };
940 char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth];
941 #ifdef HAVE_XFT
942 XftDefaultSet (dpyinfo->display, pat);
943 #else
944 FcPatternDestroy (pat);
945 #endif
946 store_config_changed_event (Qfont_render,
947 XCAR (dpyinfo->name_list_element));
948 Vxft_settings
949 = make_formatted_string (buf, format,
950 oldsettings.aa, oldsettings.hinting,
951 oldsettings.rgba, oldsettings.lcdfilter,
952 oldsettings.hintstyle, oldsettings.dpi);
953
954 }
955 else
956 FcPatternDestroy (pat);
957 #endif
958 }
959 #endif
960
961 #ifndef HAVE_PGTK
962
963
964
965 static void
966 read_and_apply_settings (Display_Info *dpyinfo, bool send_event_p)
967 {
968 struct xsettings settings;
969
970 if (!read_settings (dpyinfo, &settings))
971 return;
972
973 apply_xft_settings (dpyinfo, &settings);
974 if (settings.seen & SEEN_TB_STYLE)
975 {
976 if (send_event_p)
977 store_tool_bar_style_changed (settings.tb_style, dpyinfo);
978 else
979 current_tool_bar_style = map_tool_bar_style (settings.tb_style);
980 xfree (settings.tb_style);
981 }
982 #if defined USE_CAIRO || defined HAVE_XFT
983 if (settings.seen & SEEN_FONT)
984 {
985 if (send_event_p)
986 store_font_name_changed (settings.font);
987 else
988 dupstring (¤t_font, settings.font);
989 xfree (settings.font);
990 }
991 #endif
992 }
993 #endif
994
995 #ifndef HAVE_PGTK
996
997
998
999 bool
1000 xft_settings_event (Display_Info *dpyinfo, const XEvent *event)
1001 {
1002 bool check_window_p = false, apply_settings_p = false;
1003
1004 switch (event->type)
1005 {
1006 case DestroyNotify:
1007 if (dpyinfo->xsettings_window == event->xany.window)
1008 check_window_p = true;
1009 break;
1010
1011 case ClientMessage:
1012 if (event->xclient.message_type == dpyinfo->Xatom_xsettings_mgr
1013 && event->xclient.data.l[1] == dpyinfo->Xatom_xsettings_sel
1014 && event->xclient.window == dpyinfo->root_window)
1015 check_window_p = true;
1016 break;
1017
1018 case PropertyNotify:
1019 if (event->xproperty.window == dpyinfo->xsettings_window
1020 && event->xproperty.state == PropertyNewValue
1021 && event->xproperty.atom == dpyinfo->Xatom_xsettings_prop)
1022 apply_settings_p = true;
1023 break;
1024 }
1025
1026
1027 if (check_window_p)
1028 {
1029 dpyinfo->xsettings_window = None;
1030 get_prop_window (dpyinfo);
1031 if (dpyinfo->xsettings_window != None)
1032 apply_settings_p = true;
1033 }
1034
1035 if (apply_settings_p)
1036 read_and_apply_settings (dpyinfo, true);
1037
1038 return check_window_p || apply_settings_p;
1039 }
1040 #endif
1041
1042
1043
1044 static void
1045 init_gsettings (void)
1046 {
1047 #ifdef HAVE_GSETTINGS
1048 GVariant *val;
1049 bool schema_found = false;
1050
1051 #if ! GLIB_CHECK_VERSION (2, 36, 0)
1052 g_type_init ();
1053 #endif
1054
1055 #if GLIB_CHECK_VERSION (2, 32, 0)
1056 {
1057 GSettingsSchema *sc = g_settings_schema_source_lookup
1058 (g_settings_schema_source_get_default (),
1059 GSETTINGS_SCHEMA,
1060 true);
1061 schema_found = sc != NULL;
1062 if (sc) g_settings_schema_unref (sc);
1063 }
1064 #else
1065 {
1066 const gchar *const *schemas = g_settings_list_schemas ();
1067 if (schemas == NULL) return;
1068 while (! schema_found && *schemas != NULL)
1069 schema_found = strcmp (*schemas++, GSETTINGS_SCHEMA) == 0;
1070 }
1071 #endif
1072 if (!schema_found) return;
1073
1074 gsettings_client = g_settings_new (GSETTINGS_SCHEMA);
1075 if (!gsettings_client) return;
1076 g_object_ref_sink (G_OBJECT (gsettings_client));
1077 g_signal_connect (G_OBJECT (gsettings_client), "changed",
1078 G_CALLBACK (something_changed_gsettingsCB), NULL);
1079
1080 val = g_settings_get_value (gsettings_client, GSETTINGS_TOOL_BAR_STYLE);
1081 if (val)
1082 {
1083 g_variant_ref_sink (val);
1084 if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
1085 current_tool_bar_style
1086 = map_tool_bar_style (g_variant_get_string (val, NULL));
1087 g_variant_unref (val);
1088 }
1089
1090 #if defined USE_CAIRO || defined HAVE_XFT
1091 val = g_settings_get_value (gsettings_client, GSETTINGS_MONO_FONT);
1092 if (val)
1093 {
1094 g_variant_ref_sink (val);
1095 if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
1096 dupstring (¤t_mono_font, g_variant_get_string (val, NULL));
1097 g_variant_unref (val);
1098 }
1099
1100 val = g_settings_get_value (gsettings_client, GSETTINGS_FONT_NAME);
1101 if (val)
1102 {
1103 g_variant_ref_sink (val);
1104 if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
1105 dupstring (¤t_font, g_variant_get_string (val, NULL));
1106 g_variant_unref (val);
1107 }
1108
1109
1110
1111 #ifdef HAVE_PGTK
1112 font_options = cairo_font_options_create ();
1113 apply_gsettings_font_antialias (gsettings_client);
1114 apply_gsettings_font_hinting (gsettings_client);
1115 apply_gsettings_font_rgba_order (gsettings_client);
1116 #endif
1117
1118 #endif
1119
1120 #endif
1121 }
1122
1123
1124
1125 static void
1126 init_gconf (void)
1127 {
1128 #if defined (HAVE_GCONF)
1129 char *s;
1130
1131 #if ! GLIB_CHECK_VERSION (2, 36, 0)
1132 g_type_init ();
1133 #endif
1134
1135 gconf_client = gconf_client_get_default ();
1136 gconf_client_set_error_handling (gconf_client, GCONF_CLIENT_HANDLE_NONE);
1137 gconf_client_add_dir (gconf_client,
1138 GCONF_TOOL_BAR_STYLE,
1139 GCONF_CLIENT_PRELOAD_ONELEVEL,
1140 NULL);
1141 gconf_client_notify_add (gconf_client,
1142 GCONF_TOOL_BAR_STYLE,
1143 something_changed_gconfCB,
1144 NULL, NULL, NULL);
1145
1146 s = gconf_client_get_string (gconf_client, GCONF_TOOL_BAR_STYLE, NULL);
1147 if (s)
1148 {
1149 current_tool_bar_style = map_tool_bar_style (s);
1150 g_free (s);
1151 }
1152
1153 #if defined USE_CAIRO || defined HAVE_XFT
1154 s = gconf_client_get_string (gconf_client, GCONF_MONO_FONT, NULL);
1155 if (s)
1156 {
1157 dupstring (¤t_mono_font, s);
1158 g_free (s);
1159 }
1160 s = gconf_client_get_string (gconf_client, GCONF_FONT_NAME, NULL);
1161 if (s)
1162 {
1163 dupstring (¤t_font, s);
1164 g_free (s);
1165 }
1166 gconf_client_add_dir (gconf_client,
1167 GCONF_MONO_FONT,
1168 GCONF_CLIENT_PRELOAD_ONELEVEL,
1169 NULL);
1170 gconf_client_notify_add (gconf_client,
1171 GCONF_MONO_FONT,
1172 something_changed_gconfCB,
1173 NULL, NULL, NULL);
1174 gconf_client_add_dir (gconf_client,
1175 GCONF_FONT_NAME,
1176 GCONF_CLIENT_PRELOAD_ONELEVEL,
1177 NULL);
1178 gconf_client_notify_add (gconf_client,
1179 GCONF_FONT_NAME,
1180 something_changed_gconfCB,
1181 NULL, NULL, NULL);
1182 #endif
1183 #endif
1184 }
1185
1186 #ifndef HAVE_PGTK
1187
1188
1189 static void
1190 init_xsettings (Display_Info *dpyinfo)
1191 {
1192 Display *dpy = dpyinfo->display;
1193
1194 block_input ();
1195
1196
1197
1198 XSelectInput (dpy, dpyinfo->root_window, StructureNotifyMask);
1199
1200 get_prop_window (dpyinfo);
1201 if (dpyinfo->xsettings_window != None)
1202 read_and_apply_settings (dpyinfo, false);
1203
1204 unblock_input ();
1205 }
1206 #endif
1207
1208 void
1209 xsettings_initialize (Display_Info *dpyinfo)
1210 {
1211 if (first_dpyinfo == NULL) first_dpyinfo = dpyinfo;
1212 init_gconf ();
1213 #ifndef HAVE_PGTK
1214 init_xsettings (dpyinfo);
1215 #endif
1216 init_gsettings ();
1217 }
1218
1219
1220
1221
1222 const char *
1223 xsettings_get_system_font (void)
1224 {
1225 return current_mono_font;
1226 }
1227
1228 #ifdef USE_LUCID
1229
1230
1231
1232 const char *
1233 xsettings_get_system_normal_font (void)
1234 {
1235 return current_font;
1236 }
1237 #endif
1238
1239 #ifdef HAVE_PGTK
1240
1241
1242
1243 cairo_font_options_t *
1244 xsettings_get_font_options (void)
1245 {
1246 if (font_options != NULL)
1247 return cairo_font_options_copy (font_options);
1248 else
1249
1250 return cairo_font_options_create ();
1251 }
1252 #endif
1253
1254 DEFUN ("font-get-system-normal-font", Ffont_get_system_normal_font,
1255 Sfont_get_system_normal_font,
1256 0, 0, 0,
1257 doc:
1258 )
1259 (void)
1260 {
1261 return current_font ? build_string (current_font) : Qnil;
1262 }
1263
1264 DEFUN ("font-get-system-font", Ffont_get_system_font, Sfont_get_system_font,
1265 0, 0, 0,
1266 doc:
1267 )
1268 (void)
1269 {
1270 return current_mono_font ? build_string (current_mono_font) : Qnil;
1271 }
1272
1273 DEFUN ("tool-bar-get-system-style", Ftool_bar_get_system_style,
1274 Stool_bar_get_system_style, 0, 0, 0,
1275 doc:
1276
1277 )
1278 (void)
1279 {
1280 if (EQ (Vtool_bar_style, Qimage)
1281 || EQ (Vtool_bar_style, Qtext)
1282 || EQ (Vtool_bar_style, Qboth)
1283 || EQ (Vtool_bar_style, Qboth_horiz)
1284 || EQ (Vtool_bar_style, Qtext_image_horiz))
1285 return Vtool_bar_style;
1286 if (!NILP (current_tool_bar_style))
1287 return current_tool_bar_style;
1288 return Qimage;
1289 }
1290
1291 void
1292 syms_of_xsettings (void)
1293 {
1294 current_mono_font = NULL;
1295 PDUMPER_IGNORE (current_mono_font);
1296 current_font = NULL;
1297 PDUMPER_IGNORE (current_font);
1298 first_dpyinfo = NULL;
1299 PDUMPER_IGNORE (first_dpyinfo);
1300 #ifdef HAVE_GSETTINGS
1301 gsettings_client = NULL;
1302 PDUMPER_IGNORE (gsettings_client);
1303 #endif
1304 #ifdef HAVE_GCONF
1305 gconf_client = NULL;
1306 PDUMPER_IGNORE (gconf_client);
1307 #endif
1308 #ifdef HAVE_PGTK
1309 font_options = NULL;
1310 PDUMPER_IGNORE (font_options);
1311 #endif
1312
1313 DEFSYM (Qmonospace_font_name, "monospace-font-name");
1314 DEFSYM (Qfont_name, "font-name");
1315 DEFSYM (Qfont_render, "font-render");
1316 DEFSYM (Qdynamic_setting, "dynamic-setting");
1317 DEFSYM (Qfont_render_setting, "font-render-setting");
1318 DEFSYM (Qsystem_font_setting, "system-font-setting");
1319
1320 defsubr (&Sfont_get_system_font);
1321 defsubr (&Sfont_get_system_normal_font);
1322
1323 DEFVAR_BOOL ("font-use-system-font", use_system_font,
1324 doc:
1325
1326
1327 );
1328 use_system_font = false;
1329
1330 DEFVAR_LISP ("xft-settings", Vxft_settings,
1331 doc: );
1332 Vxft_settings = empty_unibyte_string;
1333
1334 #if defined USE_CAIRO || defined HAVE_XFT
1335 Fprovide (Qfont_render_setting, Qnil);
1336 #if defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
1337 Fprovide (Qsystem_font_setting, Qnil);
1338 #endif
1339 #endif
1340
1341 current_tool_bar_style = Qnil;
1342 DEFSYM (Qtool_bar_style, "tool-bar-style");
1343 defsubr (&Stool_bar_get_system_style);
1344
1345 Fprovide (Qdynamic_setting, Qnil);
1346 }