diff options
author | Victor Kareh <[email protected]> | 2025-10-02 17:45:04 -0400 |
---|---|---|
committer | Victor Kareh <[email protected]> | 2025-10-03 18:49:42 +0000 |
commit | ee2adf9fcbe03f2b7d0afd62cefe0b77784f618a (patch) | |
tree | 99d9e0f784b85d4a8233c40504efe2272bc55e1a | |
parent | 87e3aadef2379c94ff6d47a6bc9c4d6006d334a9 (diff) | |
download | marco-ee2adf9fcbe03f2b7d0afd62cefe0b77784f618a.tar.bz2 marco-ee2adf9fcbe03f2b7d0afd62cefe0b77784f618a.tar.xz |
screen: Add dynamic HiDPI scale change support
This allows marco to respond to HiDPI scale changes without requiring
a restart. When the scale changes, marco now automatically updates all
icons (windows, xprops, alt+tab, etc.) and mouse cursor to be at the
correct scale factor.
Window decorations are handled through an internal GDK signal triggered
from XSettings changes, and so already work out of the box.
-rw-r--r-- | src/core/screen.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/core/screen.c b/src/core/screen.c index 99e3fc39..6c61585e 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -65,6 +65,9 @@ static void set_workspace_names (MetaScreen *screen); static void prefs_changed_callback (MetaPreference pref, gpointer data); +static void on_monitors_changed (GdkScreen *gdk_screen, + gpointer user_data); + static void set_desktop_geometry_hint (MetaScreen *screen); static void set_desktop_viewport_hint (MetaScreen *screen); @@ -599,6 +602,10 @@ meta_screen_new (MetaDisplay *display, meta_prefs_add_listener (prefs_changed_callback, screen); + /* Connect to monitors-changed signal to handle dynamic HiDPI scale changes */ + g_signal_connect (gdk_display_get_default_screen (gdk_display_get_default ()), + "monitors-changed", G_CALLBACK (on_monitors_changed), screen); + #ifdef HAVE_STARTUP_NOTIFICATION screen->sn_context = sn_monitor_context_new (screen->display->sn_display, @@ -650,6 +657,9 @@ meta_screen_free (MetaScreen *screen, meta_prefs_remove_listener (prefs_changed_callback, screen); + g_signal_handlers_disconnect_by_func (gdk_display_get_default_screen (gdk_display_get_default ()), + G_CALLBACK (on_monitors_changed), screen); + meta_screen_ungrab_keys (screen); #ifdef HAVE_STARTUP_NOTIFICATION @@ -882,6 +892,58 @@ prefs_changed_callback (MetaPreference pref, } } +static void +on_monitors_changed (GdkScreen *gdk_screen, + gpointer user_data) +{ + MetaScreen *screen = user_data; + GSList *windows; + GSList *tmp; + + /* When monitors change (including HiDPI scale changes), update all window + * icons to render at the new scale. The icons are loaded at a specific pixel + * size based on meta_prefs_get_icon_size() which includes the scale factor, + * so we need to reload them when the scale changes. + */ + windows = meta_display_list_windows (screen->display); + + tmp = windows; + while (tmp != NULL) + { + MetaWindow *window = tmp->data; + + /* Only update icons for windows on this screen */ + if (window->screen == screen) + { + /* Invalidate the icon cache to force reload at new size */ + meta_icon_cache_invalidate (&window->icon_cache); + meta_window_update_icon_now (window); + } + + tmp = tmp->next; + } + + g_slist_free (windows); + + /* Update cursor size for new scale. meta_prefs_get_cursor_size() returns + * a scale-aware value, so this will reload cursors at the correct size. + */ + meta_display_set_cursor_theme (meta_prefs_get_cursor_theme (), + meta_prefs_get_cursor_size ()); + + /* Update the WM_ICON_SIZE hint so applications know the new preferred icon size */ + set_wm_icon_size_hint (screen); + + /* If there's an active tab popup, destroy it so it gets recreated with the + * new scaled icons next time Alt+Tab is pressed. + */ + if (screen->tab_popup) + { + meta_ui_tab_popup_free (screen->tab_popup); + screen->tab_popup = NULL; + } +} + static char* get_screen_name (MetaDisplay *display, int number) |