diff options
| author | Ahmed Khanzada | 2025-10-25 22:34:11 -0700 |
|---|---|---|
| committer | Eli Zaretskii | 2025-11-02 08:01:41 +0200 |
| commit | dd9d1df4fa6c96acecaae94461d962da1d822494 (patch) | |
| tree | 6c7845a7ca1bb36bd424fe858a4fc26e8fa18668 /src | |
| parent | 0c6aee302154a0ee0a5f9db0675903dfa9516c9c (diff) | |
| download | emacs-dd9d1df4fa6c96acecaae94461d962da1d822494.tar.gz emacs-dd9d1df4fa6c96acecaae94461d962da1d822494.zip | |
Automatically toggle between dark and light mode PGTK widgets
* src/gtkutil.h: Declare 'xg_set_gtk_theme_dark_mode',
'xg_update_dark_mode_for_all_displays',
'xg_set_initial_dark_mode'.
* src/gtkutil.c (xg_set_gtk_theme_dark_mode): Toggle PGTK dark mode.
(xg_update_dark_mode_for_all_displays): Toggle PGTK dark mode for all
displays.
(xg_set_initial_dark_mode): Determine PGTK dark mode preference and set.
(xg_create_frame_widgets): Set PGTK dark mode preference for widgets.
(xg_create_frame_outer_widgets): Set PGTK dark mode preference for outer
widgets.
* src/xsettings.h: Declare 'xg_get_system_dark_mode'.
* src/xsettings.c (something_changed_gsettingsCB): Update PGTK dark mode
setting.
(xg_get_system_dark_mode): Determine PGTK dark mode preference.
GSETTINGS_COLOR_SCHEME: Defined and set to "color-scheme".
* etc/NEWS: Document automatic dark mode toggling.
(Bug#79689)
Diffstat (limited to 'src')
| -rw-r--r-- | src/gtkutil.c | 50 | ||||
| -rw-r--r-- | src/gtkutil.h | 3 | ||||
| -rw-r--r-- | src/xsettings.c | 46 | ||||
| -rw-r--r-- | src/xsettings.h | 1 |
4 files changed, 100 insertions, 0 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c index c192102730c..7664e20cc6d 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c | |||
| @@ -36,6 +36,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 36 | typedef struct x_output xp_output; | 36 | typedef struct x_output xp_output; |
| 37 | #else | 37 | #else |
| 38 | #define xp pgtk | 38 | #define xp pgtk |
| 39 | #include "xsettings.h" | ||
| 39 | typedef struct pgtk_output xp_output; | 40 | typedef struct pgtk_output xp_output; |
| 40 | #endif | 41 | #endif |
| 41 | #include "blockinput.h" | 42 | #include "blockinput.h" |
| @@ -1450,6 +1451,47 @@ xg_set_widget_bg (struct frame *f, GtkWidget *w, unsigned long pixel) | |||
| 1450 | #endif | 1451 | #endif |
| 1451 | } | 1452 | } |
| 1452 | 1453 | ||
| 1454 | /* Apply dark mode preference to GTK window decorations. */ | ||
| 1455 | |||
| 1456 | #ifdef HAVE_PGTK | ||
| 1457 | void | ||
| 1458 | xg_set_gtk_theme_dark_mode (bool dark_mode_p, GtkSettings *settings) | ||
| 1459 | { | ||
| 1460 | g_object_set (settings, "gtk-application-prefer-dark-theme", | ||
| 1461 | dark_mode_p ? TRUE : FALSE, NULL); | ||
| 1462 | } | ||
| 1463 | #endif | ||
| 1464 | |||
| 1465 | /* Update all frames' dark mode based on system setting. */ | ||
| 1466 | |||
| 1467 | #ifdef HAVE_PGTK | ||
| 1468 | void | ||
| 1469 | xg_update_dark_mode_for_all_displays (bool dark_mode_p) | ||
| 1470 | { | ||
| 1471 | struct pgtk_display_info *dpyinfo; | ||
| 1472 | for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) | ||
| 1473 | { | ||
| 1474 | GdkScreen *screen | ||
| 1475 | = gdk_display_get_default_screen (dpyinfo->gdpy); | ||
| 1476 | GtkSettings *settings | ||
| 1477 | = gtk_settings_get_for_screen (screen); | ||
| 1478 | xg_set_gtk_theme_dark_mode (dark_mode_p, settings); | ||
| 1479 | } | ||
| 1480 | } | ||
| 1481 | #endif | ||
| 1482 | |||
| 1483 | /* Set initial dark mode for a new frame (called during frame | ||
| 1484 | * creation). */ | ||
| 1485 | |||
| 1486 | #ifdef HAVE_PGTK | ||
| 1487 | void | ||
| 1488 | xg_set_initial_dark_mode (struct frame *f) | ||
| 1489 | { | ||
| 1490 | bool dark_mode_p = xg_get_system_dark_mode (); | ||
| 1491 | xg_update_dark_mode_for_all_displays (dark_mode_p); | ||
| 1492 | } | ||
| 1493 | #endif | ||
| 1494 | |||
| 1453 | /* Callback called when the gtk theme changes. | 1495 | /* Callback called when the gtk theme changes. |
| 1454 | We notify lisp code so it can fix faces used for region for example. */ | 1496 | We notify lisp code so it can fix faces used for region for example. */ |
| 1455 | 1497 | ||
| @@ -1769,6 +1811,10 @@ xg_create_frame_widgets (struct frame *f) | |||
| 1769 | } | 1811 | } |
| 1770 | } | 1812 | } |
| 1771 | 1813 | ||
| 1814 | #ifdef HAVE_PGTK | ||
| 1815 | xg_set_initial_dark_mode (f); | ||
| 1816 | #endif | ||
| 1817 | |||
| 1772 | unblock_input (); | 1818 | unblock_input (); |
| 1773 | 1819 | ||
| 1774 | return 1; | 1820 | return 1; |
| @@ -1872,6 +1918,10 @@ xg_create_frame_outer_widgets (struct frame *f) | |||
| 1872 | } | 1918 | } |
| 1873 | } | 1919 | } |
| 1874 | 1920 | ||
| 1921 | #ifdef HAVE_PGTK | ||
| 1922 | xg_set_initial_dark_mode (f); | ||
| 1923 | #endif | ||
| 1924 | |||
| 1875 | unblock_input (); | 1925 | unblock_input (); |
| 1876 | } | 1926 | } |
| 1877 | #endif | 1927 | #endif |
diff --git a/src/gtkutil.h b/src/gtkutil.h index 4aef66fedf4..cabf88da73f 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h | |||
| @@ -184,6 +184,9 @@ extern bool xg_check_special_colors (struct frame *f, | |||
| 184 | Emacs_Color *color); | 184 | Emacs_Color *color); |
| 185 | #ifdef HAVE_PGTK | 185 | #ifdef HAVE_PGTK |
| 186 | extern void xg_create_frame_outer_widgets (struct frame *f); | 186 | extern void xg_create_frame_outer_widgets (struct frame *f); |
| 187 | extern void xg_set_gtk_theme_dark_mode (bool dark_mode_p, GtkSettings *settings); | ||
| 188 | extern void xg_update_dark_mode_for_all_displays (bool dark_mode_p); | ||
| 189 | extern void xg_set_initial_dark_mode (struct frame *f); | ||
| 187 | #endif | 190 | #endif |
| 188 | 191 | ||
| 189 | #ifndef HAVE_PGTK | 192 | #ifndef HAVE_PGTK |
diff --git a/src/xsettings.c b/src/xsettings.c index 30b5ed258ae..72fd70b4b99 100644 --- a/src/xsettings.c +++ b/src/xsettings.c | |||
| @@ -227,6 +227,7 @@ static cairo_font_options_t *font_options; | |||
| 227 | #define GSETTINGS_FONT_ANTIALIASING "font-antialiasing" | 227 | #define GSETTINGS_FONT_ANTIALIASING "font-antialiasing" |
| 228 | #define GSETTINGS_FONT_RGBA_ORDER "font-rgba-order" | 228 | #define GSETTINGS_FONT_RGBA_ORDER "font-rgba-order" |
| 229 | #define GSETTINGS_FONT_HINTING "font-hinting" | 229 | #define GSETTINGS_FONT_HINTING "font-hinting" |
| 230 | #define GSETTINGS_COLOR_SCHEME "color-scheme" | ||
| 230 | #endif | 231 | #endif |
| 231 | 232 | ||
| 232 | /* The single GSettings instance, or NULL if not connected to GSettings. */ | 233 | /* The single GSettings instance, or NULL if not connected to GSettings. */ |
| @@ -448,6 +449,25 @@ something_changed_gsettingsCB (GSettings *settings, | |||
| 448 | apply_gsettings_font_rgba_order (settings); | 449 | apply_gsettings_font_rgba_order (settings); |
| 449 | store_font_options_changed (); | 450 | store_font_options_changed (); |
| 450 | } | 451 | } |
| 452 | else if (!strcmp (key, GSETTINGS_COLOR_SCHEME)) | ||
| 453 | { | ||
| 454 | if (xg_settings_key_valid_p (settings, GSETTINGS_COLOR_SCHEME)) | ||
| 455 | { | ||
| 456 | val = g_settings_get_value (settings, GSETTINGS_COLOR_SCHEME); | ||
| 457 | if (val) | ||
| 458 | { | ||
| 459 | g_variant_ref_sink (val); | ||
| 460 | if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING)) | ||
| 461 | { | ||
| 462 | const char *color_scheme = g_variant_get_string (val, NULL); | ||
| 463 | /* Check dark mode preference and update all frames. */ | ||
| 464 | bool dark_mode_p = (strstr (color_scheme, "dark") != NULL); | ||
| 465 | xg_update_dark_mode_for_all_displays (dark_mode_p); | ||
| 466 | } | ||
| 467 | g_variant_unref (val); | ||
| 468 | } | ||
| 469 | } | ||
| 470 | } | ||
| 451 | #endif /* HAVE_PGTK */ | 471 | #endif /* HAVE_PGTK */ |
| 452 | } | 472 | } |
| 453 | 473 | ||
| @@ -1109,6 +1129,32 @@ init_gsettings (void) | |||
| 1109 | #endif /* HAVE_GSETTINGS */ | 1129 | #endif /* HAVE_GSETTINGS */ |
| 1110 | } | 1130 | } |
| 1111 | 1131 | ||
| 1132 | /* Get current system dark mode state. */ | ||
| 1133 | |||
| 1134 | #ifdef HAVE_PGTK | ||
| 1135 | bool | ||
| 1136 | xg_get_system_dark_mode (void) | ||
| 1137 | { | ||
| 1138 | if (gsettings_client && xg_settings_key_valid_p (gsettings_client, GSETTINGS_COLOR_SCHEME)) | ||
| 1139 | { | ||
| 1140 | GVariant *val = g_settings_get_value (gsettings_client, GSETTINGS_COLOR_SCHEME); | ||
| 1141 | if (val) | ||
| 1142 | { | ||
| 1143 | g_variant_ref_sink (val); | ||
| 1144 | if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING)) | ||
| 1145 | { | ||
| 1146 | const char *color_scheme = g_variant_get_string (val, NULL); | ||
| 1147 | bool dark_mode_p = (strstr (color_scheme, "dark") != NULL); | ||
| 1148 | g_variant_unref (val); | ||
| 1149 | return dark_mode_p; | ||
| 1150 | } | ||
| 1151 | g_variant_unref (val); | ||
| 1152 | } | ||
| 1153 | } | ||
| 1154 | return false; | ||
| 1155 | } | ||
| 1156 | #endif | ||
| 1157 | |||
| 1112 | /* Init GConf and read startup values. */ | 1158 | /* Init GConf and read startup values. */ |
| 1113 | 1159 | ||
| 1114 | static void | 1160 | static void |
diff --git a/src/xsettings.h b/src/xsettings.h index 0234fbf043e..2bb8d0c7379 100644 --- a/src/xsettings.h +++ b/src/xsettings.h | |||
| @@ -45,6 +45,7 @@ extern const char *xsettings_get_system_normal_font (void); | |||
| 45 | 45 | ||
| 46 | #ifdef HAVE_PGTK | 46 | #ifdef HAVE_PGTK |
| 47 | extern cairo_font_options_t *xsettings_get_font_options (void); | 47 | extern cairo_font_options_t *xsettings_get_font_options (void); |
| 48 | extern bool xg_get_system_dark_mode (void); | ||
| 48 | #endif | 49 | #endif |
| 49 | 50 | ||
| 50 | #endif /* XSETTINGS_H */ | 51 | #endif /* XSETTINGS_H */ |