summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Kareh <[email protected]>2025-10-02 16:34:25 -0400
committerLuke from DC <[email protected]>2025-10-06 21:07:51 +0000
commitf5c64ffdd4c6f84de21ea9208d5baa14e1649b23 (patch)
tree85c0310ec4d61a6afc514cb9ed1b7395bf8f1689
parent0be9e0492c9cfae8ef8552a71f4ba7f3d801f537 (diff)
downloadmate-panel-f5c64ffdd4c6f84de21ea9208d5baa14e1649b23.tar.bz2
mate-panel-f5c64ffdd4c6f84de21ea9208d5baa14e1649b23.tar.xz
panel-toplevel: Add dynamic HiDPI scale change support
Panels now respond to HiDPI scale factor changes without requiring a restart. When the monitors-changed signal is received, the panel updates its scale factor and forces applets to redraw at the new scale. The temporary size change (to 0 and back) is necessary because applets don't individually listen to scale change signals. This eliminates the need for mate-settings-daemon to kill and restart mate-panel when the scale factor changes.
-rw-r--r--mate-panel/panel-toplevel.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/mate-panel/panel-toplevel.c b/mate-panel/panel-toplevel.c
index bbe4980d..3892cfaf 100644
--- a/mate-panel/panel-toplevel.c
+++ b/mate-panel/panel-toplevel.c
@@ -260,6 +260,7 @@ static void panel_toplevel_update_monitor(PanelToplevel* toplevel);
static void panel_toplevel_set_monitor_internal(PanelToplevel* toplevel, int monitor, gboolean force_resize);
static void panel_toplevel_drag_threshold_changed (PanelToplevel *toplevel);
+static void panel_toplevel_on_monitors_changed (GdkScreen *screen, gpointer user_data);
static void
update_style_classes (PanelToplevel *toplevel)
@@ -3021,6 +3022,11 @@ panel_toplevel_realize (GtkWidget *widget)
if (visual == NULL)
visual = gdk_screen_get_system_visual (screen);
+ /* Connect to monitors-changed signal to handle dynamic HiDPI scale changes */
+ g_signal_connect (screen, "monitors-changed",
+ G_CALLBACK (panel_toplevel_on_monitors_changed),
+ toplevel);
+
gtk_widget_set_visual (widget, visual);
gtk_window_stick (GTK_WINDOW (widget));
gtk_window_set_decorated (GTK_WINDOW (widget), FALSE);
@@ -3066,7 +3072,15 @@ static void
panel_toplevel_unrealize (GtkWidget *widget)
{
PanelToplevel *toplevel;
+ GdkScreen *screen;
+
toplevel = PANEL_TOPLEVEL (widget);
+
+ screen = gtk_widget_get_screen (widget);
+ g_signal_handlers_disconnect_by_func (screen,
+ G_CALLBACK (panel_toplevel_on_monitors_changed),
+ toplevel);
+
panel_toplevel_disconnect_timeouts (toplevel);
panel_background_unrealized (&toplevel->background);
GTK_WIDGET_CLASS (panel_toplevel_parent_class)->unrealize (widget);
@@ -4054,6 +4068,63 @@ panel_toplevel_screen_changed (GtkWidget *widget,
gtk_widget_queue_resize (widget);
}
+static gboolean
+panel_toplevel_restore_size (gpointer user_data)
+{
+ PanelToplevel *toplevel = PANEL_TOPLEVEL (user_data);
+ int original_size;
+
+ /* Restore original size from GSettings */
+ if (toplevel->settings) {
+ original_size = g_settings_get_int (toplevel->settings, "size");
+ panel_toplevel_set_size (toplevel, original_size);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+panel_toplevel_update_applets_scale (gpointer user_data)
+{
+ PanelToplevel *toplevel = PANEL_TOPLEVEL (user_data);
+
+ /* HACK: Trigger all applets to redraw at the new scale by forcing
+ * a size change to 0 and then back to the configured size on the next
+ * cycle. This simulates what happens when you manually adjust the
+ * panel size via gsettings. Otherwise, every single applet would need
+ * to listen to their own scale change signal. */
+ panel_toplevel_set_size (toplevel, 0);
+
+ /* Use timeout to restore size after the resize completes.
+ * 100ms gives GTK enough time to complete the resize at the new scale. */
+ g_timeout_add (100, panel_toplevel_restore_size, toplevel);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+panel_toplevel_on_monitors_changed (GdkScreen *screen,
+ gpointer user_data)
+{
+ PanelToplevel *toplevel = PANEL_TOPLEVEL (user_data);
+ gint new_scale;
+
+ g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
+
+ /* Update scale factor */
+ new_scale = gtk_widget_get_scale_factor (GTK_WIDGET (toplevel));
+ if (new_scale != toplevel->priv->scale) {
+ toplevel->priv->scale = new_scale;
+
+ /* Queue resize to update panel size and layout at new scale first */
+ gtk_widget_queue_resize (GTK_WIDGET (toplevel));
+
+ /* Use timeout to update applets after panel resizes.
+ * 100ms gives GTK enough time to complete the resize at the new scale. */
+ g_timeout_add (100, panel_toplevel_update_applets_scale, toplevel);
+ }
+}
+
static void
panel_toplevel_set_property (GObject *object,
guint prop_id,