summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Kareh <[email protected]>2025-10-02 17:45:04 -0400
committerVictor Kareh <[email protected]>2025-10-03 18:49:42 +0000
commitee2adf9fcbe03f2b7d0afd62cefe0b77784f618a (patch)
tree99d9e0f784b85d4a8233c40504efe2272bc55e1a
parent87e3aadef2379c94ff6d47a6bc9c4d6006d334a9 (diff)
downloadmarco-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.c62
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)